From bb939520ee088eac9749e8f913526c8b6c22f978 Mon Sep 17 00:00:00 2001 From: Malte Reents Date: Sun, 19 May 2024 11:46:14 +0200 Subject: [PATCH] lcd folder --- src/lcd/dogm/HAL_LCD_class_defines.h | 136 + src/lcd/dogm/HAL_LCD_com_defines.h | 132 + src/lcd/dogm/dogm_Bootscreen.h | 540 ++ src/lcd/dogm/dogm_Statusscreen.h | 765 +++ src/lcd/dogm/fontdata/fontdata_6x9_marlin.h | 189 + src/lcd/dogm/fontdata/fontdata_ISO10646_1.h | 305 ++ src/lcd/dogm/fontdata/langdata.h | 23 + src/lcd/dogm/fontdata/langdata_an.h | 10 + src/lcd/dogm/fontdata/langdata_bg.h | 78 + src/lcd/dogm/fontdata/langdata_ca.h | 10 + src/lcd/dogm/fontdata/langdata_cz.h | 55 + src/lcd/dogm/fontdata/langdata_da.h | 10 + src/lcd/dogm/fontdata/langdata_de.h | 10 + src/lcd/dogm/fontdata/langdata_el.h | 91 + src/lcd/dogm/fontdata/langdata_el_CY.h | 91 + src/lcd/dogm/fontdata/langdata_en.h | 10 + src/lcd/dogm/fontdata/langdata_es.h | 10 + src/lcd/dogm/fontdata/langdata_eu.h | 10 + src/lcd/dogm/fontdata/langdata_fi.h | 10 + src/lcd/dogm/fontdata/langdata_fr.h | 10 + src/lcd/dogm/fontdata/langdata_gl.h | 10 + src/lcd/dogm/fontdata/langdata_hr.h | 33 + src/lcd/dogm/fontdata/langdata_hu.h | 16 + src/lcd/dogm/fontdata/langdata_it.h | 10 + src/lcd/dogm/fontdata/langdata_jp_kana.h | 112 + src/lcd/dogm/fontdata/langdata_ko_KR.h | 548 ++ src/lcd/dogm/fontdata/langdata_nl.h | 10 + src/lcd/dogm/fontdata/langdata_pl.h | 41 + src/lcd/dogm/fontdata/langdata_pt.h | 10 + src/lcd/dogm/fontdata/langdata_pt_br.h | 10 + src/lcd/dogm/fontdata/langdata_ro.h | 10 + src/lcd/dogm/fontdata/langdata_ru.h | 74 + src/lcd/dogm/fontdata/langdata_sk.h | 50 + src/lcd/dogm/fontdata/langdata_test.h | 232 + src/lcd/dogm/fontdata/langdata_tr.h | 28 + src/lcd/dogm/fontdata/langdata_uk.h | 86 + src/lcd/dogm/fontdata/langdata_vi.h | 228 + src/lcd/dogm/fontdata/langdata_zh_CN.h | 1824 +++++++ src/lcd/dogm/fontdata/langdata_zh_TW.h | 1522 ++++++ src/lcd/dogm/lcdprint_u8g.cpp | 56 + src/lcd/dogm/marlinui_DOGM.cpp | 754 +++ src/lcd/dogm/marlinui_DOGM.h | 234 + src/lcd/dogm/status/ammeter.h | 68 + src/lcd/dogm/status/bed.h | 138 + src/lcd/dogm/status/chamber.h | 89 + src/lcd/dogm/status/combined.h | 315 ++ src/lcd/dogm/status/cooler.h | 119 + src/lcd/dogm/status/cutter.h | 123 + src/lcd/dogm/status/fan.h | 443 ++ src/lcd/dogm/status/hotend.h | 759 +++ src/lcd/dogm/status_screen_DOGM.cpp | 1031 ++++ src/lcd/dogm/status_screen_lite_ST7920.cpp | 920 ++++ src/lcd/dogm/status_screen_lite_ST7920.h | 106 + .../u8g_dev_ssd1306_sh1106_128x64_I2C.cpp | 302 + src/lcd/dogm/u8g_dev_ssd1309_12864.cpp | 129 + src/lcd/dogm/u8g_dev_st7565_64128n_HAL.cpp | 241 + src/lcd/dogm/u8g_dev_st7920_128x64_HAL.cpp | 208 + .../dogm/u8g_dev_tft_upscale_from_128x64.cpp | 559 ++ src/lcd/dogm/u8g_dev_uc1701_mini12864_HAL.cpp | 213 + src/lcd/dogm/u8g_fontutf8.cpp | 315 ++ src/lcd/dogm/u8g_fontutf8.h | 40 + .../dogm/ultralcd_st7920_u8glib_rrd_AVR.cpp | 196 + src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.h | 53 + src/lcd/e3v2/README.md | 7 + src/lcd/e3v2/common/dwin_api.cpp | 471 ++ src/lcd/e3v2/common/dwin_api.h | 270 + src/lcd/e3v2/common/dwin_color.h | 44 + src/lcd/e3v2/common/dwin_font.h | 40 + src/lcd/e3v2/common/dwin_set.h | 147 + src/lcd/e3v2/common/encoder.cpp | 253 + src/lcd/e3v2/common/encoder.h | 111 + src/lcd/e3v2/creality/dwin.cpp | 4317 +++++++++++++++ src/lcd/e3v2/creality/dwin.h | 249 + src/lcd/e3v2/creality/dwin_lcd.cpp | 84 + src/lcd/e3v2/creality/dwin_lcd.h | 47 + src/lcd/e3v2/jyersui/README.md | 7 + src/lcd/e3v2/jyersui/dwin.cpp | 4848 +++++++++++++++++ src/lcd/e3v2/jyersui/dwin.h | 245 + src/lcd/e3v2/jyersui/dwin_lcd.cpp | 64 + src/lcd/e3v2/jyersui/dwin_lcd.h | 34 + src/lcd/e3v2/marlinui/dwin_lcd.cpp | 63 + src/lcd/e3v2/marlinui/dwin_lcd.h | 82 + src/lcd/e3v2/marlinui/dwin_string.cpp | 182 + src/lcd/e3v2/marlinui/dwin_string.h | 1050 ++++ src/lcd/e3v2/marlinui/lcdprint_dwin.cpp | 190 + src/lcd/e3v2/marlinui/lcdprint_dwin.h | 30 + src/lcd/e3v2/marlinui/marlinui_dwin.h | 146 + src/lcd/e3v2/marlinui/ui_common.cpp | 594 ++ src/lcd/e3v2/marlinui/ui_status_480x272.cpp | 474 ++ src/lcd/e3v2/proui/base64.hpp | 208 + src/lcd/e3v2/proui/bedlevel_tools.cpp | 286 + src/lcd/e3v2/proui/bedlevel_tools.h | 77 + src/lcd/e3v2/proui/dwin.cpp | 3875 +++++++++++++ src/lcd/e3v2/proui/dwin.h | 293 + src/lcd/e3v2/proui/dwin_defines.h | 122 + src/lcd/e3v2/proui/dwin_lcd.cpp | 160 + src/lcd/e3v2/proui/dwin_lcd.h | 76 + src/lcd/e3v2/proui/dwin_popup.cpp | 95 + src/lcd/e3v2/proui/dwin_popup.h | 73 + src/lcd/e3v2/proui/dwinui.cpp | 372 ++ src/lcd/e3v2/proui/dwinui.h | 562 ++ src/lcd/e3v2/proui/endstop_diag.cpp | 113 + src/lcd/e3v2/proui/endstop_diag.h | 37 + src/lcd/e3v2/proui/gcode_preview.cpp | 258 + src/lcd/e3v2/proui/gcode_preview.h | 27 + src/lcd/e3v2/proui/lockscreen.cpp | 80 + src/lcd/e3v2/proui/lockscreen.h | 46 + src/lcd/e3v2/proui/menus.cpp | 566 ++ src/lcd/e3v2/proui/menus.h | 188 + src/lcd/e3v2/proui/meshviewer.cpp | 144 + src/lcd/e3v2/proui/meshviewer.h | 40 + src/lcd/e3v2/proui/plot.cpp | 99 + src/lcd/e3v2/proui/plot.h | 54 + src/lcd/e3v2/proui/printstats.cpp | 82 + src/lcd/e3v2/proui/printstats.h | 39 + 115 files changed, 36781 insertions(+) create mode 100644 src/lcd/dogm/HAL_LCD_class_defines.h create mode 100644 src/lcd/dogm/HAL_LCD_com_defines.h create mode 100644 src/lcd/dogm/dogm_Bootscreen.h create mode 100644 src/lcd/dogm/dogm_Statusscreen.h create mode 100644 src/lcd/dogm/fontdata/fontdata_6x9_marlin.h create mode 100644 src/lcd/dogm/fontdata/fontdata_ISO10646_1.h create mode 100644 src/lcd/dogm/fontdata/langdata.h create mode 100644 src/lcd/dogm/fontdata/langdata_an.h create mode 100644 src/lcd/dogm/fontdata/langdata_bg.h create mode 100644 src/lcd/dogm/fontdata/langdata_ca.h create mode 100644 src/lcd/dogm/fontdata/langdata_cz.h create mode 100644 src/lcd/dogm/fontdata/langdata_da.h create mode 100644 src/lcd/dogm/fontdata/langdata_de.h create mode 100644 src/lcd/dogm/fontdata/langdata_el.h create mode 100644 src/lcd/dogm/fontdata/langdata_el_CY.h create mode 100644 src/lcd/dogm/fontdata/langdata_en.h create mode 100644 src/lcd/dogm/fontdata/langdata_es.h create mode 100644 src/lcd/dogm/fontdata/langdata_eu.h create mode 100644 src/lcd/dogm/fontdata/langdata_fi.h create mode 100644 src/lcd/dogm/fontdata/langdata_fr.h create mode 100644 src/lcd/dogm/fontdata/langdata_gl.h create mode 100644 src/lcd/dogm/fontdata/langdata_hr.h create mode 100644 src/lcd/dogm/fontdata/langdata_hu.h create mode 100644 src/lcd/dogm/fontdata/langdata_it.h create mode 100644 src/lcd/dogm/fontdata/langdata_jp_kana.h create mode 100644 src/lcd/dogm/fontdata/langdata_ko_KR.h create mode 100644 src/lcd/dogm/fontdata/langdata_nl.h create mode 100644 src/lcd/dogm/fontdata/langdata_pl.h create mode 100644 src/lcd/dogm/fontdata/langdata_pt.h create mode 100644 src/lcd/dogm/fontdata/langdata_pt_br.h create mode 100644 src/lcd/dogm/fontdata/langdata_ro.h create mode 100644 src/lcd/dogm/fontdata/langdata_ru.h create mode 100644 src/lcd/dogm/fontdata/langdata_sk.h create mode 100644 src/lcd/dogm/fontdata/langdata_test.h create mode 100644 src/lcd/dogm/fontdata/langdata_tr.h create mode 100644 src/lcd/dogm/fontdata/langdata_uk.h create mode 100644 src/lcd/dogm/fontdata/langdata_vi.h create mode 100644 src/lcd/dogm/fontdata/langdata_zh_CN.h create mode 100644 src/lcd/dogm/fontdata/langdata_zh_TW.h create mode 100644 src/lcd/dogm/lcdprint_u8g.cpp create mode 100644 src/lcd/dogm/marlinui_DOGM.cpp create mode 100644 src/lcd/dogm/marlinui_DOGM.h create mode 100644 src/lcd/dogm/status/ammeter.h create mode 100644 src/lcd/dogm/status/bed.h create mode 100644 src/lcd/dogm/status/chamber.h create mode 100644 src/lcd/dogm/status/combined.h create mode 100644 src/lcd/dogm/status/cooler.h create mode 100644 src/lcd/dogm/status/cutter.h create mode 100644 src/lcd/dogm/status/fan.h create mode 100644 src/lcd/dogm/status/hotend.h create mode 100644 src/lcd/dogm/status_screen_DOGM.cpp create mode 100644 src/lcd/dogm/status_screen_lite_ST7920.cpp create mode 100644 src/lcd/dogm/status_screen_lite_ST7920.h create mode 100644 src/lcd/dogm/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp create mode 100644 src/lcd/dogm/u8g_dev_ssd1309_12864.cpp create mode 100644 src/lcd/dogm/u8g_dev_st7565_64128n_HAL.cpp create mode 100644 src/lcd/dogm/u8g_dev_st7920_128x64_HAL.cpp create mode 100644 src/lcd/dogm/u8g_dev_tft_upscale_from_128x64.cpp create mode 100644 src/lcd/dogm/u8g_dev_uc1701_mini12864_HAL.cpp create mode 100644 src/lcd/dogm/u8g_fontutf8.cpp create mode 100644 src/lcd/dogm/u8g_fontutf8.h create mode 100644 src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.cpp create mode 100644 src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.h create mode 100644 src/lcd/e3v2/README.md create mode 100644 src/lcd/e3v2/common/dwin_api.cpp create mode 100644 src/lcd/e3v2/common/dwin_api.h create mode 100644 src/lcd/e3v2/common/dwin_color.h create mode 100644 src/lcd/e3v2/common/dwin_font.h create mode 100644 src/lcd/e3v2/common/dwin_set.h create mode 100644 src/lcd/e3v2/common/encoder.cpp create mode 100644 src/lcd/e3v2/common/encoder.h create mode 100644 src/lcd/e3v2/creality/dwin.cpp create mode 100644 src/lcd/e3v2/creality/dwin.h create mode 100644 src/lcd/e3v2/creality/dwin_lcd.cpp create mode 100644 src/lcd/e3v2/creality/dwin_lcd.h create mode 100644 src/lcd/e3v2/jyersui/README.md create mode 100644 src/lcd/e3v2/jyersui/dwin.cpp create mode 100644 src/lcd/e3v2/jyersui/dwin.h create mode 100644 src/lcd/e3v2/jyersui/dwin_lcd.cpp create mode 100644 src/lcd/e3v2/jyersui/dwin_lcd.h create mode 100644 src/lcd/e3v2/marlinui/dwin_lcd.cpp create mode 100644 src/lcd/e3v2/marlinui/dwin_lcd.h create mode 100644 src/lcd/e3v2/marlinui/dwin_string.cpp create mode 100644 src/lcd/e3v2/marlinui/dwin_string.h create mode 100644 src/lcd/e3v2/marlinui/lcdprint_dwin.cpp create mode 100644 src/lcd/e3v2/marlinui/lcdprint_dwin.h create mode 100644 src/lcd/e3v2/marlinui/marlinui_dwin.h create mode 100644 src/lcd/e3v2/marlinui/ui_common.cpp create mode 100644 src/lcd/e3v2/marlinui/ui_status_480x272.cpp create mode 100644 src/lcd/e3v2/proui/base64.hpp create mode 100644 src/lcd/e3v2/proui/bedlevel_tools.cpp create mode 100644 src/lcd/e3v2/proui/bedlevel_tools.h create mode 100644 src/lcd/e3v2/proui/dwin.cpp create mode 100644 src/lcd/e3v2/proui/dwin.h create mode 100644 src/lcd/e3v2/proui/dwin_defines.h create mode 100644 src/lcd/e3v2/proui/dwin_lcd.cpp create mode 100644 src/lcd/e3v2/proui/dwin_lcd.h create mode 100644 src/lcd/e3v2/proui/dwin_popup.cpp create mode 100644 src/lcd/e3v2/proui/dwin_popup.h create mode 100644 src/lcd/e3v2/proui/dwinui.cpp create mode 100644 src/lcd/e3v2/proui/dwinui.h create mode 100644 src/lcd/e3v2/proui/endstop_diag.cpp create mode 100644 src/lcd/e3v2/proui/endstop_diag.h create mode 100644 src/lcd/e3v2/proui/gcode_preview.cpp create mode 100644 src/lcd/e3v2/proui/gcode_preview.h create mode 100644 src/lcd/e3v2/proui/lockscreen.cpp create mode 100644 src/lcd/e3v2/proui/lockscreen.h create mode 100644 src/lcd/e3v2/proui/menus.cpp create mode 100644 src/lcd/e3v2/proui/menus.h create mode 100644 src/lcd/e3v2/proui/meshviewer.cpp create mode 100644 src/lcd/e3v2/proui/meshviewer.h create mode 100644 src/lcd/e3v2/proui/plot.cpp create mode 100644 src/lcd/e3v2/proui/plot.h create mode 100644 src/lcd/e3v2/proui/printstats.cpp create mode 100644 src/lcd/e3v2/proui/printstats.h diff --git a/src/lcd/dogm/HAL_LCD_class_defines.h b/src/lcd/dogm/HAL_LCD_class_defines.h new file mode 100644 index 0000000..28ca261 --- /dev/null +++ b/src/lcd/dogm/HAL_LCD_class_defines.h @@ -0,0 +1,136 @@ +/** + * 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 "../../inc/MarlinConfig.h" + +// use this file to create the public interface for device drivers that are NOT in the U8G library + +extern u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_sw_spi; +extern u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_hw_spi; + +class U8GLIB_64128N_2X_HAL : public U8GLIB { +public: + U8GLIB_64128N_2X_HAL() : U8GLIB() { } + U8GLIB_64128N_2X_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); } + U8GLIB_64128N_2X_HAL(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(cs, a0, reset); } + void init(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_st7565_64128n_HAL_2x_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset); + } + void init(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_st7565_64128n_HAL_2x_hw_spi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset); + } +}; + +extern u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_sw_spi; +extern u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_hw_spi; + +class U8GLIB_ST7920_128X64_4X_HAL : public U8GLIB { +public: + U8GLIB_ST7920_128X64_4X_HAL() : U8GLIB() { } + U8GLIB_ST7920_128X64_4X_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, reset); } + U8GLIB_ST7920_128X64_4X_HAL(pin_t cs, pin_t reset = U8G_PIN_NONE) { init(cs, reset); } + void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_st7920_128x64_HAL_4x_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); // a0 = U8G_PIN_NONE + } + void init(pin_t cs, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_st7920_128x64_HAL_4x_hw_spi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); // a0 = U8G_PIN_NONE + } +}; + +// +// AVR version uses ultralcd_st7920_u8glib_rrd_AVR.cpp +// HAL version uses u8g_dev_st7920_128x64_HAL.cpp +// +extern u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi; + +class U8GLIB_ST7920_128X64_RRD : public U8GLIB { +public: + U8GLIB_ST7920_128X64_RRD() : U8GLIB() { } + U8GLIB_ST7920_128X64_RRD(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, reset); } + void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_st7920_128x64_rrd_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); // a0 = U8G_PIN_NONE + } +}; + +extern u8g_dev_t u8g_dev_sh1106_128x64_2x_i2c_2_wire; + +class U8GLIB_SH1106_128X64_2X_I2C_2_WIRE : public U8GLIB { +public: + U8GLIB_SH1106_128X64_2X_I2C_2_WIRE() : U8GLIB() { } + U8GLIB_SH1106_128X64_2X_I2C_2_WIRE(uint8_t options) { init(options); } + void init(uint8_t options = U8G_I2C_OPT_NONE) { U8GLIB::init(&u8g_dev_sh1106_128x64_2x_i2c_2_wire, options); } +}; + +extern u8g_dev_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire; + +class U8GLIB_SSD1306_128X64_2X_I2C_2_WIRE : public U8GLIB { +public: + U8GLIB_SSD1306_128X64_2X_I2C_2_WIRE() : U8GLIB() { } + U8GLIB_SSD1306_128X64_2X_I2C_2_WIRE(uint8_t options) { init(options); } + void init(uint8_t options = U8G_I2C_OPT_NONE) { U8GLIB::init(&u8g_dev_ssd1306_128x64_2x_i2c_2_wire, options); } +}; + +// +// Very basic support for 320x240 TFT screen +// Tested on MKS Robin TFT_V2.0 with ST7789V controller +// +extern u8g_dev_t u8g_dev_tft_320x240_upscale_from_128x64; + +class U8GLIB_TFT_320X240_UPSCALE_FROM_128X64 : public U8GLIB { +public: + U8GLIB_TFT_320X240_UPSCALE_FROM_128X64() : U8GLIB() { } + U8GLIB_TFT_320X240_UPSCALE_FROM_128X64(uint8_t cs, uint8_t rs, uint8_t reset = U8G_PIN_NONE) { init(cs, rs, reset); } + void init(uint8_t cs, uint8_t rs, uint8_t reset = U8G_PIN_NONE) { U8GLIB::init(&u8g_dev_tft_320x240_upscale_from_128x64, cs, rs, reset); } +}; + + +extern u8g_dev_t u8g_dev_uc1701_mini12864_HAL_2x_sw_spi, u8g_dev_uc1701_mini12864_HAL_2x_hw_spi; + +class U8GLIB_MINI12864_2X_HAL : public U8GLIB { +public: + U8GLIB_MINI12864_2X_HAL() : U8GLIB() { } + U8GLIB_MINI12864_2X_HAL(uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); } + U8GLIB_MINI12864_2X_HAL(uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) { init(cs, a0, reset); } + void init(uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_uc1701_mini12864_HAL_2x_sw_spi, sck, mosi, cs, a0, reset); + } + void init(uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_uc1701_mini12864_HAL_2x_hw_spi, cs, a0, reset); + } +}; + +extern u8g_dev_t u8g_dev_ssd1309_sw_spi; +extern u8g_dev_t u8g_dev_ssd1309_hw_spi; + +class U8GLIB_SSD1309_128X64_HAL : public U8GLIB { +public: + U8GLIB_SSD1309_128X64_HAL() : U8GLIB() { } + U8GLIB_SSD1309_128X64_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); } + U8GLIB_SSD1309_128X64_HAL(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(cs, a0, reset); } + void init(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_ssd1309_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset); + } + void init(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_ssd1309_hw_spi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset); + } +}; diff --git a/src/lcd/dogm/HAL_LCD_com_defines.h b/src/lcd/dogm/HAL_LCD_com_defines.h new file mode 100644 index 0000000..f38c9d7 --- /dev/null +++ b/src/lcd/dogm/HAL_LCD_com_defines.h @@ -0,0 +1,132 @@ +/** + * 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 + +// Use this file to select the com driver for device drivers that are NOT in the U8G library + +#include + +#ifndef U8G_HAL_LINKS // Defined by LPC1768/9 environments in platform.ini + + #ifdef __SAM3X8E__ + + uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_DUE_sw_spi_fn + #define U8G_COM_HAL_HW_SPI_FN u8g_com_HAL_DUE_shared_hw_spi_fn + #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_HAL_DUE_ST7920_sw_spi_fn + + #elif defined(__SAMD51__) + + #define U8G_COM_HAL_HW_SPI_FN u8g_com_samd51_hw_spi_fn + #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_samd51_st7920_hw_spi_fn + + #elif defined(__STM32F1__) + + uint8_t u8g_com_HAL_STM32F1_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_stm32duino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_STM32F1_sw_spi_fn + #define U8G_COM_HAL_HW_SPI_FN u8g_com_stm32duino_hw_spi_fn + #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_std_sw_spi_fn + #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_stm32duino_hw_spi_fn + + #elif defined(ARDUINO_ARCH_STM32) + + uint8_t u8g_com_std_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_stm32duino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_SW_SPI_FN u8g_com_std_sw_spi_fn + #define U8G_COM_HAL_HW_SPI_FN u8g_com_stm32duino_hw_spi_fn + + #elif defined(ESP32) + + uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_HW_SPI_FN u8g_eps_hw_spi_fn + + #elif defined(__AVR__) + + uint8_t u8g_com_HAL_AVR_sw_sp_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_AVR_sw_sp_fn + + #endif + + #ifndef U8G_COM_HAL_SW_SPI_FN + #define U8G_COM_HAL_SW_SPI_FN u8g_com_arduino_std_sw_spi_fn + #endif + #ifndef U8G_COM_HAL_HW_SPI_FN + #define U8G_COM_HAL_HW_SPI_FN u8g_com_arduino_hw_spi_fn + #endif + #ifndef U8G_COM_ST7920_HAL_SW_SPI + #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_arduino_st7920_spi_fn + #endif + #ifndef U8G_COM_ST7920_HAL_HW_SPI + #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_arduino_st7920_hw_spi_fn + #endif + + // This can't be invoked from the current platformio.ini + #ifdef TARGET_LPC1768 + uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #endif + + #define U8G_COM_SSD_I2C_HAL u8g_com_arduino_ssd_i2c_fn + +#elif defined(TARGET_LPC1768) + + uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_LPC1768_sw_spi_fn + #define U8G_COM_HAL_HW_SPI_FN u8g_com_HAL_LPC1768_hw_spi_fn + #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_HAL_LPC1768_ST7920_sw_spi_fn + #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_HAL_LPC1768_ST7920_hw_spi_fn + #define U8G_COM_SSD_I2C_HAL u8g_com_HAL_LPC1768_ssd_hw_i2c_fn + +#elif defined(__PLAT_NATIVE_SIM__) + uint8_t u8g_com_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + uint8_t u8g_com_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_SW_SPI_FN u8g_com_sw_spi_fn + #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_ST7920_sw_spi_fn +#endif + +#ifndef U8G_COM_HAL_SW_SPI_FN + #define U8G_COM_HAL_SW_SPI_FN u8g_com_null_fn +#endif +#ifndef U8G_COM_HAL_HW_SPI_FN + #define U8G_COM_HAL_HW_SPI_FN u8g_com_null_fn +#endif +#ifndef U8G_COM_ST7920_HAL_SW_SPI + #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_null_fn +#endif +#ifndef U8G_COM_ST7920_HAL_HW_SPI + #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_null_fn +#endif +#ifndef U8G_COM_SSD_I2C_HAL + #define U8G_COM_SSD_I2C_HAL u8g_com_null_fn +#endif +#if HAS_FSMC_GRAPHICAL_TFT || HAS_SPI_GRAPHICAL_TFT || HAS_LTDC_GRAPHICAL_TFT + uint8_t u8g_com_hal_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); + #define U8G_COM_HAL_TFT_FN u8g_com_hal_tft_fn +#else + #define U8G_COM_HAL_TFT_FN u8g_com_null_fn +#endif diff --git a/src/lcd/dogm/dogm_Bootscreen.h b/src/lcd/dogm/dogm_Bootscreen.h new file mode 100644 index 0000000..4240861 --- /dev/null +++ b/src/lcd/dogm/dogm_Bootscreen.h @@ -0,0 +1,540 @@ +/** + * 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 + +/** + * Standard Marlin Boot Screen bitmaps + * + * Use the Marlin Bitmap Converter to make your own: + * https://marlinfw.org/tools/u8glib/converter.html + */ + +#include "../../inc/MarlinConfig.h" + +#if ENABLED(SHOW_CUSTOM_BOOTSCREEN) + + typedef struct { + const unsigned char *bitmap; + const unsigned short duration; + } boot_frame_t; + + #include "../../../_Bootscreen.h" + + #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED) && DISABLED(CUSTOM_BOOTSCREEN_ANIMATED_FRAME_TIME) && !defined(CUSTOM_BOOTSCREEN_FRAME_TIME) + #define CUSTOM_BOOTSCREEN_FRAME_TIME 500 // (ms) + #endif + + #ifndef CUSTOM_BOOTSCREEN_BMPWIDTH + #define CUSTOM_BOOTSCREEN_BMPWIDTH 128 + #endif + #ifndef CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH + #define CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH CEILING(CUSTOM_BOOTSCREEN_BMPWIDTH, 8) + #endif + #ifndef CUSTOM_BOOTSCREEN_BMPHEIGHT + #define CUSTOM_BOOTSCREEN_BMPHEIGHT (sizeof(custom_start_bmp) / (CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH)) + #endif + + #ifndef CUSTOM_BOOTSCREEN_Y + #if ENABLED(CUSTOM_BOOTSCREEN_BOTTOM_JUSTIFY) + #define CUSTOM_BOOTSCREEN_Y (LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) + #else + #define CUSTOM_BOOTSCREEN_Y ((LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) / 2) + #endif + #endif +#endif + +#if ENABLED(BOOT_MARLIN_LOGO_SMALL) + + #define START_BMPWIDTH 56 + + const unsigned char start_bmp[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000011,B11001111,B00000000,B00000000,B00001100,B00110000,B00111111, + B10000111,B11111111,B10000000,B00000000,B00001100,B00110000,B00011111, + B10000110,B01111001,B10000000,B00000000,B00001100,B00000000,B00001111, + B10001100,B00110000,B11000111,B10000011,B10001100,B00110000,B11100111, + B10001100,B00110000,B11001111,B11000111,B11001100,B00110001,B11110011, + B10001100,B00110000,B11011100,B11101100,B11101100,B00110011,B10111001, + B10001100,B00110000,B11011000,B01101100,B01101100,B00110011,B00011001, + B10001100,B00110000,B11010000,B01101100,B00001100,B00110011,B00011001, + B10001100,B00110000,B11011000,B01101100,B00001100,B00110011,B00011001, + B10001100,B00110000,B11011100,B01101100,B00001110,B00111011,B00011001, + B10001100,B00110000,B11001111,B01111100,B00000111,B10011111,B00011001, + B10001100,B00110000,B11000111,B01111100,B00000011,B10001111,B00011001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + #if ENABLED(BOOT_MARLIN_LOGO_ANIMATED) + + const unsigned char start_bmp1[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + const unsigned char start_bmp2[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000011,B11001111,B00000000,B00000000,B00000000,B00000000,B00111111, + B10000111,B11111111,B10000000,B00000000,B00000000,B00000000,B00011111, + B10000110,B01111001,B10000000,B00000000,B00000000,B00000000,B00001111, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000111, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000011, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + const unsigned char start_bmp3[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000011,B11001111,B00000000,B00000000,B00000000,B00000000,B00111111, + B10000111,B11111111,B10000000,B00000000,B00000000,B00000000,B00011111, + B10000110,B01111001,B10000000,B00000000,B00000000,B00000000,B00001111, + B10001100,B00110000,B11000111,B10000000,B00000000,B00000000,B00000111, + B10001100,B00110000,B11001111,B11000000,B00000000,B00000000,B00000011, + B10001100,B00110000,B11011100,B11100000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11011000,B01100000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11010000,B01100000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11011000,B01100000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11011100,B01100000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11001111,B01110000,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000111,B01110000,B00000000,B00000000,B00000001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + const unsigned char start_bmp4[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000011,B11001111,B00000000,B00000000,B00000000,B00000000,B00111111, + B10000111,B11111111,B10000000,B00000000,B00000000,B00000000,B00011111, + B10000110,B01111001,B10000000,B00000000,B00000000,B00000000,B00001111, + B10001100,B00110000,B11000111,B10000011,B10000000,B00000000,B00000111, + B10001100,B00110000,B11001111,B11000111,B11000000,B00000000,B00000011, + B10001100,B00110000,B11011100,B11101100,B11100000,B00000000,B00000001, + B10001100,B00110000,B11011000,B01101100,B01100000,B00000000,B00000001, + B10001100,B00110000,B11010000,B01101100,B00000000,B00000000,B00000001, + B10001100,B00110000,B11011000,B01101100,B00000000,B00000000,B00000001, + B10001100,B00110000,B11011100,B01101100,B00000000,B00000000,B00000001, + B10001100,B00110000,B11001111,B01111100,B00000000,B00000000,B00000001, + B10001100,B00110000,B11000111,B01111100,B00000000,B00000000,B00000001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + const unsigned char start_bmp5[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000011,B11001111,B00000000,B00000000,B00001100,B00000000,B00111111, + B10000111,B11111111,B10000000,B00000000,B00001100,B00000000,B00011111, + B10000110,B01111001,B10000000,B00000000,B00001100,B00000000,B00001111, + B10001100,B00110000,B11000111,B10000011,B10001100,B00000000,B00000111, + B10001100,B00110000,B11001111,B11000111,B11001100,B00000000,B00000011, + B10001100,B00110000,B11011100,B11101100,B11101100,B00000000,B00000001, + B10001100,B00110000,B11011000,B01101100,B01101100,B00000000,B00000001, + B10001100,B00110000,B11010000,B01101100,B00001100,B00000000,B00000001, + B10001100,B00110000,B11011000,B01101100,B00001100,B00000000,B00000001, + B10001100,B00110000,B11011100,B01101100,B00001110,B00000000,B00000001, + B10001100,B00110000,B11001111,B01111100,B00000111,B10000000,B00000001, + B10001100,B00110000,B11000111,B01111100,B00000011,B10000000,B00000001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + const unsigned char start_bmp6[] PROGMEM = { + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B10000011,B11001111,B00000000,B00000000,B00001100,B00110000,B00111111, + B10000111,B11111111,B10000000,B00000000,B00001100,B00110000,B00011111, + B10000110,B01111001,B10000000,B00000000,B00001100,B00000000,B00001111, + B10001100,B00110000,B11000111,B10000011,B10001100,B00110000,B00000111, + B10001100,B00110000,B11001111,B11000111,B11001100,B00110000,B00000011, + B10001100,B00110000,B11011100,B11101100,B11101100,B00110000,B00000001, + B10001100,B00110000,B11011000,B01101100,B01101100,B00110000,B00000001, + B10001100,B00110000,B11010000,B01101100,B00001100,B00110000,B00000001, + B10001100,B00110000,B11011000,B01101100,B00001100,B00110000,B00000001, + B10001100,B00110000,B11011100,B01101100,B00001110,B00111000,B00000001, + B10001100,B00110000,B11001111,B01111100,B00000111,B10011100,B00000001, + B10001100,B00110000,B11000111,B01111100,B00000011,B10001100,B00000001, + B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 + }; + + #endif + +#else + + #define START_BMPWIDTH 112 + + const unsigned char start_bmp[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00011000,B00000000,B00011111,B11111111, + B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00001111,B11111111, + B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00000111,B11111111, + B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00000011,B11111111, + B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000001,B11111111, + B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,B11111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B01111000,B00111100,B00000011,B11110000,B01111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B01111000,B00111100,B00000111,B11111100,B00111111, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B01111000,B00111100,B00001111,B11111110,B00011111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B01111000,B00111100,B00011111,B11111110,B00001111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B01111000,B00111100,B00111111,B00111111,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B01111000,B00111100,B00111110,B00011111,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B01111000,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B01111000,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B01111100,B00111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B01111111,B10111100,B00111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00111111,B10111111,B11111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00011111,B10111111,B11111100,B00001111,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00001111,B10111111,B11111100,B00001111,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + #if ENABLED(BOOT_MARLIN_LOGO_ANIMATED) + + const unsigned char start_bmp1[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + const unsigned char start_bmp2[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, + B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, + B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, + B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, + B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + const unsigned char start_bmp3[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, + B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, + B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, + B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, + B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + const unsigned char start_bmp4[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, + B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, + B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, + B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, + B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, + B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B00000000,B00000000,B00000000,B00000000,B00111111, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B00000000,B00000000,B00000000,B00000000,B00011111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B00000000,B00000000,B00000000,B00000000,B00001111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B00000000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + const unsigned char start_bmp5[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00011111,B11111111, + B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00001111,B11111111, + B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000111,B11111111, + B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000011,B11111111, + B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000001,B11111111, + B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,B11111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B01111000,B00000000,B00000000,B00000000,B01111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B01111000,B00000000,B00000000,B00000000,B00111111, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B01111000,B00000000,B00000000,B00000000,B00011111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B01111000,B00000000,B00000000,B00000000,B00001111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B01111000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B01111000,B00000000,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B01111000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B01111000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B01111100,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B01111111,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00111111,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00011111,B00000000,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00001111,B00000000,B00000000,B00000000,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + const unsigned char start_bmp6[] PROGMEM = { + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, + B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00111111,B11111111, + B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00011000,B00000000,B00011111,B11111111, + B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00001111,B11111111, + B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00000111,B11111111, + B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00000011,B11111111, + B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000001,B11111111, + B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,B11111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B01111000,B00111100,B00000000,B00000000,B01111111, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B01111000,B00111100,B00000000,B00000000,B00111111, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B01111000,B00111100,B00000000,B00000000,B00011111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B01111000,B00111100,B00000000,B00000000,B00001111, + B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B01111000,B00111100,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B01111000,B00111100,B00000000,B00000000,B00000111, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B01111000,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B01111000,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B01111100,B00111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B01111111,B10111100,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00111111,B10111111,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00011111,B10111111,B00000000,B00000000,B00000011, + B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00001111,B10111111,B00000000,B00000000,B00000011, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, + B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, + B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, + B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, + B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, + B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, + B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 + }; + + #endif + +#endif + +#if ENABLED(BOOT_MARLIN_LOGO_ANIMATED) + #ifndef MARLIN_BOOTSCREEN_FRAME_TIME + #define MARLIN_BOOTSCREEN_FRAME_TIME 100 // (ms) + #endif + const unsigned char * const marlin_bootscreen_animation[] PROGMEM = { + start_bmp1, start_bmp2, start_bmp3, start_bmp4, start_bmp5, start_bmp6, start_bmp + }; +#endif + +#ifndef START_BMP_BYTEWIDTH + #define START_BMP_BYTEWIDTH CEILING(START_BMPWIDTH, 8) +#endif +#ifndef START_BMPHEIGHT + #define START_BMPHEIGHT (sizeof(start_bmp) / (START_BMP_BYTEWIDTH)) +#endif + +static_assert(sizeof(start_bmp) == (START_BMP_BYTEWIDTH) * (START_BMPHEIGHT), "Bootscreen (start_bmp) dimensions don't match data."); diff --git a/src/lcd/dogm/dogm_Statusscreen.h b/src/lcd/dogm/dogm_Statusscreen.h new file mode 100644 index 0000000..8d0ab4e --- /dev/null +++ b/src/lcd/dogm/dogm_Statusscreen.h @@ -0,0 +1,765 @@ +/** + * 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 + +/** + * Standard Marlin Status Screen bitmaps + * + * Use the Marlin Bitmap Converter to make your own: + * https://marlinfw.org/tools/u8glib/converter.html + */ + +#include "../../inc/MarlinConfig.h" +#include "marlinui_DOGM.h" + +#define BW(N) ((N + 7) / 8) + +#if ENABLED(CUSTOM_STATUS_SCREEN_IMAGE) && DISABLED(STATUS_COMBINE_HEATERS) + + #undef STATUS_HEATERS_X + #undef STATUS_BED_X + + /** + * Custom _Statusscreen.h files can define: + * - A custom logo image + * - A custom heater bitmap + * - A custom fan bitmap / animation + * + * See the included examples for guidance + */ + #include "../../../_Statusscreen.h" + + #ifdef STATUS_SCREENWIDTH + #error "Your custom _Statusscreen.h needs to be converted for Marlin 2.0." + #endif + +#endif + +// +// Default Status Screen Heater or Hotends bitmaps +// +#if !STATUS_HEATERS_WIDTH && !STATUS_HOTEND1_WIDTH + #if ENABLED(STATUS_COMBINE_HEATERS) + #include "status/combined.h" + #else + #if HAS_HOTEND + #include "status/hotend.h" + #else + #define STATUS_HEATERS_HEIGHT 20 + #endif + #endif +#endif + +// +// Laser / Spindle +// +#if !STATUS_CUTTER_WIDTH && HAS_CUTTER + #include "status/cutter.h" +#endif +#ifndef STATUS_CUTTER_WIDTH + #define STATUS_CUTTER_WIDTH 0 +#endif + #ifndef STATUS_CUTTER_BYTEWIDTH + #define STATUS_CUTTER_BYTEWIDTH BW(STATUS_CUTTER_WIDTH) + #endif + +// +// Laser cooler +// +#if !STATUS_COOLER_WIDTH && HAS_COOLER + #include "status/cooler.h" +#endif +#ifndef STATUS_COOLER_WIDTH + #define STATUS_COOLER_WIDTH 0 +#endif +#ifndef STATUS_COOLER_BYTEWIDTH + #define STATUS_COOLER_BYTEWIDTH BW(STATUS_COOLER_WIDTH) +#endif + +// +// Laser Flowmeter +// +#if !STATUS_FLOWMETER_WIDTH && ENABLED(LASER_COOLANT_FLOW_METER) + #include "status/cooler.h" +#endif +#ifndef STATUS_FLOWMETER_WIDTH + #define STATUS_FLOWMETER_WIDTH 0 +#endif +#ifndef STATUS_FLOWMETER_BYTEWIDTH + #define STATUS_FLOWMETER_BYTEWIDTH BW(STATUS_FLOWMETER_WIDTH) +#endif + +// +// Laser Ammeter +// +#if ENABLED(I2C_AMMETER) + #if !STATUS_AMMETER_WIDTH + #include "status/ammeter.h" + #endif + #ifndef STATUS_AMMETER_WIDTH + #define STATUS_AMMETER_WIDTH 0 + #endif +#endif + +// +// Bed +// +#if !STATUS_BED_WIDTH && HAS_HEATED_BED && DISABLED(STATUS_COMBINE_HEATERS) + #include "status/bed.h" +#endif +#ifndef STATUS_BED_WIDTH + #define STATUS_BED_WIDTH 0 +#endif + +// +// Chamber +// +#if !STATUS_CHAMBER_WIDTH && HAS_TEMP_CHAMBER && ((HOTENDS <= 4 && !HAS_HEATED_BED) || (HOTENDS <= 3 && HAS_HEATED_BED)) + #include "status/chamber.h" +#endif +#ifndef STATUS_CHAMBER_WIDTH + #define STATUS_CHAMBER_WIDTH 0 +#endif + +// Can also be overridden in Configuration_adv.h +// If you can afford it, try the 3-frame fan animation! +// Don't compile in the fan animation with no fan +#if !HAS_FAN0 || (HOTENDS == 5 || (HOTENDS == 4 && BED_OR_CHAMBER) || BOTH(STATUS_COMBINE_HEATERS, HAS_HEATED_CHAMBER)) + #undef STATUS_FAN_FRAMES +#elif !STATUS_FAN_FRAMES + #define STATUS_FAN_FRAMES 2 +#elif STATUS_FAN_FRAMES > 4 + #error "A maximum of 4 fan animation frames is currently supported." +#endif + +#if HOTENDS > 4 + #undef STATUS_LOGO_WIDTH + #undef STATUS_HEATERS_XSPACE + #define STATUS_HEATERS_XSPACE 24 +#endif + +// +// Provide default Fan Bitmaps +// +#if !STATUS_FAN_WIDTH && STATUS_FAN_FRAMES > 0 + #include "status/fan.h" +#else + #undef STATUS_FAN_FRAMES + #define STATUS_FAN_WIDTH 0 +#endif + +#define _EXTRA_WIDTH (STATUS_FAN_WIDTH + STATUS_CHAMBER_WIDTH + STATUS_BED_WIDTH) + +// +// Heater Bitmap X Space Requirements +// +#if !defined(STATUS_HEATERS_XSPACE) && (STATUS_HOTEND1_WIDTH || STATUS_HEATERS_WIDTH) + #if (HOTENDS == 3 || HOTENDS == 4) && ENABLED(STATUS_COMBINE_HEATERS) + // If more heaters or they're combined, 3 bytes + #define STATUS_HEATERS_XSPACE 24 + #elif STATUS_LOGO_WIDTH > (LCD_PIXEL_WIDTH - (_EXTRA_WIDTH) - 26 * (HOTENDS)) // 128 - (20 + 24 + 26) == 58 + // If the logo won't fit at 26 width + #define STATUS_HEATERS_XSPACE 24 + #else + #define STATUS_HEATERS_XSPACE 26 + #endif +#endif + +#if ENABLED(CUSTOM_STATUS_SCREEN_IMAGE) + // + // Disable the logo bitmap if insufficient space + // + #if STATUS_HEATERS_XSPACE + #define _HEATERS_WIDTH (HOTENDS * (STATUS_HEATERS_XSPACE)) // as many hotends as possible + #elif STATUS_HEATERS_WIDTH + #define _HEATERS_WIDTH STATUS_HEATERS_WIDTH + #elif HOTENDS + #error "Status screen heaters region was not specified." + #endif + #if STATUS_LOGO_WIDTH > (LCD_PIXEL_WIDTH - (_EXTRA_WIDTH + _HEATERS_WIDTH)) + #warning "Unable to fit custom Status Screen logo. Disabling." + #undef STATUS_LOGO_WIDTH + #endif + + #if !defined(STATUS_HEATERS_X) && ((HAS_HOTEND && STATUS_LOGO_WIDTH && BED_OR_CHAMBER_OR_FAN) || (HOTENDS >= 3 && !BED_OR_CHAMBER_OR_FAN)) + #define _STATUS_HEATERS_X(H,S,N) ((LCD_PIXEL_WIDTH - (H * (S + N)) - (_EXTRA_WIDTH) + (STATUS_LOGO_WIDTH)) / 2) + #if STATUS_HOTEND1_WIDTH + #if HOTENDS > 2 + #define STATUS_HEATERS_X _STATUS_HEATERS_X(HOTENDS, STATUS_HOTEND1_WIDTH, 6) + #else + #define STATUS_HEATERS_X _STATUS_HEATERS_X(HOTENDS, STATUS_HOTEND1_WIDTH, 4) + #endif + #else + #define STATUS_HEATERS_X _STATUS_HEATERS_X(1, STATUS_HEATERS_WIDTH, 4) + #endif + #endif +#endif + +// +// Custom Logo Bitmap Properties +// +#ifndef STATUS_LOGO_WIDTH + #define STATUS_LOGO_WIDTH 0 +#endif +#ifndef STATUS_LOGO_BYTEWIDTH + #define STATUS_LOGO_BYTEWIDTH BW(STATUS_LOGO_WIDTH) +#endif +#if STATUS_LOGO_WIDTH + #ifndef STATUS_LOGO_X + #ifdef STATUS_HEATERS_X + #define STATUS_LOGO_X ((STATUS_HEATERS_X - (STATUS_LOGO_WIDTH) - 1) / 2) + #else + #define STATUS_LOGO_X 0 + #endif + #endif + #ifndef STATUS_LOGO_HEIGHT + #define STATUS_LOGO_HEIGHT (sizeof(status_logo_bmp) / (STATUS_LOGO_BYTEWIDTH)) + #endif + #ifndef STATUS_LOGO_Y + #define STATUS_LOGO_Y _MAX(0U, (28U - _MIN(28U, STATUS_LOGO_HEIGHT)) / 2U) + #endif + static_assert( + sizeof(status_logo_bmp) == (STATUS_LOGO_BYTEWIDTH) * (STATUS_LOGO_HEIGHT), + "Status logo bitmap (status_logo_bmp) dimensions don't match data." + ); +#endif + +// +// Hotend Heater Bitmap starting X position +// +#if !defined(STATUS_HEATERS_X) && (STATUS_HOTEND1_WIDTH || STATUS_HEATERS_WIDTH) + #if STATUS_LOGO_BYTEWIDTH + #define STATUS_HEATERS_X (STATUS_LOGO_BYTEWIDTH * 8) + #elif ((STATUS_CHAMBER_WIDTH || STATUS_FAN_WIDTH) && (STATUS_BED_WIDTH && STATUS_HOTEND_BITMAPS == 3)) || \ + ((STATUS_CHAMBER_WIDTH || STATUS_FAN_WIDTH || STATUS_BED_WIDTH) && STATUS_HOTEND_BITMAPS == 4) + #define STATUS_HEATERS_X 5 + #else + #if BOTH(STATUS_COMBINE_HEATERS, HAS_HEATED_BED) && HOTENDS <= 4 + #define STATUS_HEATERS_X 5 + #else + #define STATUS_HEATERS_X 8 // Like the included bitmaps + #endif + #endif +#endif + +#if STATUS_HOTEND1_WIDTH + + // + // Hotend images. A base hotend image and optional "ON" state image. + // + #ifndef STATUS_HOTEND_BITMAPS + #define STATUS_HOTEND_BITMAPS 1 + #endif + + #ifndef STATUS_HOTEND2_WIDTH + #define STATUS_HOTEND2_WIDTH STATUS_HOTEND1_WIDTH + #endif + #ifndef STATUS_HOTEND3_WIDTH + #define STATUS_HOTEND3_WIDTH STATUS_HOTEND2_WIDTH + #endif + #ifndef STATUS_HOTEND4_WIDTH + #define STATUS_HOTEND4_WIDTH STATUS_HOTEND3_WIDTH + #endif + #ifndef STATUS_HOTEND5_WIDTH + #define STATUS_HOTEND5_WIDTH STATUS_HOTEND4_WIDTH + #endif + #ifndef STATUS_HOTEND6_WIDTH + #define STATUS_HOTEND6_WIDTH STATUS_HOTEND5_WIDTH + #endif + #ifndef STATUS_HOTEND7_WIDTH + #define STATUS_HOTEND7_WIDTH STATUS_HOTEND6_WIDTH + #endif + #ifndef STATUS_HOTEND8_WIDTH + #define STATUS_HOTEND8_WIDTH STATUS_HOTEND7_WIDTH + #endif + + #define _SHNAME(N,T) STATUS_HOTEND##N##_##T, + + constexpr uint8_t status_hotend_width[HOTENDS] = { REPEAT2_S(1, INCREMENT(HOTENDS), _SHNAME, WIDTH) }; + #define STATUS_HOTEND_WIDTH(N) status_hotend_width[N] + + #ifndef STATUS_HOTEND1_BYTEWIDTH + #define STATUS_HOTEND1_BYTEWIDTH BW(STATUS_HOTEND1_WIDTH) + #endif + #ifndef STATUS_HOTEND2_BYTEWIDTH + #define STATUS_HOTEND2_BYTEWIDTH BW(STATUS_HOTEND2_WIDTH) + #endif + #ifndef STATUS_HOTEND3_BYTEWIDTH + #define STATUS_HOTEND3_BYTEWIDTH BW(STATUS_HOTEND3_WIDTH) + #endif + #ifndef STATUS_HOTEND4_BYTEWIDTH + #define STATUS_HOTEND4_BYTEWIDTH BW(STATUS_HOTEND4_WIDTH) + #endif + #ifndef STATUS_HOTEND5_BYTEWIDTH + #define STATUS_HOTEND5_BYTEWIDTH BW(STATUS_HOTEND5_WIDTH) + #endif + #ifndef STATUS_HOTEND6_BYTEWIDTH + #define STATUS_HOTEND6_BYTEWIDTH BW(STATUS_HOTEND6_WIDTH) + #endif + #ifndef STATUS_HOTEND7_BYTEWIDTH + #define STATUS_HOTEND7_BYTEWIDTH BW(STATUS_HOTEND7_WIDTH) + #endif + #ifndef STATUS_HOTEND8_BYTEWIDTH + #define STATUS_HOTEND8_BYTEWIDTH BW(STATUS_HOTEND8_WIDTH) + #endif + + constexpr uint8_t status_hotend_bytewidth[HOTENDS] = { REPEAT2_S(1, INCREMENT(HOTENDS), _SHNAME, BYTEWIDTH) }; + #define STATUS_HOTEND_BYTEWIDTH(N) status_hotend_bytewidth[N] + + #ifndef STATUS_HOTEND1_X + #define STATUS_HOTEND1_X STATUS_HEATERS_X + #endif + #ifndef STATUS_HOTEND2_X + #define STATUS_HOTEND2_X STATUS_HOTEND1_X + STATUS_HEATERS_XSPACE + #endif + + #if HOTENDS > 2 + #ifndef STATUS_HOTEND3_X + #define STATUS_HOTEND3_X STATUS_HOTEND2_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND4_X + #define STATUS_HOTEND4_X STATUS_HOTEND3_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND5_X + #define STATUS_HOTEND5_X STATUS_HOTEND4_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND6_X + #define STATUS_HOTEND6_X STATUS_HOTEND5_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND7_X + #define STATUS_HOTEND7_X STATUS_HOTEND6_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND8_X + #define STATUS_HOTEND8_X STATUS_HOTEND7_X + STATUS_HEATERS_XSPACE + #endif + + constexpr uint8_t status_hotend_x[HOTENDS] = { REPEAT2_S(1, INCREMENT(HOTENDS), _SHNAME, X) }; + #define STATUS_HOTEND_X(N) status_hotend_x[N] + #elif HAS_MULTI_HOTEND + #define STATUS_HOTEND_X(N) ((N) ? STATUS_HOTEND2_X : STATUS_HOTEND1_X) + #else + #define STATUS_HOTEND_X(N) STATUS_HOTEND1_X + #endif + + #ifndef STATUS_HOTEND_TEXT_X + #ifdef STATUS_HOTEND1_TEXT_X + #ifndef STATUS_HOTEND2_TEXT_X + #define STATUS_HOTEND2_TEXT_X STATUS_HOTEND1_TEXT_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND3_TEXT_X + #define STATUS_HOTEND3_TEXT_X STATUS_HOTEND2_TEXT_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND4_TEXT_X + #define STATUS_HOTEND4_TEXT_X STATUS_HOTEND3_TEXT_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND5_TEXT_X + #define STATUS_HOTEND5_TEXT_X STATUS_HOTEND4_TEXT_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND6_TEXT_X + #define STATUS_HOTEND6_TEXT_X STATUS_HOTEND5_TEXT_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND7_TEXT_X + #define STATUS_HOTEND7_TEXT_X STATUS_HOTEND6_TEXT_X + STATUS_HEATERS_XSPACE + #endif + #ifndef STATUS_HOTEND8_TEXT_X + #define STATUS_HOTEND8_TEXT_X STATUS_HOTEND7_TEXT_X + STATUS_HEATERS_XSPACE + #endif + constexpr uint8_t status_hotend_text_x[HOTENDS] = { REPEAT2_S(1, INCREMENT(HOTENDS), _SHNAME, TEXT_X) }; + #define STATUS_HOTEND_TEXT_X(N) status_hotend_text_x[N] + #else + #define STATUS_HOTEND_TEXT_X(N) (STATUS_HOTEND1_X + 6 + (N) * (STATUS_HEATERS_XSPACE)) + #endif + #endif + + #undef _SHNAME + + #if STATUS_HOTEND_BITMAPS > 1 && DISABLED(STATUS_HOTEND_NUMBERLESS) + #define TEST_BITMAP_OFF status_hotend1_a_bmp + #define TEST_BITMAP_ON status_hotend1_b_bmp + #else + #define TEST_BITMAP_OFF status_hotend_a_bmp + #define TEST_BITMAP_ON status_hotend_b_bmp + #endif + #ifndef STATUS_HEATERS_HEIGHT + #define STATUS_HEATERS_HEIGHT (sizeof(TEST_BITMAP_OFF) / (STATUS_HOTEND1_BYTEWIDTH)) + #endif + #ifndef STATUS_HEATERS_Y + #define STATUS_HEATERS_Y (20 - (STATUS_HEATERS_HEIGHT)) + #endif + + #define HOTEND0_BITMAP_SIZE (STATUS_HOTEND1_BYTEWIDTH) * (STATUS_HEATERS_HEIGHT) + static_assert( + sizeof(TEST_BITMAP_OFF) == HOTEND0_BITMAP_SIZE, + "Status hotend bitmap (" STRINGIFY(TEST_BITMAP_OFF) ") dimensions don't match data." + ); + #ifdef STATUS_HOTEND_ANIM + static_assert( + sizeof(TEST_BITMAP_ON) == HOTEND0_BITMAP_SIZE, + "Status hotend bitmaps (" STRINGIFY(TEST_BITMAP_OFF) " and " STRINGIFY(TEST_BITMAP_ON) ") dimensions don't match." + ); + #endif + +#elif STATUS_HEATERS_WIDTH + + #ifndef STATUS_HEATERS_XSPACE + #define STATUS_HEATERS_XSPACE 24 + #endif + #ifndef STATUS_HOTEND_WIDTH + #define STATUS_HOTEND_WIDTH(N) 10 + #endif + #ifndef STATUS_HOTEND_X + #define STATUS_HOTEND_X(N) (STATUS_HEATERS_X + 2 + (N) * (STATUS_HEATERS_XSPACE)) + #endif + #ifndef STATUS_HOTEND_TEXT_X + #if HOTENDS == 4 && STATUS_LOGO_WIDTH + #define STATUS_HOTEND_TEXT_X(N) (STATUS_HEATERS_X + 6 + (N) * (STATUS_HEATERS_XSPACE)) + #else + #define STATUS_HOTEND_TEXT_X(N) (STATUS_HEATERS_X + 6 + (N) * (STATUS_HEATERS_XSPACE)) + #endif + #endif + #ifndef STATUS_HEATERS_BYTEWIDTH + #define STATUS_HEATERS_BYTEWIDTH BW(STATUS_HEATERS_WIDTH) + #endif + #ifndef STATUS_HEATERS_HEIGHT + #define STATUS_HEATERS_HEIGHT (sizeof(status_heaters_bmp) / (STATUS_HEATERS_BYTEWIDTH)) + #endif + #ifndef STATUS_HEATERS_Y + #define STATUS_HEATERS_Y (20 - (STATUS_HEATERS_HEIGHT)) + #endif + + static_assert( + sizeof(status_heaters_bmp) == (STATUS_HEATERS_BYTEWIDTH) * (STATUS_HEATERS_HEIGHT), + "Status heaters bitmap (status_heaters_bmp) dimensions don't match data." + ); + +#else // HOTENDS == 0 + + #define STATUS_HOTEND_TEXT_X(N) 0 + #define STATUS_HEATERS_Y 0 + +#endif + +// +// Cutter Bitmap Properties +// +#if HAS_CUTTER + #if STATUS_CUTTER_WIDTH + + #ifndef STATUS_CUTTER_X + #define STATUS_CUTTER_X (LCD_PIXEL_WIDTH - (STATUS_CUTTER_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH) * 8) + #endif + + #ifndef STATUS_CUTTER_HEIGHT + #ifdef STATUS_CUTTER_ANIM + #define STATUS_CUTTER_HEIGHT(S) ((S) ? sizeof(status_cutter_on_bmp) / (STATUS_CUTTER_BYTEWIDTH) : sizeof(status_cutter_bmp) / (STATUS_CUTTER_BYTEWIDTH)) + #else + #define STATUS_CUTTER_HEIGHT(S) (sizeof(status_cutter_bmp) / (STATUS_CUTTER_BYTEWIDTH)) + #endif + #endif + + #ifndef STATUS_CUTTER_Y + #define STATUS_CUTTER_Y(S) 4 + #endif + + #ifndef STATUS_CUTTER_TEXT_X + #define STATUS_CUTTER_TEXT_X (STATUS_CUTTER_X - 1) + #endif + + #ifndef STATUS_CUTTER_TEXT_Y + #define STATUS_CUTTER_TEXT_Y 28 + #endif + + static_assert( + sizeof(status_cutter_bmp) == (STATUS_CUTTER_BYTEWIDTH) * STATUS_CUTTER_HEIGHT(0), + "Status cutter bitmap (status_cutter_bmp) dimensions don't match data." + ); + #ifdef STATUS_CUTTER_ANIM + static_assert( + sizeof(status_cutter_on_bmp) == (STATUS_CUTTER_BYTEWIDTH) * STATUS_CUTTER_HEIGHT(1), + "Status cutter bitmap (status_cutter_on_bmp) dimensions don't match data." + ); + #endif + + #endif +#endif + +// +// Chamber Bitmap Properties +// +#ifndef STATUS_CHAMBER_BYTEWIDTH + #define STATUS_CHAMBER_BYTEWIDTH BW(STATUS_CHAMBER_WIDTH) +#endif +#if STATUS_CHAMBER_WIDTH + + #ifndef STATUS_CHAMBER_X + #define STATUS_CHAMBER_X (LCD_PIXEL_WIDTH - (STATUS_CHAMBER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) + #endif + + #ifndef STATUS_CHAMBER_HEIGHT + #ifdef STATUS_CHAMBER_ANIM + #define STATUS_CHAMBER_HEIGHT(S) ((S) ? sizeof(status_chamber_on_bmp) / (STATUS_CHAMBER_BYTEWIDTH) : sizeof(status_chamber_bmp) / (STATUS_CHAMBER_BYTEWIDTH)) + #else + #define STATUS_CHAMBER_HEIGHT(S) (sizeof(status_chamber_bmp) / (STATUS_CHAMBER_BYTEWIDTH)) + #endif + #endif + + #ifndef STATUS_CHAMBER_Y + #define STATUS_CHAMBER_Y(S) (20 - STATUS_CHAMBER_HEIGHT(S)) + #endif + + #ifndef STATUS_CHAMBER_TEXT_X + #define STATUS_CHAMBER_TEXT_X (STATUS_CHAMBER_X + 11) + #endif + + static_assert( + sizeof(status_chamber_bmp) == (STATUS_CHAMBER_BYTEWIDTH) * STATUS_CHAMBER_HEIGHT(0), + "Status chamber bitmap (status_chamber_bmp) dimensions don't match data." + ); + #ifdef STATUS_CHAMBER_ANIM + static_assert( + sizeof(status_chamber_on_bmp) == (STATUS_CHAMBER_BYTEWIDTH) * STATUS_CHAMBER_HEIGHT(1), + "Status chamber bitmap (status_chamber_on_bmp) dimensions don't match data." + ); + #endif + +#endif + +// +// Cooler Bitmap Properties +// +#if HAS_COOLER + #if STATUS_COOLER_WIDTH + + #ifndef STATUS_COOLER_X + #define STATUS_COOLER_X (LCD_PIXEL_WIDTH - (STATUS_COOLER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH) * 8) + #endif + + #ifndef STATUS_COOLER_HEIGHT + #define STATUS_COOLER_HEIGHT(S) (sizeof(status_cooler_bmp1) / (STATUS_COOLER_BYTEWIDTH)) + #endif + + #ifndef STATUS_COOLER_Y + #define STATUS_COOLER_Y(S) (18 - STATUS_COOLER_HEIGHT(S)) + #endif + + #ifndef STATUS_COOLER_TEXT_X + #define STATUS_COOLER_TEXT_X (STATUS_COOLER_X + 12) + #endif + + static_assert( + sizeof(status_cooler_bmp1) == (STATUS_COOLER_BYTEWIDTH) * STATUS_COOLER_HEIGHT(0), + "Status cooler bitmap (status_cooler_bmp1) dimensions don't match data." + ); + #ifdef STATUS_COOLER_ANIM + static_assert( + sizeof(status_cooler_bmp2) == (STATUS_COOLER_BYTEWIDTH) * STATUS_COOLER_HEIGHT(1), + "Status cooler bitmap (status_cooler_bmp2) dimensions don't match data." + ); + #endif + + #endif +#endif + +// +// Flowmeter Bitmap Properties +// +#if ENABLED(LASER_COOLANT_FLOW_METER) + #if STATUS_FLOWMETER_WIDTH + + #ifndef STATUS_FLOWMETER_X + #define STATUS_FLOWMETER_X (LCD_PIXEL_WIDTH - (STATUS_FLOWMETER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH + STATUS_COOLER_BYTEWIDTH) * 8) + #endif + + #ifndef STATUS_FLOWMETER_HEIGHT + #define STATUS_FLOWMETER_HEIGHT(S) (sizeof(status_flowmeter_bmp1) / (STATUS_FLOWMETER_BYTEWIDTH)) + #endif + + #ifndef STATUS_FLOWMETER_Y + #define STATUS_FLOWMETER_Y(S) (20 - STATUS_FLOWMETER_HEIGHT(S)) + #endif + + #ifndef STATUS_FLOWMETER_TEXT_X + #define STATUS_FLOWMETER_TEXT_X (STATUS_FLOWMETER_X + 12) + #endif + + static_assert( + sizeof(status_flowmeter_bmp1) == (STATUS_FLOWMETER_BYTEWIDTH) * STATUS_FLOWMETER_HEIGHT(0), + "Status flowmeter bitmap (status_flowmeter_bmp1) dimensions don't match data." + ); + #ifdef STATUS_COOLER_ANIM + static_assert( + sizeof(status_flowmeter_bmp2) == (STATUS_FLOWMETER_BYTEWIDTH) * STATUS_FLOWMETER_HEIGHT(1), + "Status flowmeter bitmap (status_flowmeter_bmp2) dimensions don't match data." + ); + #endif + #endif +#endif + +// +// I2C Laser Ammeter +// +#if ENABLED(I2C_AMMETER) && STATUS_AMMETER_WIDTH + #ifndef STATUS_AMMETER_BYTEWIDTH + #define STATUS_AMMETER_BYTEWIDTH BW(STATUS_AMMETER_WIDTH) + #endif + #ifndef STATUS_AMMETER_X + #define STATUS_AMMETER_X (LCD_PIXEL_WIDTH - (STATUS_AMMETER_BYTEWIDTH + STATUS_FLOWMETER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH + STATUS_COOLER_BYTEWIDTH) * 8) + #endif + #ifndef STATUS_AMMETER_HEIGHT + #define STATUS_AMMETER_HEIGHT(S) (sizeof(status_ammeter_bmp_mA) / (STATUS_AMMETER_BYTEWIDTH)) + #endif + #ifndef STATUS_AMMETER_Y + #define STATUS_AMMETER_Y(S) (18 - STATUS_AMMETER_HEIGHT(S)) + #endif + #ifndef STATUS_AMMETER_TEXT_X + #define STATUS_AMMETER_TEXT_X (STATUS_AMMETER_X + 7) + #endif + static_assert( + sizeof(status_ammeter_bmp_mA) == (STATUS_AMMETER_BYTEWIDTH) * STATUS_AMMETER_HEIGHT(0), + "Status ammeter bitmap (status_ammeter_bmp_mA) dimensions don't match data." + ); +#endif + +// +// Bed Bitmap Properties +// +#ifndef STATUS_BED_BYTEWIDTH + #define STATUS_BED_BYTEWIDTH BW(STATUS_BED_WIDTH) +#endif +#if STATUS_BED_WIDTH && !STATUS_HEATERS_WIDTH + + #ifndef STATUS_BED_X + #define STATUS_BED_X (LCD_PIXEL_WIDTH - (STATUS_CHAMBER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_BED_BYTEWIDTH) * 8 - TERN0(STATUS_HEAT_PERCENT, 4)) + #endif + + #ifndef STATUS_BED_HEIGHT + #ifdef STATUS_BED_ANIM + #define STATUS_BED_HEIGHT(S) ((S) ? sizeof(status_bed_on_bmp) / (STATUS_BED_BYTEWIDTH) : sizeof(status_bed_bmp) / (STATUS_BED_BYTEWIDTH)) + #else + #define STATUS_BED_HEIGHT(S) (sizeof(status_bed_bmp) / (STATUS_BED_BYTEWIDTH)) + #endif + #endif + + #ifndef STATUS_BED_Y + #define STATUS_BED_Y(S) (20 - STATUS_BED_HEIGHT(S)) + #endif + + #ifndef STATUS_BED_TEXT_X + #define STATUS_BED_TEXT_X (STATUS_BED_X + 9) + #endif + + static_assert( + sizeof(status_bed_bmp) == (STATUS_BED_BYTEWIDTH) * STATUS_BED_HEIGHT(0), + "Status bed bitmap (status_bed_bmp) dimensions don't match data." + ); + #ifdef STATUS_BED_ANIM + static_assert( + sizeof(status_bed_on_bmp) == (STATUS_BED_BYTEWIDTH) * STATUS_BED_HEIGHT(1), + "Status bed bitmap (status_bed_on_bmp) dimensions don't match data." + ); + #endif +#endif + +// +// Fan Bitmap Properties +// +#ifndef STATUS_FAN_BYTEWIDTH + #define STATUS_FAN_BYTEWIDTH BW(STATUS_FAN_WIDTH) +#endif +#if STATUS_FAN_FRAMES + #ifndef STATUS_FAN_X + #define STATUS_FAN_X (LCD_PIXEL_WIDTH - (STATUS_FAN_BYTEWIDTH) * 8) + #endif + #ifndef STATUS_FAN_Y + #define STATUS_FAN_Y 1 + #endif + #ifndef STATUS_FAN_TEXT_X + #define STATUS_FAN_TEXT_X (STATUS_FAN_X - 1) + #endif + #ifndef STATUS_FAN_TEXT_Y + #define STATUS_FAN_TEXT_Y 28 + #endif + #ifndef STATUS_FAN_HEIGHT + #define STATUS_FAN_HEIGHT (sizeof(status_fan0_bmp) / (STATUS_FAN_BYTEWIDTH)) + #endif + #define FAN_BMP_SIZE (STATUS_FAN_BYTEWIDTH) * (STATUS_FAN_HEIGHT) + static_assert(sizeof(status_fan0_bmp) == FAN_BMP_SIZE, "Status fan bitmap (status_fan0_bmp) dimensions don't match data."); + #if STATUS_FAN_FRAMES > 1 + static_assert(sizeof(status_fan1_bmp) == FAN_BMP_SIZE, "Status fan bitmap (status_fan1_bmp) dimensions don't match data."); + #if STATUS_FAN_FRAMES > 2 + static_assert(sizeof(status_fan2_bmp) == FAN_BMP_SIZE, "Status fan bitmap (status_fan2_bmp) dimensions don't match data."); + #if STATUS_FAN_FRAMES > 3 + static_assert(sizeof(status_fan3_bmp) == FAN_BMP_SIZE, "Status fan bitmap (status_fan3_bmp) dimensions don't match data."); + #endif + #endif + #endif +#endif + +#if STATUS_LOGO_WIDTH && ENABLED(CUSTOM_STATUS_SCREEN_IMAGE) + #define DO_DRAW_LOGO 1 +#endif +#if HOTENDS > 0 + #define DO_DRAW_HOTENDS 1 +#endif +#if HAS_HEATED_BED && HOTENDS <= 4 + #define DO_DRAW_BED 1 +#endif +#if HAS_CUTTER && !DO_DRAW_BED + #define DO_DRAW_CUTTER 1 +#endif +#if HAS_COOLER + #define DO_DRAW_COOLER 1 +#endif +#if ENABLED(LASER_COOLANT_FLOW_METER) + #define DO_DRAW_FLOWMETER 1 +#endif +#if ENABLED(I2C_AMMETER) + #define DO_DRAW_AMMETER 1 +#endif + +#if HAS_TEMP_CHAMBER && STATUS_CHAMBER_WIDTH && HOTENDS <= 4 + #define DO_DRAW_CHAMBER 1 +#endif +#if HAS_FAN0 && STATUS_FAN_WIDTH && HOTENDS <= 4 && defined(STATUS_FAN_FRAMES) + #define DO_DRAW_FAN 1 +#endif +#if BOTH(HAS_HOTEND, STATUS_HOTEND_ANIM) + #define ANIM_HOTEND 1 +#endif +#if BOTH(DO_DRAW_BED, STATUS_BED_ANIM) + #define ANIM_BED 1 +#endif +#if BOTH(DO_DRAW_CHAMBER, STATUS_CHAMBER_ANIM) + #define ANIM_CHAMBER 1 +#endif +#if BOTH(DO_DRAW_CUTTER, STATUS_CUTTER_ANIM) + #define ANIM_CUTTER 1 +#endif +#if BOTH(DO_DRAW_COOLER, STATUS_COOLER_ANIM) + #define ANIM_COOLER 1 +#endif +#if BOTH(DO_DRAW_FLOWMETER, STATUS_FLOWMETER_ANIM) + #define ANIM_FLOWMETER 1 +#endif +#if ANIM_HOTEND || ANIM_BED || ANIM_CHAMBER || ANIM_CUTTER + #define ANIM_HBCC 1 +#endif diff --git a/src/lcd/dogm/fontdata/fontdata_6x9_marlin.h b/src/lcd/dogm/fontdata/fontdata_6x9_marlin.h new file mode 100644 index 0000000..524ff18 --- /dev/null +++ b/src/lcd/dogm/fontdata/fontdata_6x9_marlin.h @@ -0,0 +1,189 @@ +/** + * 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 + +/** + Fontname: -Misc-Fixed-Medium-R-Normal--9-90-75-75-C-60-ISO10646-1 + Copyright: Public domain font. Share and enjoy. + Capital A Height: 6, '1' Height: 6 + Calculated Max Values w= 6 h= 9 x= 5 y= 5 dx= 6 dy= 0 ascent= 7 len= 9 + Font Bounding box w= 6 h= 9 x= 0 y=-2 + Calculated Min Values x= 0 y=-2 dx= 0 dy= 0 + Pure Font ascent = 6 descent=-2 + X Font ascent = 6 descent=-2 + Max Font ascent = 7 descent=-2 +*/ +#include +const u8g_fntpgm_uint8_t u8g_font_6x9[2434] U8G_FONT_SECTION(".progmem.u8g_font_6x9") = { + 0x00,0x06,0x09,0x00,0xFE,0x06,0x02,0x0F,0x03,0x84,0x01,0xFF,0xFE,0x07,0xFE,0x06, + 0xFE,0x05,0x07,0x07,0x00,0x00,0x00,0x40,0xF0,0xC8,0x88,0x98,0x78,0x10,0x05,0x07, + 0x07,0x00,0x00,0x00,0xC0,0xF8,0x88,0x88,0x88,0x88,0xF8,0x05,0x05,0x05,0x00,0x00, + 0x01,0x20,0x30,0xF8,0x30,0x20,0x05,0x07,0x07,0x00,0x00,0x00,0x20,0x70,0xF8,0x20, + 0x20,0x20,0xE0,0x05,0x07,0x07,0x00,0x00,0x00,0x20,0x70,0xA8,0xB8,0x88,0x70,0x20, + 0x06,0x05,0x05,0x00,0x00,0x00,0xB0,0xD8,0x6C,0xD8,0xB0,0x05,0x08,0x08,0x00,0x00, + 0xFF,0xF8,0xA8,0x88,0x88,0x88,0x88,0xA8,0xF8,0x05,0x09,0x09,0x00,0x00,0xFE,0x20, + 0x50,0x50,0x50,0x50,0x88,0xA8,0x88,0x70,0x03,0x03,0x03,0x00,0x00,0x03,0x40,0xA0, + 0x40,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x06,0x05,0xFF,0x01,0x06,0x06, + 0x06,0x02,0x00,0x80,0x80,0x80,0x80,0x00,0x80,0x03,0x03,0x03,0x06,0x01,0x03,0xA0, + 0xA0,0xA0,0x05,0x07,0x07,0x06,0x00,0xFF,0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x05, + 0x09,0x09,0x06,0x00,0xFE,0x20,0x70,0xA8,0xA0,0x70,0x28,0xA8,0x70,0x20,0x06,0x08, + 0x08,0x06,0x00,0xFF,0x40,0xA8,0x48,0x10,0x20,0x48,0x54,0x08,0x05,0x07,0x07,0x06, + 0x00,0xFF,0x60,0x90,0x90,0x60,0x98,0x90,0x68,0x01,0x03,0x03,0x06,0x02,0x03,0x80, + 0x80,0x80,0x02,0x07,0x07,0x06,0x02,0xFF,0x40,0x80,0x80,0x80,0x80,0x80,0x40,0x02, + 0x07,0x07,0x06,0x02,0xFF,0x80,0x40,0x40,0x40,0x40,0x40,0x80,0x05,0x05,0x05,0x06, + 0x00,0x00,0x88,0x50,0xF8,0x50,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x20,0x20,0xF8, + 0x20,0x20,0x02,0x04,0x04,0x06,0x02,0xFE,0xC0,0x40,0x40,0x80,0x05,0x01,0x01,0x06, + 0x00,0x02,0xF8,0x02,0x02,0x02,0x06,0x02,0x00,0xC0,0xC0,0x04,0x06,0x06,0x06,0x01, + 0x00,0x10,0x10,0x20,0x40,0x80,0x80,0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90,0x90, + 0x90,0x90,0x60,0x03,0x06,0x06,0x06,0x01,0x00,0x40,0xC0,0x40,0x40,0x40,0xE0,0x04, + 0x06,0x06,0x06,0x01,0x00,0x60,0x90,0x10,0x20,0x40,0xF0,0x04,0x06,0x06,0x06,0x01, + 0x00,0xF0,0x20,0x60,0x10,0x10,0xE0,0x05,0x06,0x06,0x06,0x00,0x00,0x10,0x30,0x50, + 0x90,0xF8,0x10,0x04,0x06,0x06,0x06,0x01,0x00,0xF0,0x80,0xE0,0x10,0x10,0xE0,0x04, + 0x06,0x06,0x06,0x01,0x00,0x60,0x80,0xE0,0x90,0x90,0x60,0x04,0x06,0x06,0x06,0x01, + 0x00,0xF0,0x10,0x10,0x20,0x40,0x40,0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90,0x60, + 0x90,0x90,0x60,0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90,0x90,0x70,0x10,0x60,0x02, + 0x05,0x05,0x06,0x02,0x00,0xC0,0xC0,0x00,0xC0,0xC0,0x02,0x07,0x07,0x06,0x02,0xFE, + 0xC0,0xC0,0x00,0xC0,0x40,0x40,0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x18,0x60,0x80, + 0x60,0x18,0x05,0x03,0x03,0x06,0x00,0x01,0xF8,0x00,0xF8,0x05,0x05,0x05,0x06,0x00, + 0x00,0xC0,0x30,0x08,0x30,0xC0,0x04,0x07,0x07,0x06,0x01,0x00,0x60,0x90,0x10,0x60, + 0x40,0x00,0x40,0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x90,0xA8,0xB0,0x80,0x70,0x05, + 0x06,0x06,0x06,0x00,0x00,0x20,0x50,0x88,0xF8,0x88,0x88,0x05,0x06,0x06,0x06,0x00, + 0x00,0xF0,0x88,0xF0,0x88,0x88,0xF0,0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90,0x80, + 0x80,0x90,0x60,0x04,0x06,0x06,0x06,0x01,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x04, + 0x06,0x06,0x06,0x01,0x00,0xF0,0x80,0xE0,0x80,0x80,0xF0,0x04,0x06,0x06,0x06,0x01, + 0x00,0xF0,0x80,0xE0,0x80,0x80,0x80,0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90,0x80, + 0xB0,0x90,0x60,0x04,0x06,0x06,0x06,0x01,0x00,0x90,0x90,0xF0,0x90,0x90,0x90,0x03, + 0x06,0x06,0x06,0x01,0x00,0xE0,0x40,0x40,0x40,0x40,0xE0,0x05,0x06,0x06,0x06,0x00, + 0x00,0x38,0x10,0x10,0x10,0x90,0x60,0x04,0x06,0x06,0x06,0x01,0x00,0x90,0xA0,0xC0, + 0xA0,0x90,0x90,0x04,0x06,0x06,0x06,0x01,0x00,0x80,0x80,0x80,0x80,0x80,0xF0,0x05, + 0x06,0x06,0x06,0x00,0x00,0x88,0xD8,0xA8,0xA8,0x88,0x88,0x04,0x06,0x06,0x06,0x01, + 0x00,0x90,0xD0,0xB0,0x90,0x90,0x90,0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x88,0x88, + 0x88,0x88,0x70,0x04,0x06,0x06,0x06,0x01,0x00,0xE0,0x90,0x90,0xE0,0x80,0x80,0x04, + 0x07,0x07,0x06,0x01,0xFF,0x60,0x90,0x90,0xD0,0xB0,0x60,0x10,0x04,0x06,0x06,0x06, + 0x01,0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90, + 0x40,0x20,0x90,0x60,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20, + 0x04,0x06,0x06,0x06,0x01,0x00,0x90,0x90,0x90,0x90,0x90,0x60,0x04,0x06,0x06,0x06, + 0x01,0x00,0x90,0x90,0x90,0xF0,0x60,0x60,0x05,0x06,0x06,0x06,0x00,0x00,0x88,0x88, + 0xA8,0xA8,0xD8,0x88,0x05,0x06,0x06,0x06,0x00,0x00,0x88,0x50,0x20,0x20,0x50,0x88, + 0x05,0x06,0x06,0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x04,0x06,0x06,0x06, + 0x01,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x03,0x06,0x06,0x06,0x01,0x00,0xE0,0x80, + 0x80,0x80,0x80,0xE0,0x04,0x06,0x06,0x06,0x01,0x00,0x80,0x80,0x40,0x20,0x10,0x10, + 0x03,0x06,0x06,0x06,0x01,0x00,0xE0,0x20,0x20,0x20,0x20,0xE0,0x05,0x03,0x03,0x06, + 0x00,0x03,0x20,0x50,0x88,0x05,0x01,0x01,0x06,0x00,0xFE,0xF8,0x02,0x02,0x02,0x06, + 0x02,0x04,0x80,0x40,0x04,0x04,0x04,0x06,0x01,0x00,0x70,0x90,0x90,0x70,0x04,0x06, + 0x06,0x06,0x01,0x00,0x80,0x80,0xE0,0x90,0x90,0xE0,0x04,0x04,0x04,0x06,0x01,0x00, + 0x70,0x80,0x80,0x70,0x04,0x06,0x06,0x06,0x01,0x00,0x10,0x10,0x70,0x90,0x90,0x70, + 0x04,0x04,0x04,0x06,0x01,0x00,0x60,0xB0,0xC0,0x70,0x04,0x06,0x06,0x06,0x01,0x00, + 0x20,0x50,0x40,0xE0,0x40,0x40,0x04,0x06,0x06,0x06,0x01,0xFE,0x60,0x90,0x90,0x70, + 0x10,0x60,0x04,0x06,0x06,0x06,0x01,0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x03,0x06, + 0x06,0x06,0x01,0x00,0x40,0x00,0xC0,0x40,0x40,0xE0,0x03,0x08,0x08,0x06,0x01,0xFE, + 0x20,0x00,0x60,0x20,0x20,0x20,0xA0,0x40,0x04,0x06,0x06,0x06,0x01,0x00,0x80,0x80, + 0xA0,0xC0,0xA0,0x90,0x03,0x06,0x06,0x06,0x01,0x00,0xC0,0x40,0x40,0x40,0x40,0xE0, + 0x05,0x04,0x04,0x06,0x00,0x00,0xD0,0xA8,0xA8,0x88,0x04,0x04,0x04,0x06,0x01,0x00, + 0xE0,0x90,0x90,0x90,0x04,0x04,0x04,0x06,0x01,0x00,0x60,0x90,0x90,0x60,0x04,0x06, + 0x06,0x06,0x01,0xFE,0xE0,0x90,0x90,0xE0,0x80,0x80,0x04,0x06,0x06,0x06,0x01,0xFE, + 0x70,0x90,0x90,0x70,0x10,0x10,0x04,0x04,0x04,0x06,0x01,0x00,0xA0,0xD0,0x80,0x80, + 0x04,0x04,0x04,0x06,0x01,0x00,0x70,0xC0,0x30,0xE0,0x04,0x06,0x06,0x06,0x01,0x00, + 0x40,0x40,0xE0,0x40,0x50,0x20,0x04,0x04,0x04,0x06,0x01,0x00,0x90,0x90,0x90,0x70, + 0x04,0x04,0x04,0x06,0x01,0x00,0x90,0x90,0x60,0x60,0x05,0x04,0x04,0x06,0x00,0x00, + 0x88,0xA8,0xA8,0x50,0x04,0x04,0x04,0x06,0x01,0x00,0x90,0x60,0x60,0x90,0x04,0x06, + 0x06,0x06,0x01,0xFE,0x90,0x90,0x90,0x70,0x90,0x60,0x04,0x04,0x04,0x06,0x01,0x00, + 0xF0,0x20,0x40,0xF0,0x03,0x07,0x07,0x06,0x01,0x00,0x20,0x40,0x40,0x80,0x40,0x40, + 0x20,0x01,0x07,0x07,0x06,0x02,0xFF,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x03,0x07, + 0x07,0x06,0x01,0x00,0x80,0x40,0x40,0x20,0x40,0x40,0x80,0x04,0x02,0x02,0x06,0x01, + 0x03,0x50,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x06,0x05,0xFF,0x01,0x06,0x06,0x06,0x02,0x00, + 0x80,0x00,0x80,0x80,0x80,0x80,0x04,0x06,0x06,0x06,0x01,0xFF,0x20,0x70,0xA0,0xA0, + 0x70,0x20,0x05,0x07,0x07,0x06,0x00,0xFF,0x30,0x48,0x40,0xF0,0x40,0x40,0xF8,0x05, + 0x05,0x05,0x06,0x00,0x00,0xA8,0x50,0x88,0x50,0xA8,0x05,0x06,0x06,0x06,0x00,0x00, + 0x88,0x50,0xF8,0x20,0xF8,0x20,0x01,0x07,0x07,0x06,0x02,0xFF,0x80,0x80,0x80,0x00, + 0x80,0x80,0x80,0x04,0x07,0x07,0x06,0x01,0xFF,0x70,0x80,0x60,0x90,0x60,0x10,0xE0, + 0x03,0x01,0x01,0x06,0x01,0x05,0xA0,0x06,0x07,0x07,0x06,0x00,0x00,0x78,0x84,0x94, + 0xA4,0x94,0x84,0x78,0x03,0x05,0x05,0x06,0x01,0x01,0x60,0xA0,0x60,0x00,0xE0,0x05, + 0x05,0x05,0x06,0x00,0x00,0x28,0x50,0xA0,0x50,0x28,0x04,0x03,0x03,0x06,0x01,0x00, + 0xF0,0x10,0x10,0x04,0x01,0x01,0x06,0x01,0x02,0xF0,0x06,0x07,0x07,0x06,0x00,0x00, + 0x78,0x84,0xB4,0xA4,0xA4,0x84,0x78,0x04,0x01,0x01,0x06,0x01,0x05,0xF0,0x04,0x03, + 0x03,0x06,0x01,0x02,0x60,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0xFF,0x20,0x20,0xF8, + 0x20,0x20,0x00,0xF8,0x03,0x05,0x05,0x06,0x01,0x01,0x40,0xA0,0x20,0x40,0xE0,0x03, + 0x05,0x05,0x06,0x01,0x01,0xC0,0x20,0x40,0x20,0xC0,0x02,0x02,0x02,0x06,0x02,0x04, + 0x40,0x80,0x04,0x05,0x05,0x06,0x01,0xFF,0x90,0x90,0xB0,0xD0,0x80,0x05,0x06,0x06, + 0x06,0x00,0x00,0x78,0xE8,0xE8,0x68,0x28,0x28,0x01,0x01,0x01,0x06,0x02,0x02,0x80, + 0x02,0x02,0x02,0x06,0x02,0xFE,0x40,0x80,0x03,0x05,0x05,0x06,0x01,0x01,0x40,0xC0, + 0x40,0x40,0xE0,0x03,0x05,0x05,0x06,0x01,0x01,0x40,0xA0,0x40,0x00,0xE0,0x05,0x05, + 0x05,0x06,0x00,0x00,0xA0,0x50,0x28,0x50,0xA0,0x05,0x08,0x08,0x06,0x00,0xFF,0x40, + 0xC0,0x40,0x50,0x70,0x30,0x78,0x10,0x05,0x08,0x08,0x06,0x00,0xFF,0x40,0xC0,0x40, + 0x50,0x68,0x08,0x10,0x38,0x05,0x08,0x08,0x06,0x00,0xFF,0xC0,0x20,0x40,0x30,0xF0, + 0x30,0x78,0x10,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x00,0x20,0x60,0x80,0x90,0x60, + 0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x20,0x20,0x50,0x70,0x88,0x88,0x05,0x07,0x07, + 0x06,0x00,0x00,0x10,0x20,0x20,0x50,0x70,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00, + 0x20,0x50,0x20,0x50,0x70,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x28,0x50,0x20, + 0x50,0x70,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x50,0x00,0x20,0x50,0x70,0x88, + 0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x50,0x20,0x50,0x70,0x88,0x88,0x05,0x06, + 0x06,0x06,0x00,0x00,0x78,0xA0,0xF0,0xA0,0xA0,0xB8,0x04,0x08,0x08,0x06,0x01,0xFE, + 0x60,0x90,0x80,0x80,0x90,0x60,0x20,0x40,0x04,0x07,0x07,0x06,0x01,0x00,0x40,0x20, + 0xF0,0x80,0xE0,0x80,0xF0,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x40,0xF0,0x80,0xE0, + 0x80,0xF0,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x50,0xF0,0x80,0xE0,0x80,0xF0,0x04, + 0x07,0x07,0x06,0x01,0x00,0x50,0x00,0xF0,0x80,0xE0,0x80,0xF0,0x03,0x07,0x07,0x06, + 0x01,0x00,0x80,0x40,0xE0,0x40,0x40,0x40,0xE0,0x03,0x07,0x07,0x06,0x01,0x00,0x20, + 0x40,0xE0,0x40,0x40,0x40,0xE0,0x03,0x07,0x07,0x06,0x01,0x00,0x40,0xA0,0xE0,0x40, + 0x40,0x40,0xE0,0x03,0x07,0x07,0x06,0x01,0x00,0xA0,0x00,0xE0,0x40,0x40,0x40,0xE0, + 0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x48,0xE8,0x48,0x48,0x70,0x04,0x07,0x07,0x06, + 0x01,0x00,0x50,0xA0,0x90,0xD0,0xB0,0x90,0x90,0x04,0x07,0x07,0x06,0x01,0x00,0x40, + 0x20,0x60,0x90,0x90,0x90,0x60,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x40,0x60,0x90, + 0x90,0x90,0x60,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x50,0x60,0x90,0x90,0x90,0x60, + 0x04,0x07,0x07,0x06,0x01,0x00,0x50,0xA0,0x60,0x90,0x90,0x90,0x60,0x04,0x07,0x07, + 0x06,0x01,0x00,0x50,0x00,0x60,0x90,0x90,0x90,0x60,0x05,0x05,0x05,0x06,0x00,0x00, + 0x88,0x50,0x20,0x50,0x88,0x04,0x08,0x08,0x06,0x01,0xFF,0x10,0x70,0xB0,0xB0,0xD0, + 0xD0,0xE0,0x80,0x04,0x07,0x07,0x06,0x01,0x00,0x40,0x20,0x90,0x90,0x90,0x90,0x60, + 0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x40,0x90,0x90,0x90,0x90,0x60,0x04,0x07,0x07, + 0x06,0x01,0x00,0x20,0x50,0x90,0x90,0x90,0x90,0x60,0x04,0x07,0x07,0x06,0x01,0x00, + 0x50,0x00,0x90,0x90,0x90,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0x20,0x88, + 0x50,0x20,0x20,0x20,0x04,0x06,0x06,0x06,0x01,0x00,0x80,0xE0,0x90,0x90,0xE0,0x80, + 0x04,0x06,0x06,0x06,0x01,0x00,0x60,0x90,0xA0,0xA0,0x90,0xA0,0x04,0x07,0x07,0x06, + 0x01,0x00,0x40,0x20,0x00,0x70,0x90,0x90,0x70,0x04,0x07,0x07,0x06,0x01,0x00,0x20, + 0x40,0x00,0x70,0x90,0x90,0x70,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x50,0x00,0x70, + 0x90,0x90,0x70,0x04,0x07,0x07,0x06,0x01,0x00,0x50,0xA0,0x00,0x70,0x90,0x90,0x70, + 0x04,0x06,0x06,0x06,0x01,0x00,0x50,0x00,0x70,0x90,0x90,0x70,0x04,0x07,0x07,0x06, + 0x01,0x00,0x20,0x50,0x20,0x70,0x90,0x90,0x70,0x05,0x04,0x04,0x06,0x00,0x00,0x70, + 0xA8,0xB0,0x78,0x04,0x06,0x06,0x06,0x01,0xFE,0x70,0x80,0x80,0x70,0x20,0x40,0x04, + 0x07,0x07,0x06,0x01,0x00,0x40,0x20,0x00,0x60,0xB0,0xC0,0x70,0x04,0x07,0x07,0x06, + 0x01,0x00,0x20,0x40,0x00,0x60,0xB0,0xC0,0x70,0x04,0x07,0x07,0x06,0x01,0x00,0x20, + 0x50,0x00,0x60,0xB0,0xC0,0x70,0x04,0x06,0x06,0x06,0x01,0x00,0x50,0x00,0x60,0xB0, + 0xC0,0x70,0x03,0x07,0x07,0x06,0x01,0x00,0x80,0x40,0x00,0xC0,0x40,0x40,0xE0,0x03, + 0x07,0x07,0x06,0x01,0x00,0x20,0x40,0x00,0xC0,0x40,0x40,0xE0,0x03,0x07,0x07,0x06, + 0x01,0x00,0x40,0xA0,0x00,0xC0,0x40,0x40,0xE0,0x03,0x06,0x06,0x06,0x01,0x00,0xA0, + 0x00,0xC0,0x40,0x40,0xE0,0x04,0x07,0x07,0x06,0x01,0x00,0x30,0x60,0x10,0x70,0x90, + 0x90,0x60,0x04,0x07,0x07,0x06,0x01,0x00,0x50,0xA0,0x00,0xE0,0x90,0x90,0x90,0x04, + 0x07,0x07,0x06,0x01,0x00,0x40,0x20,0x00,0x60,0x90,0x90,0x60,0x04,0x07,0x07,0x06, + 0x01,0x00,0x20,0x40,0x00,0x60,0x90,0x90,0x60,0x04,0x07,0x07,0x06,0x01,0x00,0x20, + 0x50,0x00,0x60,0x90,0x90,0x60,0x04,0x07,0x07,0x06,0x01,0x00,0x50,0xA0,0x00,0x60, + 0x90,0x90,0x60,0x04,0x06,0x06,0x06,0x01,0x00,0x50,0x00,0x60,0x90,0x90,0x60,0x05, + 0x05,0x05,0x06,0x00,0x00,0x20,0x00,0xF8,0x00,0x20,0x04,0x04,0x04,0x06,0x01,0x00, + 0x70,0xB0,0xD0,0xE0,0x04,0x07,0x07,0x06,0x01,0x00,0x40,0x20,0x00,0x90,0x90,0x90, + 0x70,0x04,0x07,0x07,0x06,0x01,0x00,0x20,0x40,0x00,0x90,0x90,0x90,0x70,0x04,0x07, + 0x07,0x06,0x01,0x00,0x20,0x50,0x00,0x90,0x90,0x90,0x70,0x04,0x06,0x06,0x06,0x01, + 0x00,0x50,0x00,0x90,0x90,0x90,0x70,0x04,0x09,0x09,0x06,0x01,0xFE,0x20,0x40,0x00, + 0x90,0x90,0x90,0x70,0x90,0x60,0x04,0x08,0x08,0x06,0x01,0xFE,0x80,0x80,0xE0,0x90, + 0x90,0xE0,0x80,0x80,0x04,0x08,0x08,0x06,0x01,0xFE,0x50,0x00,0x90,0x90,0x90,0x70, + 0x90,0x60}; diff --git a/src/lcd/dogm/fontdata/fontdata_ISO10646_1.h b/src/lcd/dogm/fontdata/fontdata_ISO10646_1.h new file mode 100644 index 0000000..6f55d3b --- /dev/null +++ b/src/lcd/dogm/fontdata/fontdata_ISO10646_1.h @@ -0,0 +1,305 @@ +/** + * 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 + +#if defined(__AVR__) && ENABLED(NOT_EXTENDED_ISO10646_1_5X7) + // reduced font (only symbols 1 - 127) - saves about 1278 bytes of FLASH + +/* + Fontname: -Marlin6x12-Fixed-Medium-R-SemiCondensed--12-90-100-100-C-111-ISO10646-1 + Copyright: Public domain terminal emulator font. Share and enjoy. original font -Misc-Fixed-Medium-R-SemiCondensed--12-110-75-75-C-60-ISO10646-1 + Capital A Height: 7, '1' Height: 7 + Calculated Max Values w= 7 h=10 x= 5 y= 5 dx= 7 dy= 0 ascent= 8 len=10 + Font Bounding box w=12 h=15 x= 0 y=-2 + Calculated Min Values x= 0 y=-2 dx= 0 dy= 0 + Pure Font ascent = 7 descent=-2 + X Font ascent = 8 descent=-2 + Max Font ascent = 8 descent=-2 +*/ +const u8g_fntpgm_uint8_t ISO10646_1_5x7[1324] U8G_FONT_SECTION("ISO10646_1_5x7") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x07,0x02,0x25,0x03,0xBB,0x01,0x7F,0xFE,0x08,0xFE,0x08, + 0xFE,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0xF0,0xC8,0x88,0x88,0x98,0x78,0x10,0x05, + 0x08,0x08,0x06,0x00,0x00,0xC0,0xF8,0x88,0x88,0x88,0x88,0x88,0xF8,0x05,0x05,0x05, + 0x06,0x00,0x01,0x20,0x30,0xF8,0x30,0x20,0x05,0x08,0x08,0x06,0x00,0x00,0x20,0x70, + 0xF8,0x20,0x20,0x20,0x20,0xE0,0x05,0x09,0x09,0x06,0x00,0xFF,0x20,0x70,0xA8,0xA8, + 0xB8,0x88,0x88,0x70,0x20,0x07,0x05,0x05,0x07,0x00,0x01,0xD8,0x6C,0x36,0x6C,0xD8, + 0x05,0x09,0x09,0x06,0x00,0xFF,0xF8,0xA8,0x88,0x88,0x88,0x88,0x88,0xA8,0xF8,0x05, + 0x0A,0x0A,0x06,0x00,0xFE,0x20,0x50,0x50,0x50,0x50,0x88,0xA8,0xA8,0x88,0x70,0x03, + 0x03,0x03,0x06,0x00,0x03,0x40,0xA0,0x40,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00, + 0x00,0x06,0x05,0xFF,0x01,0x07,0x07,0x06,0x02,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x80,0x03,0x03,0x03,0x06,0x01,0x05,0xA0,0xA0,0xA0,0x05,0x06,0x06,0x06,0x00,0x00, + 0x50,0xF8,0x50,0x50,0xF8,0x50,0x05,0x09,0x09,0x06,0x00,0xFF,0x20,0x70,0xA8,0xA0, + 0x70,0x28,0xA8,0x70,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0xC8,0xC8,0x10,0x20,0x40, + 0x98,0x98,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x01, + 0x03,0x03,0x06,0x02,0x05,0x80,0x80,0x80,0x03,0x09,0x09,0x06,0x01,0xFF,0x20,0x40, + 0x40,0x80,0x80,0x80,0x40,0x40,0x20,0x03,0x09,0x09,0x06,0x01,0xFF,0x80,0x40,0x40, + 0x20,0x20,0x20,0x40,0x40,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0xA8,0x70,0x20, + 0x70,0xA8,0x20,0x05,0x05,0x05,0x06,0x00,0x01,0x20,0x20,0xF8,0x20,0x20,0x02,0x03, + 0x03,0x06,0x01,0xFF,0xC0,0x40,0x80,0x05,0x01,0x01,0x06,0x00,0x03,0xF8,0x02,0x02, + 0x02,0x06,0x01,0x00,0xC0,0xC0,0x05,0x07,0x07,0x06,0x00,0x00,0x08,0x10,0x10,0x20, + 0x40,0x40,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x98,0xA8,0xC8,0x88,0x70, + 0x03,0x07,0x07,0x06,0x01,0x00,0x40,0xC0,0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07, + 0x06,0x00,0x00,0x70,0x88,0x08,0x10,0x20,0x40,0xF8,0x05,0x07,0x07,0x06,0x00,0x00, + 0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0x30,0x50, + 0x90,0xF8,0x10,0x10,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0xF0,0x08,0x08,0x88, + 0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x30,0x40,0x80,0xF0,0x88,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF8,0x08,0x10,0x10,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88, + 0x88,0x78,0x08,0x10,0x60,0x02,0x05,0x05,0x06,0x01,0x00,0xC0,0xC0,0x00,0xC0,0xC0, + 0x02,0x06,0x06,0x06,0x01,0xFF,0xC0,0xC0,0x00,0xC0,0x40,0x80,0x03,0x05,0x05,0x06, + 0x01,0x01,0x20,0x40,0x80,0x40,0x20,0x05,0x03,0x03,0x06,0x00,0x02,0xF8,0x00,0xF8, + 0x03,0x05,0x05,0x06,0x01,0x01,0x80,0x40,0x20,0x40,0x80,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x10,0x20,0x20,0x00,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88, + 0xB8,0xA8,0xB8,0x80,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88, + 0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x48,0x48,0x70,0x48,0x48,0xF0,0x05, + 0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x05,0x07,0x07,0x06, + 0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0xF8, + 0x80,0x80,0xF0,0x80,0x80,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0, + 0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x80,0x98,0x88,0x70, + 0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x03,0x07,0x07, + 0x06,0x01,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07,0x06,0x00,0x00, + 0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0, + 0xC0,0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80, + 0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88, + 0x88,0xF0,0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0xA8, + 0x90,0x68,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x05, + 0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x05,0x07,0x07,0x06, + 0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88, + 0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x88, + 0x50,0x50,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x88,0xA8,0xA8,0x50, + 0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x05,0x07,0x07, + 0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00, + 0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,0x03,0x09,0x09,0x06,0x01,0xFF,0xE0,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x40,0x40,0x20, + 0x10,0x10,0x08,0x03,0x09,0x09,0x06,0x01,0xFF,0xE0,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0xE0,0x05,0x03,0x03,0x06,0x00,0x05,0x20,0x50,0x88,0x05,0x01,0x01,0x06,0x00, + 0xFE,0xF8,0x03,0x03,0x03,0x06,0x01,0x05,0x80,0x40,0x20,0x05,0x05,0x05,0x06,0x00, + 0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x80,0xF0,0x88, + 0x88,0x88,0xF0,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x80,0x80,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x05,0x05,0x05,0x06,0x00, + 0x00,0x70,0x88,0xF0,0x80,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x30,0x48,0x40,0xE0, + 0x40,0x40,0x40,0x05,0x07,0x07,0x06,0x00,0xFE,0x70,0x88,0x88,0x88,0x78,0x08,0x70, + 0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x88,0x03,0x07,0x07, + 0x06,0x01,0x00,0x40,0x00,0xC0,0x40,0x40,0x40,0xE0,0x04,0x09,0x09,0x06,0x01,0xFE, + 0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x80, + 0x80,0x88,0x90,0xE0,0x90,0x88,0x03,0x07,0x07,0x06,0x01,0x00,0xC0,0x40,0x40,0x40, + 0x40,0x40,0xE0,0x05,0x05,0x05,0x06,0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x05,0x05, + 0x05,0x06,0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x70, + 0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0xFE,0xF0,0x88,0x88,0x88,0xF0,0x80, + 0x80,0x05,0x07,0x07,0x06,0x00,0xFE,0x78,0x88,0x88,0x88,0x78,0x08,0x08,0x05,0x05, + 0x05,0x06,0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x78, + 0x80,0x70,0x08,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x20, + 0x18,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x05,0x05,0x05,0x06, + 0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0xA8, + 0xA8,0x50,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x05,0x07,0x07, + 0x06,0x00,0xFE,0x88,0x88,0x88,0x50,0x20,0x40,0x80,0x05,0x05,0x05,0x06,0x00,0x00, + 0xF8,0x10,0x20,0x40,0xF8,0x03,0x09,0x09,0x06,0x01,0xFF,0x20,0x40,0x40,0x40,0x80, + 0x40,0x40,0x40,0x20,0x01,0x09,0x09,0x06,0x02,0xFF,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x03,0x09,0x09,0x06,0x01,0xFF,0x80,0x40,0x40,0x40,0x20,0x40,0x40, + 0x40,0x80,0x05,0x03,0x03,0x06,0x00,0x02,0x48,0xA8,0x90,0xFF}; +#else + // extended (original) font (symbols 1 - 255) + +/* + Fontname: -Marlin6x12-Fixed-Medium-R-SemiCondensed--12-90-100-100-C-111-ISO10646-1 + Copyright: Public domain terminal emulator font. Share and enjoy. original font -Misc-Fixed-Medium-R-SemiCondensed--12-110-75-75-C-60-ISO10646-1 + Capital A Height: 7, '1' Height: 7 + Calculated Max Values w= 7 h=10 x= 5 y= 7 dx= 7 dy= 0 ascent=10 len=10 + Font Bounding box w=12 h=15 x= 0 y=-2 + Calculated Min Values x= 0 y=-2 dx= 0 dy= 0 + Pure Font ascent = 7 descent=-2 + X Font ascent = 8 descent=-2 + Max Font ascent =10 descent=-2 +*/ +const u8g_fntpgm_uint8_t ISO10646_1_5x7[2647] U8G_FONT_SECTION("ISO10646_1_5x7") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x07,0x02,0x25,0x03,0xBB,0x01,0xFF,0xFE,0x0A,0xFE,0x08, + 0xFE,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0xF0,0xC8,0x88,0x88,0x98,0x78,0x10,0x05, + 0x08,0x08,0x06,0x00,0x00,0xC0,0xF8,0x88,0x88,0x88,0x88,0x88,0xF8,0x05,0x05,0x05, + 0x06,0x00,0x01,0x20,0x30,0xF8,0x30,0x20,0x05,0x08,0x08,0x06,0x00,0x00,0x20,0x70, + 0xF8,0x20,0x20,0x20,0x20,0xE0,0x05,0x09,0x09,0x06,0x00,0xFF,0x20,0x70,0xA8,0xA8, + 0xB8,0x88,0x88,0x70,0x20,0x07,0x05,0x05,0x07,0x00,0x01,0xD8,0x6C,0x36,0x6C,0xD8, + 0x05,0x09,0x09,0x06,0x00,0xFF,0xF8,0xA8,0x88,0x88,0x88,0x88,0x88,0xA8,0xF8,0x05, + 0x0A,0x0A,0x06,0x00,0xFE,0x20,0x50,0x50,0x50,0x50,0x88,0xA8,0xA8,0x88,0x70,0x03, + 0x03,0x03,0x06,0x00,0x03,0x40,0xA0,0x40,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00, + 0x00,0x06,0x05,0xFF,0x01,0x07,0x07,0x06,0x02,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x80,0x03,0x03,0x03,0x06,0x01,0x05,0xA0,0xA0,0xA0,0x05,0x06,0x06,0x06,0x00,0x00, + 0x50,0xF8,0x50,0x50,0xF8,0x50,0x05,0x09,0x09,0x06,0x00,0xFF,0x20,0x70,0xA8,0xA0, + 0x70,0x28,0xA8,0x70,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0xC8,0xC8,0x10,0x20,0x40, + 0x98,0x98,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x01, + 0x03,0x03,0x06,0x02,0x05,0x80,0x80,0x80,0x03,0x09,0x09,0x06,0x01,0xFF,0x20,0x40, + 0x40,0x80,0x80,0x80,0x40,0x40,0x20,0x03,0x09,0x09,0x06,0x01,0xFF,0x80,0x40,0x40, + 0x20,0x20,0x20,0x40,0x40,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0xA8,0x70,0x20, + 0x70,0xA8,0x20,0x05,0x05,0x05,0x06,0x00,0x01,0x20,0x20,0xF8,0x20,0x20,0x02,0x03, + 0x03,0x06,0x01,0xFF,0xC0,0x40,0x80,0x05,0x01,0x01,0x06,0x00,0x03,0xF8,0x02,0x02, + 0x02,0x06,0x01,0x00,0xC0,0xC0,0x05,0x07,0x07,0x06,0x00,0x00,0x08,0x10,0x10,0x20, + 0x40,0x40,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x98,0xA8,0xC8,0x88,0x70, + 0x03,0x07,0x07,0x06,0x01,0x00,0x40,0xC0,0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07, + 0x06,0x00,0x00,0x70,0x88,0x08,0x10,0x20,0x40,0xF8,0x05,0x07,0x07,0x06,0x00,0x00, + 0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0x30,0x50, + 0x90,0xF8,0x10,0x10,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0xF0,0x08,0x08,0x88, + 0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x30,0x40,0x80,0xF0,0x88,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF8,0x08,0x10,0x10,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88, + 0x88,0x78,0x08,0x10,0x60,0x02,0x05,0x05,0x06,0x01,0x00,0xC0,0xC0,0x00,0xC0,0xC0, + 0x02,0x06,0x06,0x06,0x01,0xFF,0xC0,0xC0,0x00,0xC0,0x40,0x80,0x03,0x05,0x05,0x06, + 0x01,0x01,0x20,0x40,0x80,0x40,0x20,0x05,0x03,0x03,0x06,0x00,0x02,0xF8,0x00,0xF8, + 0x03,0x05,0x05,0x06,0x01,0x01,0x80,0x40,0x20,0x40,0x80,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x10,0x20,0x20,0x00,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88, + 0xB8,0xA8,0xB8,0x80,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88, + 0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x48,0x48,0x70,0x48,0x48,0xF0,0x05, + 0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x05,0x07,0x07,0x06, + 0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0xF8, + 0x80,0x80,0xF0,0x80,0x80,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0, + 0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x80,0x98,0x88,0x70, + 0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x03,0x07,0x07, + 0x06,0x01,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07,0x06,0x00,0x00, + 0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0, + 0xC0,0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80, + 0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88, + 0x88,0xF0,0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0xA8, + 0x90,0x68,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x05, + 0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x05,0x07,0x07,0x06, + 0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88, + 0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x88, + 0x50,0x50,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x88,0xA8,0xA8,0x50, + 0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x05,0x07,0x07, + 0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00, + 0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,0x03,0x09,0x09,0x06,0x01,0xFF,0xE0,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x40,0x40,0x20, + 0x10,0x10,0x08,0x03,0x09,0x09,0x06,0x01,0xFF,0xE0,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0xE0,0x05,0x03,0x03,0x06,0x00,0x05,0x20,0x50,0x88,0x05,0x01,0x01,0x06,0x00, + 0xFE,0xF8,0x03,0x03,0x03,0x06,0x01,0x05,0x80,0x40,0x20,0x05,0x05,0x05,0x06,0x00, + 0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x80,0xF0,0x88, + 0x88,0x88,0xF0,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x80,0x80,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x05,0x05,0x05,0x06,0x00, + 0x00,0x70,0x88,0xF0,0x80,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x30,0x48,0x40,0xE0, + 0x40,0x40,0x40,0x05,0x07,0x07,0x06,0x00,0xFE,0x70,0x88,0x88,0x88,0x78,0x08,0x70, + 0x05,0x07,0x07,0x06,0x00,0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x88,0x03,0x07,0x07, + 0x06,0x01,0x00,0x40,0x00,0xC0,0x40,0x40,0x40,0xE0,0x04,0x09,0x09,0x06,0x01,0xFE, + 0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x80, + 0x80,0x88,0x90,0xE0,0x90,0x88,0x03,0x07,0x07,0x06,0x01,0x00,0xC0,0x40,0x40,0x40, + 0x40,0x40,0xE0,0x05,0x05,0x05,0x06,0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x05,0x05, + 0x05,0x06,0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x70, + 0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0xFE,0xF0,0x88,0x88,0x88,0xF0,0x80, + 0x80,0x05,0x07,0x07,0x06,0x00,0xFE,0x78,0x88,0x88,0x88,0x78,0x08,0x08,0x05,0x05, + 0x05,0x06,0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x78, + 0x80,0x70,0x08,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x20, + 0x18,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x05,0x05,0x05,0x06, + 0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0xA8, + 0xA8,0x50,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x05,0x07,0x07, + 0x06,0x00,0xFE,0x88,0x88,0x88,0x50,0x20,0x40,0x80,0x05,0x05,0x05,0x06,0x00,0x00, + 0xF8,0x10,0x20,0x40,0xF8,0x03,0x09,0x09,0x06,0x01,0xFF,0x20,0x40,0x40,0x40,0x80, + 0x40,0x40,0x40,0x20,0x01,0x09,0x09,0x06,0x02,0xFF,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x03,0x09,0x09,0x06,0x01,0xFF,0x80,0x40,0x40,0x40,0x20,0x40,0x40, + 0x40,0x80,0x05,0x03,0x03,0x06,0x00,0x02,0x48,0xA8,0x90,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x06, + 0x05,0xFF,0x01,0x07,0x07,0x06,0x02,0x00,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x05, + 0x07,0x07,0x06,0x00,0xFF,0x20,0x70,0xA8,0xA0,0xA8,0x70,0x20,0x05,0x07,0x07,0x06, + 0x00,0x00,0x30,0x48,0x40,0xE0,0x40,0x48,0xB0,0x05,0x05,0x05,0x06,0x00,0x00,0xA8, + 0x50,0x88,0x50,0xA8,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x50,0xF8,0x20,0xF8,0x20, + 0x20,0x01,0x07,0x07,0x06,0x02,0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x04,0x08, + 0x08,0x06,0x01,0x00,0x70,0x80,0x60,0x90,0x90,0x60,0x10,0xE0,0x03,0x01,0x01,0x06, + 0x01,0x07,0xA0,0x06,0x07,0x07,0x06,0x00,0x00,0x78,0x84,0xB4,0xA4,0xB4,0x84,0x78, + 0x03,0x05,0x05,0x06,0x01,0x04,0x60,0xA0,0x60,0x00,0xE0,0x05,0x05,0x05,0x06,0x00, + 0x00,0x28,0x50,0xA0,0x50,0x28,0x05,0x03,0x03,0x06,0x00,0x01,0xF8,0x08,0x08,0x03, + 0x01,0x01,0x06,0x01,0x03,0xE0,0x06,0x07,0x07,0x06,0x00,0x00,0x78,0x84,0xB4,0xA4, + 0xA4,0x84,0x78,0x05,0x01,0x01,0x06,0x00,0x07,0xF8,0x04,0x04,0x04,0x06,0x01,0x05, + 0x60,0x90,0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00, + 0xF8,0x03,0x05,0x05,0x06,0x01,0x04,0x40,0xA0,0x20,0x40,0xE0,0x03,0x05,0x05,0x06, + 0x01,0x04,0xC0,0x20,0x40,0x20,0xC0,0x03,0x03,0x03,0x06,0x01,0x05,0x20,0x40,0x80, + 0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88,0x98,0xE8,0x80,0x80,0x05,0x08,0x08, + 0x06,0x00,0x00,0x78,0xE8,0xE8,0xE8,0x68,0x28,0x28,0x28,0x02,0x02,0x02,0x06,0x02, + 0x03,0xC0,0xC0,0x03,0x02,0x02,0x06,0x01,0xFE,0x20,0xC0,0x03,0x05,0x05,0x06,0x01, + 0x04,0x40,0xC0,0x40,0x40,0xE0,0x03,0x05,0x05,0x06,0x01,0x05,0x40,0xA0,0x40,0x00, + 0xE0,0x05,0x05,0x05,0x06,0x00,0x00,0xA0,0x50,0x28,0x50,0xA0,0x05,0x0A,0x0A,0x06, + 0x00,0x00,0x40,0xC0,0x48,0x50,0x60,0x50,0xB0,0x50,0x78,0x10,0x05,0x0A,0x0A,0x06, + 0x00,0x00,0x40,0xC0,0x48,0x50,0x60,0x50,0xA8,0x08,0x10,0x38,0x05,0x0A,0x0A,0x06, + 0x00,0x00,0xC0,0x20,0x48,0x30,0xE0,0x50,0xB0,0x50,0x78,0x10,0x05,0x07,0x07,0x06, + 0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x88,0x70,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40, + 0x20,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x10, + 0x20,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x20, + 0x50,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x68, + 0xB0,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0x00,0x50, + 0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x20,0x50, + 0x20,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x78,0xA0, + 0xA0,0xF0,0xA0,0xA0,0xB8,0x05,0x09,0x09,0x06,0x00,0xFE,0x70,0x88,0x80,0x80,0x80, + 0x88,0x70,0x10,0x60,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40,0x20,0x00,0xF8,0x80,0x80, + 0xF0,0x80,0x80,0xF8,0x05,0x0A,0x0A,0x06,0x00,0x00,0x10,0x20,0x00,0xF8,0x80,0x80, + 0xF0,0x80,0x80,0xF8,0x05,0x0A,0x0A,0x06,0x00,0x00,0x20,0x50,0x00,0xF8,0x80,0x80, + 0xF0,0x80,0x80,0xF8,0x05,0x09,0x09,0x06,0x00,0x00,0x50,0x00,0xF8,0x80,0x80,0xF0, + 0x80,0x80,0xF8,0x03,0x0A,0x0A,0x06,0x01,0x00,0x80,0x40,0x00,0xE0,0x40,0x40,0x40, + 0x40,0x40,0xE0,0x03,0x0A,0x0A,0x06,0x01,0x00,0x20,0x40,0x00,0xE0,0x40,0x40,0x40, + 0x40,0x40,0xE0,0x03,0x0A,0x0A,0x06,0x01,0x00,0x40,0xA0,0x00,0xE0,0x40,0x40,0x40, + 0x40,0x40,0xE0,0x03,0x09,0x09,0x06,0x01,0x00,0xA0,0x00,0xE0,0x40,0x40,0x40,0x40, + 0x40,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x48,0x48,0xE8,0x48,0x48,0x70,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x68,0xB0,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x40,0x20,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x20,0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x68,0xB0,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05, + 0x09,0x09,0x06,0x00,0x00,0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x05, + 0x05,0x06,0x00,0x01,0x88,0x50,0x20,0x50,0x88,0x05,0x09,0x09,0x06,0x00,0xFF,0x08, + 0x70,0x98,0xA8,0xA8,0xA8,0xC8,0x70,0x80,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40,0x20, + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x0A,0x0A,0x06,0x00,0x00,0x10,0x20, + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x0A,0x0A,0x06,0x00,0x00,0x20,0x50, + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x09,0x09,0x06,0x00,0x00,0x50,0x00, + 0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x0A,0x0A,0x06,0x00,0x00,0x10,0x20,0x00, + 0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x04,0x07,0x07,0x06,0x01,0x00,0x80,0xE0,0x90, + 0x90,0x90,0xE0,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x90,0xA0,0x90,0x88, + 0xB0,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0x20,0x00,0x70,0x08,0x78,0x88,0x78,0x05, + 0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x08,0x08, + 0x06,0x00,0x00,0x20,0x50,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x08,0x08,0x06,0x00, + 0x00,0x68,0xB0,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00,0x00,0x50, + 0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x08,0x08,0x06,0x00,0x00,0x20,0x50,0x20,0x70, + 0x08,0x78,0x88,0x78,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x28,0x70,0xA0,0x78,0x05, + 0x07,0x07,0x06,0x00,0xFE,0x70,0x88,0x80,0x88,0x70,0x10,0x60,0x05,0x08,0x08,0x06, + 0x00,0x00,0x40,0x20,0x00,0x70,0x88,0xF0,0x80,0x70,0x05,0x08,0x08,0x06,0x00,0x00, + 0x10,0x20,0x00,0x70,0x88,0xF0,0x80,0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x20,0x50, + 0x00,0x70,0x88,0xF0,0x80,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x50,0x00,0x70,0x88, + 0xF0,0x80,0x70,0x03,0x08,0x08,0x06,0x01,0x00,0x80,0x40,0x00,0xC0,0x40,0x40,0x40, + 0xE0,0x03,0x08,0x08,0x06,0x01,0x00,0x20,0x40,0x00,0xC0,0x40,0x40,0x40,0xE0,0x03, + 0x08,0x08,0x06,0x01,0x00,0x40,0xA0,0x00,0xC0,0x40,0x40,0x40,0xE0,0x03,0x07,0x07, + 0x06,0x01,0x00,0xA0,0x00,0xC0,0x40,0x40,0x40,0xE0,0x05,0x09,0x09,0x06,0x00,0x00, + 0x50,0x20,0x50,0x08,0x78,0x88,0x88,0x88,0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x68, + 0xB0,0x00,0xB0,0xC8,0x88,0x88,0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0x20,0x00, + 0x70,0x88,0x88,0x88,0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88, + 0x88,0x88,0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x20,0x50,0x00,0x70,0x88,0x88,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x68,0xB0,0x00,0x70,0x88,0x88,0x88,0x70,0x05, + 0x07,0x07,0x06,0x00,0x00,0x50,0x00,0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06, + 0x00,0x01,0x20,0x00,0xF8,0x00,0x20,0x05,0x05,0x05,0x06,0x00,0x00,0x78,0x98,0xA8, + 0xC8,0xF0,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0x20,0x00,0x88,0x88,0x88,0x88,0x70, + 0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x88,0x88,0x88,0x88,0x70,0x05,0x08, + 0x08,0x06,0x00,0x00,0x20,0x50,0x00,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06, + 0x00,0x00,0x50,0x00,0x88,0x88,0x88,0x88,0x70,0x05,0x0A,0x0A,0x06,0x00,0xFE,0x10, + 0x20,0x00,0x88,0x88,0x88,0x50,0x20,0x40,0x80,0x05,0x09,0x09,0x06,0x00,0xFE,0x80, + 0x80,0xF0,0x88,0x88,0x88,0xF0,0x80,0x80,0x05,0x09,0x09,0x06,0x00,0xFE,0x50,0x00, + 0x88,0x88,0x88,0x50,0x20,0x40,0x80}; + +#endif diff --git a/src/lcd/dogm/fontdata/langdata.h b/src/lcd/dogm/fontdata/langdata.h new file mode 100644 index 0000000..746a3bd --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata.h @@ -0,0 +1,23 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * 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 + +#define FONTDATA_ITEM(page, begin, end, data) { page, begin, end, COUNT(data), data } diff --git a/src/lcd/dogm/fontdata/langdata_an.h b/src/lcd/dogm/fontdata/langdata_an.h new file mode 100644 index 0000000..fb0fdcf --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_an.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_an[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_bg.h b/src/lcd/dogm/fontdata/langdata_bg.h new file mode 100644 index 0000000..20cd7b9 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_bg.h @@ -0,0 +1,78 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_8_144_149[96] U8G_FONT_SECTION("fontpage_8_144_149") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0x95,0x00,0x07,0xFF,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF0,0x80,0x80,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80, + 0x80,0x80,0x80,0x80,0x80,0x05,0x08,0x08,0x06,0x00,0xFF,0x30,0x50,0x50,0x50,0x50, + 0x50,0xF8,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8 + }; +const u8g_fntpgm_uint8_t fontpage_8_151_152[43] U8G_FONT_SECTION("fontpage_8_151_152") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x97,0x98,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x08,0x70,0x08,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0x88,0x88,0x98,0xA8,0xC8,0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_8_154_164[160] U8G_FONT_SECTION("fontpage_8_154_164") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0xA4,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x48,0x48,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88, + 0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x88, + 0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x88,0x88,0x05, + 0x07,0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x05,0x07,0x07,0x06, + 0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF8, + 0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x88, + 0x78,0x08,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x70,0xA8,0xA8,0xA8,0x70,0x20 + }; +const u8g_fntpgm_uint8_t fontpage_8_166_166[32] U8G_FONT_SECTION("fontpage_8_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x07,0xFE,0x00, + 0x00,0x05,0x09,0x09,0x06,0x00,0xFE,0x90,0x90,0x90,0x90,0x90,0x90,0xF8,0x08,0x08 + }; +const u8g_fntpgm_uint8_t fontpage_8_175_195[260] U8G_FONT_SECTION("fontpage_8_175_195") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xC3,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x78,0x88,0x88,0x78,0x28,0x48,0x88,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00,0x00,0x70, + 0x80,0xF0,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF0,0x88,0xF0,0x88, + 0xF0,0x05,0x05,0x05,0x06,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x05,0x06,0x06,0x06, + 0x00,0xFF,0x30,0x50,0x50,0x50,0xF8,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88, + 0xF0,0x80,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0x70,0x20,0x70,0xA8,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x88,0x30,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x88, + 0x98,0xA8,0xC8,0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x88,0x70,0x00,0x88,0x98,0xA8, + 0xC8,0x88,0x04,0x05,0x05,0x06,0x01,0x00,0x90,0xA0,0xC0,0xA0,0x90,0x05,0x05,0x05, + 0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0xD8, + 0xA8,0x88,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0xF8,0x88,0x88,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF8, + 0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0xFE,0xF0,0x88,0x88,0x88,0xF0,0x80, + 0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x05,0x05,0x05,0x06, + 0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88, + 0x88,0x78,0x08,0x70}; +const u8g_fntpgm_uint8_t fontpage_8_197_200[63] U8G_FONT_SECTION("fontpage_8_197_200") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC5,0xC8,0x00,0x05,0xFE,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x05,0x07,0x07,0x06, + 0x00,0xFE,0x90,0x90,0x90,0x90,0xF8,0x08,0x08,0x05,0x05,0x05,0x06,0x00,0x00,0x88, + 0x88,0x78,0x08,0x08,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0xA8,0xA8,0xA8,0xF8}; +const u8g_fntpgm_uint8_t fontpage_8_202_202[28] U8G_FONT_SECTION("fontpage_8_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0xC0,0x40,0x70,0x48,0x70}; +const u8g_fntpgm_uint8_t fontpage_8_206_207[39] U8G_FONT_SECTION("fontpage_8_206_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCE,0xCF,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x90,0xA8,0xE8,0xA8,0x90,0x04,0x05,0x05,0x06, + 0x01,0x00,0x70,0x90,0x70,0x50,0x90}; + +static const uxg_fontinfo_t g_fontinfo_bg[] PROGMEM = { + FONTDATA_ITEM(8, 144, 149, fontpage_8_144_149), // 'А' -- 'Е' + FONTDATA_ITEM(8, 151, 152, fontpage_8_151_152), // 'З' -- 'И' + FONTDATA_ITEM(8, 154, 164, fontpage_8_154_164), // 'К' -- 'Ф' + FONTDATA_ITEM(8, 166, 166, fontpage_8_166_166), // 'Ц' -- 'Ц' + FONTDATA_ITEM(8, 175, 195, fontpage_8_175_195), // 'Я' -- 'у' + FONTDATA_ITEM(8, 197, 200, fontpage_8_197_200), // 'х' -- 'ш' + FONTDATA_ITEM(8, 202, 202, fontpage_8_202_202), // 'ъ' -- 'ъ' + FONTDATA_ITEM(8, 206, 207, fontpage_8_206_207), // 'ю' -- 'я' +}; diff --git a/src/lcd/dogm/fontdata/langdata_ca.h b/src/lcd/dogm/fontdata/langdata_ca.h new file mode 100644 index 0000000..deac367 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_ca.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_ca[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_cz.h b/src/lcd/dogm/fontdata/langdata_cz.h new file mode 100644 index 0000000..39f03f3 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_cz.h @@ -0,0 +1,55 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_140_141[47] U8G_FONT_SECTION("fontpage_2_140_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8D,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x80,0x80,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_2_143_143[33] U8G_FONT_SECTION("fontpage_2_143_143") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8F,0x8F,0x00,0x0A,0x00,0x00, + 0x00,0x06,0x0A,0x0A,0x06,0x00,0x00,0x14,0x08,0x00,0x08,0x08,0x78,0x88,0x88,0x88, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_2_154_155[47] U8G_FONT_SECTION("fontpage_2_154_155") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9B,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80, + 0xF8,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0xF0,0x80,0x70}; +const u8g_fntpgm_uint8_t fontpage_2_200_200[31] U8G_FONT_SECTION("fontpage_2_200_200") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0xB0,0xC8,0x88,0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_2_216_217[47] U8G_FONT_SECTION("fontpage_2_216_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD9,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0xF0,0x88,0x88,0xF0,0xA0,0x90, + 0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0xB0,0xC8,0x80,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_2_224_225[47] U8G_FONT_SECTION("fontpage_2_224_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE1,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x70,0x08,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x78,0x80,0x70,0x08,0xF0}; +const u8g_fntpgm_uint8_t fontpage_2_229_229[33] U8G_FONT_SECTION("fontpage_2_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x20,0x20,0xF8,0x20,0x20,0x20, + 0x18}; +const u8g_fntpgm_uint8_t fontpage_2_239_239[31] U8G_FONT_SECTION("fontpage_2_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x20,0x50,0x20,0x88,0x88,0x88,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_2_253_254[47] U8G_FONT_SECTION("fontpage_2_253_254") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFE,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0xF8,0x08,0x10,0x20,0x40,0x80, + 0xF8,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0xF8,0x10,0x20,0x40,0xF8}; + +static const uxg_fontinfo_t g_fontinfo_cz[] PROGMEM = { + FONTDATA_ITEM(2, 140, 141, fontpage_2_140_141), // 'Č' -- 'č' + FONTDATA_ITEM(2, 143, 143, fontpage_2_143_143), // 'ď' -- 'ď' + FONTDATA_ITEM(2, 154, 155, fontpage_2_154_155), // 'Ě' -- 'ě' + FONTDATA_ITEM(2, 200, 200, fontpage_2_200_200), // 'ň' -- 'ň' + FONTDATA_ITEM(2, 216, 217, fontpage_2_216_217), // 'Ř' -- 'ř' + FONTDATA_ITEM(2, 224, 225, fontpage_2_224_225), // 'Š' -- 'š' + FONTDATA_ITEM(2, 229, 229, fontpage_2_229_229), // 'ť' -- 'ť' + FONTDATA_ITEM(2, 239, 239, fontpage_2_239_239), // 'ů' -- 'ů' + FONTDATA_ITEM(2, 253, 254, fontpage_2_253_254), // 'Ž' -- 'ž' +}; diff --git a/src/lcd/dogm/fontdata/langdata_da.h b/src/lcd/dogm/fontdata/langdata_da.h new file mode 100644 index 0000000..ad8df9a --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_da.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_da[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_de.h b/src/lcd/dogm/fontdata/langdata_de.h new file mode 100644 index 0000000..44230fa --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_de.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_de[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_el.h b/src/lcd/dogm/fontdata/langdata_el.h new file mode 100644 index 0000000..6fefab9 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_el.h @@ -0,0 +1,91 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_7_136_136[33] U8G_FONT_SECTION("fontpage_7_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40,0x80,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80, + 0xF8}; +const u8g_fntpgm_uint8_t fontpage_7_145_157[186] U8G_FONT_SECTION("fontpage_7_145_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x9D,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF8,0x80,0x80,0x80,0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20, + 0x50,0x50,0x88,0x88,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0,0x80, + 0x80,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,0x05, + 0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06, + 0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x70,0x03,0x07,0x07,0x06,0x01,0x00,0xE0, + 0x40,0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0,0xC0, + 0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0x50,0x50,0x88,0x88,0x88, + 0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07,0x07, + 0x06,0x00,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_7_159_161[56] U8G_FONT_SECTION("fontpage_7_159_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0xA1,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF0,0x88,0x88,0xF0,0x80,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_7_163_167[82] U8G_FONT_SECTION("fontpage_7_163_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA3,0xA7,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x40,0x20,0x10,0x20,0x40,0xF8,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00, + 0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x70, + 0xA8,0xA8,0xA8,0x70,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x50, + 0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_7_172_175[75] U8G_FONT_SECTION("fontpage_7_172_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAF,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x68,0x90,0x90,0x90,0x68,0x05, + 0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x60,0x88,0x70,0x05,0x0A,0x0A, + 0x06,0x00,0xFE,0x10,0x20,0x00,0xB0,0xC8,0x88,0x88,0x88,0x08,0x08,0x03,0x08,0x08, + 0x06,0x01,0x00,0x40,0x80,0x00,0x80,0x80,0x80,0xA0,0x40}; +const u8g_fntpgm_uint8_t fontpage_7_177_181[80] U8G_FONT_SECTION("fontpage_7_177_181") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB5,0x00,0x07,0xFE,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x68,0x90,0x90,0x90,0x68,0x05,0x09,0x09,0x06, + 0x00,0xFE,0x60,0x90,0x90,0xB0,0x88,0x88,0xF0,0x80,0x80,0x05,0x07,0x07,0x06,0x00, + 0xFE,0x88,0x88,0x50,0x50,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x80, + 0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x60,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_7_183_199[226] U8G_FONT_SECTION("fontpage_7_183_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xC7,0x00,0x09,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0xFE,0xB0,0xC8,0x88,0x88,0x88,0x08,0x08,0x04,0x07, + 0x07,0x06,0x01,0x00,0x60,0x90,0x90,0xF0,0x90,0x90,0x60,0x03,0x05,0x05,0x06,0x02, + 0x00,0x80,0x80,0x80,0xA0,0x40,0x04,0x05,0x05,0x06,0x01,0x00,0x90,0xA0,0xC0,0xA0, + 0x90,0x05,0x09,0x09,0x06,0x00,0x00,0x80,0x40,0x40,0x20,0x20,0x50,0x50,0x88,0x88, + 0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88,0x98,0xE8,0x80,0x80,0x05,0x05,0x05, + 0x06,0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x05,0x09,0x09,0x06,0x00,0xFE,0xF8,0x20, + 0x40,0x70,0x80,0x80,0x70,0x08,0x10,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x88, + 0x88,0x70,0x06,0x05,0x05,0x06,0x00,0x00,0xF8,0x50,0x50,0x54,0x48,0x05,0x07,0x07, + 0x06,0x00,0xFE,0x70,0x88,0x88,0xC8,0xB0,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0xFE, + 0x70,0x88,0x80,0x80,0x70,0x08,0x30,0x05,0x05,0x05,0x06,0x00,0x00,0x78,0x90,0x88, + 0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF8,0x20,0x20,0x28,0x10,0x05,0x05,0x05, + 0x06,0x00,0x00,0x90,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0xFE,0x10,0xA8, + 0xA8,0xA8,0x70,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x50,0x20,0x50, + 0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_7_201_201[28] U8G_FONT_SECTION("fontpage_7_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x50,0x88,0xA8,0xA8,0x50}; +const u8g_fntpgm_uint8_t fontpage_7_204_206[59] U8G_FONT_SECTION("fontpage_7_204_206") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCE,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x88,0x88,0x70,0x05, + 0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x90,0x88,0x88,0x88,0x70,0x05,0x08,0x08, + 0x06,0x00,0x00,0x10,0x20,0x00,0x50,0x88,0xA8,0xA8,0x50}; +const u8g_fntpgm_uint8_t fontpage_64_166_166[24] U8G_FONT_SECTION("fontpage_64_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x01,0x00,0x00, + 0x00,0x05,0x01,0x01,0x06,0x00,0x00,0xA8}; + +static const uxg_fontinfo_t g_fontinfo_el[] PROGMEM = { + FONTDATA_ITEM(7, 136, 136, fontpage_7_136_136), // 'Έ' -- 'Έ' + FONTDATA_ITEM(7, 145, 157, fontpage_7_145_157), // 'Α' -- 'Ν' + FONTDATA_ITEM(7, 159, 161, fontpage_7_159_161), // 'Ο' -- 'Ρ' + FONTDATA_ITEM(7, 163, 167, fontpage_7_163_167), // 'Σ' -- 'Χ' + FONTDATA_ITEM(7, 172, 175, fontpage_7_172_175), // 'ά' -- 'ί' + FONTDATA_ITEM(7, 177, 181, fontpage_7_177_181), // 'α' -- 'ε' + FONTDATA_ITEM(7, 183, 199, fontpage_7_183_199), // 'η' -- 'χ' + FONTDATA_ITEM(7, 201, 201, fontpage_7_201_201), // 'ω' -- 'ω' + FONTDATA_ITEM(7, 204, 206, fontpage_7_204_206), // 'ό' -- 'ώ' + FONTDATA_ITEM(64, 166, 166, fontpage_64_166_166), // '…' -- '…' +}; diff --git a/src/lcd/dogm/fontdata/langdata_el_CY.h b/src/lcd/dogm/fontdata/langdata_el_CY.h new file mode 100644 index 0000000..c3a2264 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_el_CY.h @@ -0,0 +1,91 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_7_136_136[33] U8G_FONT_SECTION("fontpage_7_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40,0x80,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80, + 0xF8}; +const u8g_fntpgm_uint8_t fontpage_7_145_157[186] U8G_FONT_SECTION("fontpage_7_145_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x9D,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF8,0x80,0x80,0x80,0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20, + 0x50,0x50,0x88,0x88,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0,0x80, + 0x80,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,0x05, + 0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06, + 0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x70,0x03,0x07,0x07,0x06,0x01,0x00,0xE0, + 0x40,0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0,0xC0, + 0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0x50,0x50,0x88,0x88,0x88, + 0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07,0x07, + 0x06,0x00,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_7_159_161[56] U8G_FONT_SECTION("fontpage_7_159_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0xA1,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF0,0x88,0x88,0xF0,0x80,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_7_163_167[82] U8G_FONT_SECTION("fontpage_7_163_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA3,0xA7,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x40,0x20,0x10,0x20,0x40,0xF8,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00, + 0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x70, + 0xA8,0xA8,0xA8,0x70,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x50, + 0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_7_172_175[75] U8G_FONT_SECTION("fontpage_7_172_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAF,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x68,0x90,0x90,0x90,0x68,0x05, + 0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x60,0x88,0x70,0x05,0x0A,0x0A, + 0x06,0x00,0xFE,0x10,0x20,0x00,0xB0,0xC8,0x88,0x88,0x88,0x08,0x08,0x03,0x08,0x08, + 0x06,0x01,0x00,0x40,0x80,0x00,0x80,0x80,0x80,0xA0,0x40}; +const u8g_fntpgm_uint8_t fontpage_7_177_181[80] U8G_FONT_SECTION("fontpage_7_177_181") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB5,0x00,0x07,0xFE,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x68,0x90,0x90,0x90,0x68,0x05,0x09,0x09,0x06, + 0x00,0xFE,0x60,0x90,0x90,0xB0,0x88,0x88,0xF0,0x80,0x80,0x05,0x07,0x07,0x06,0x00, + 0xFE,0x88,0x88,0x50,0x50,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x80, + 0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x60,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_7_183_199[226] U8G_FONT_SECTION("fontpage_7_183_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xC7,0x00,0x09,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0xFE,0xB0,0xC8,0x88,0x88,0x88,0x08,0x08,0x04,0x07, + 0x07,0x06,0x01,0x00,0x60,0x90,0x90,0xF0,0x90,0x90,0x60,0x03,0x05,0x05,0x06,0x02, + 0x00,0x80,0x80,0x80,0xA0,0x40,0x04,0x05,0x05,0x06,0x01,0x00,0x90,0xA0,0xC0,0xA0, + 0x90,0x05,0x09,0x09,0x06,0x00,0x00,0x80,0x40,0x40,0x20,0x20,0x50,0x50,0x88,0x88, + 0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88,0x98,0xE8,0x80,0x80,0x05,0x05,0x05, + 0x06,0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x05,0x09,0x09,0x06,0x00,0xFE,0xF8,0x20, + 0x40,0x70,0x80,0x80,0x70,0x08,0x10,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x88, + 0x88,0x70,0x06,0x05,0x05,0x06,0x00,0x00,0xF8,0x50,0x50,0x54,0x48,0x05,0x07,0x07, + 0x06,0x00,0xFE,0x70,0x88,0x88,0xC8,0xB0,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0xFE, + 0x70,0x88,0x80,0x80,0x70,0x08,0x30,0x05,0x05,0x05,0x06,0x00,0x00,0x78,0x90,0x88, + 0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF8,0x20,0x20,0x28,0x10,0x05,0x05,0x05, + 0x06,0x00,0x00,0x90,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0xFE,0x10,0xA8, + 0xA8,0xA8,0x70,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x50,0x20,0x50, + 0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_7_201_201[28] U8G_FONT_SECTION("fontpage_7_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x50,0x88,0xA8,0xA8,0x50}; +const u8g_fntpgm_uint8_t fontpage_7_204_206[59] U8G_FONT_SECTION("fontpage_7_204_206") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCE,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x88,0x88,0x70,0x05, + 0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x90,0x88,0x88,0x88,0x70,0x05,0x08,0x08, + 0x06,0x00,0x00,0x10,0x20,0x00,0x50,0x88,0xA8,0xA8,0x50}; +const u8g_fntpgm_uint8_t fontpage_64_166_166[24] U8G_FONT_SECTION("fontpage_64_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x01,0x00,0x00, + 0x00,0x05,0x01,0x01,0x06,0x00,0x00,0xA8}; + +static const uxg_fontinfo_t g_fontinfo_el_CY[] PROGMEM = { + FONTDATA_ITEM(7, 136, 136, fontpage_7_136_136), // 'Έ' -- 'Έ' + FONTDATA_ITEM(7, 145, 157, fontpage_7_145_157), // 'Α' -- 'Ν' + FONTDATA_ITEM(7, 159, 161, fontpage_7_159_161), // 'Ο' -- 'Ρ' + FONTDATA_ITEM(7, 163, 167, fontpage_7_163_167), // 'Σ' -- 'Χ' + FONTDATA_ITEM(7, 172, 175, fontpage_7_172_175), // 'ά' -- 'ί' + FONTDATA_ITEM(7, 177, 181, fontpage_7_177_181), // 'α' -- 'ε' + FONTDATA_ITEM(7, 183, 199, fontpage_7_183_199), // 'η' -- 'χ' + FONTDATA_ITEM(7, 201, 201, fontpage_7_201_201), // 'ω' -- 'ω' + FONTDATA_ITEM(7, 204, 206, fontpage_7_204_206), // 'ό' -- 'ώ' + FONTDATA_ITEM(64, 166, 166, fontpage_64_166_166), // '…' -- '…' +}; diff --git a/src/lcd/dogm/fontdata/langdata_en.h b/src/lcd/dogm/fontdata/langdata_en.h new file mode 100644 index 0000000..a69161b --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_en.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_en[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_es.h b/src/lcd/dogm/fontdata/langdata_es.h new file mode 100644 index 0000000..a8ddb44 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_es.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_es[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_eu.h b/src/lcd/dogm/fontdata/langdata_eu.h new file mode 100644 index 0000000..3fdc025 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_eu.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_eu[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_fi.h b/src/lcd/dogm/fontdata/langdata_fi.h new file mode 100644 index 0000000..25e1927 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_fi.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_fi[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_fr.h b/src/lcd/dogm/fontdata/langdata_fr.h new file mode 100644 index 0000000..a3cc160 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_fr.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_fr[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_gl.h b/src/lcd/dogm/fontdata/langdata_gl.h new file mode 100644 index 0000000..2f93d05 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_gl.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_gl[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_hr.h b/src/lcd/dogm/fontdata/langdata_hr.h new file mode 100644 index 0000000..b5e4d54 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_hr.h @@ -0,0 +1,33 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_135_135[31] U8G_FONT_SECTION("fontpage_2_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x80,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_2_140_141[47] U8G_FONT_SECTION("fontpage_2_140_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8D,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x80,0x80,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_2_145_145[31] U8G_FONT_SECTION("fontpage_2_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x08,0x00,0x00, + 0x00,0x06,0x08,0x08,0x06,0x00,0x00,0x08,0x1C,0x08,0x78,0x88,0x88,0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_2_225_225[31] U8G_FONT_SECTION("fontpage_2_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x78,0x80,0x70,0x08,0xF0}; +const u8g_fntpgm_uint8_t fontpage_2_254_254[31] U8G_FONT_SECTION("fontpage_2_254_254") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0xF8,0x10,0x20,0x40,0xF8}; + +static const uxg_fontinfo_t g_fontinfo_hr[] PROGMEM = { + FONTDATA_ITEM(2, 135, 135, fontpage_2_135_135), // 'ć' -- 'ć' + FONTDATA_ITEM(2, 140, 141, fontpage_2_140_141), // 'Č' -- 'č' + FONTDATA_ITEM(2, 145, 145, fontpage_2_145_145), // 'đ' -- 'đ' + FONTDATA_ITEM(2, 225, 225, fontpage_2_225_225), // 'š' -- 'š' + FONTDATA_ITEM(2, 254, 254, fontpage_2_254_254), // 'ž' -- 'ž' +}; diff --git a/src/lcd/dogm/fontdata/langdata_hu.h b/src/lcd/dogm/fontdata/langdata_hu.h new file mode 100644 index 0000000..450662a --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_hu.h @@ -0,0 +1,16 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_241_241[31] U8G_FONT_SECTION("fontpage_2_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x48,0x90,0x00,0x88,0x88,0x88,0x88,0x70}; + +static const uxg_fontinfo_t g_fontinfo_hu[] PROGMEM = { + FONTDATA_ITEM(2, 241, 241, fontpage_2_241_241), // 'ű' -- 'ű' +}; diff --git a/src/lcd/dogm/fontdata/langdata_it.h b/src/lcd/dogm/fontdata/langdata_it.h new file mode 100644 index 0000000..1a41a79 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_it.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_it[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_jp_kana.h b/src/lcd/dogm/fontdata/langdata_jp_kana.h new file mode 100644 index 0000000..dc483b7 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_jp_kana.h @@ -0,0 +1,112 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_97_161_164[65] U8G_FONT_SECTION("fontpage_97_161_164") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA4,0x00,0x07,0x00,0x00, + 0x00,0x04,0x05,0x05,0x06,0x00,0x00,0xF0,0x10,0x60,0x40,0x80,0x05,0x07,0x07,0x06, + 0x00,0x00,0xF8,0x08,0x28,0x30,0x20,0x20,0x40,0x04,0x05,0x05,0x06,0x00,0x00,0x10, + 0x20,0x60,0xA0,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x08,0x10,0x20,0x60,0xA0,0x20, + 0x20}; +const u8g_fntpgm_uint8_t fontpage_97_166_166[30] U8G_FONT_SECTION("fontpage_97_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0xF8,0x88,0x88,0x08,0x10,0x60}; +const u8g_fntpgm_uint8_t fontpage_97_168_168[29] U8G_FONT_SECTION("fontpage_97_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x06,0x00,0x00, + 0x00,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0xF8}; +const u8g_fntpgm_uint8_t fontpage_97_170_187[268] U8G_FONT_SECTION("fontpage_97_170_187") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAA,0xBB,0x00,0x0D,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0xF8,0x10,0x30,0x50,0x90,0x10,0x05,0x07, + 0x07,0x06,0x00,0x00,0x40,0xF8,0x48,0x48,0x48,0x48,0x98,0x05,0x09,0x09,0x06,0x00, + 0x00,0x28,0x08,0x40,0xF8,0x48,0x48,0x48,0x48,0x98,0x05,0x07,0x07,0x06,0x00,0x00, + 0x20,0xF8,0x20,0x20,0xF8,0x10,0x10,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x20, + 0xF8,0x20,0x20,0xF8,0x10,0x10,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x78,0x48,0x88, + 0x08,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x40,0x78,0x48,0x88,0x08, + 0x10,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x80,0xF8,0x90,0x90,0x10,0x10,0x20,0x05, + 0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x80,0xF8,0x90,0x90,0x10,0x10,0x20,0x05,0x06, + 0x06,0x06,0x00,0x00,0xF8,0x08,0x08,0x08,0x08,0xF8,0x05,0x09,0x09,0x06,0x00,0x00, + 0x28,0x28,0x00,0xF8,0x08,0x08,0x08,0x08,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0x50, + 0xF8,0x50,0x50,0x50,0x10,0x20,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x50,0xF8, + 0x50,0x50,0x50,0x10,0x20,0x05,0x06,0x06,0x06,0x00,0x00,0xC0,0x08,0xC8,0x08,0x10, + 0xE0,0x07,0x0D,0x0D,0x06,0x00,0x00,0x02,0x00,0x00,0x00,0x28,0x28,0x00,0xC0,0x08, + 0xC8,0x08,0x10,0xE0,0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x10,0x10,0x20,0x50,0x88, + 0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0x70,0x10,0x10,0x20,0x50,0x88,0x05, + 0x07,0x07,0x06,0x00,0x00,0x40,0x40,0xF8,0x48,0x50,0x40,0x38}; +const u8g_fntpgm_uint8_t fontpage_97_189_193[85] U8G_FONT_SECTION("fontpage_97_189_193") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBD,0xC1,0x00,0x09,0x00,0x00, + 0x00,0x05,0x06,0x06,0x06,0x00,0x00,0x88,0x48,0x48,0x10,0x10,0x20,0x05,0x09,0x09, + 0x06,0x00,0x00,0x28,0x28,0x00,0x88,0x48,0x48,0x10,0x10,0x20,0x05,0x07,0x07,0x06, + 0x00,0x00,0x40,0x78,0x48,0xA8,0x18,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x28, + 0x08,0x40,0x78,0x48,0xA8,0x18,0x10,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0x60, + 0x20,0xF8,0x20,0x20,0x40}; +const u8g_fntpgm_uint8_t fontpage_97_195_211[241] U8G_FONT_SECTION("fontpage_97_195_211") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC3,0xD3,0x00,0x09,0x00,0x00, + 0x00,0x05,0x04,0x04,0x06,0x00,0x00,0xA8,0xA8,0x08,0x30,0x05,0x06,0x06,0x06,0x00, + 0x00,0xA8,0xA8,0xA8,0x08,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00, + 0xA8,0xA8,0xA8,0x08,0x10,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x00,0xF8,0x20, + 0x20,0x20,0x40,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x70,0x00,0xF8,0x20,0x20, + 0x20,0x40,0x04,0x07,0x07,0x06,0x01,0x00,0x80,0x80,0xC0,0xA0,0x90,0x80,0x80,0x04, + 0x09,0x09,0x06,0x01,0x00,0x50,0x10,0x80,0x80,0xC0,0xA0,0x90,0x80,0x80,0x05,0x07, + 0x07,0x06,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x40,0x80,0x05,0x06,0x06,0x06,0x00, + 0x00,0x70,0x00,0x00,0x00,0x00,0xF8,0x05,0x06,0x06,0x06,0x00,0x00,0x78,0x08,0x28, + 0x10,0x28,0xC0,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x70,0x10,0x20,0x70,0xA8,0x20, + 0x03,0x06,0x06,0x06,0x01,0x00,0x20,0x20,0x20,0x40,0x40,0x80,0x05,0x06,0x06,0x06, + 0x00,0x00,0x10,0x50,0x50,0x48,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28, + 0x00,0x10,0x50,0x50,0x48,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0x00,0x18,0x18,0x00, + 0x10,0x50,0x50,0x48,0x88,0x88,0x04,0x06,0x06,0x06,0x00,0x00,0x80,0x90,0xE0,0x80, + 0x80,0x70,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0x80,0x90,0xE0,0x80,0x80, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_97_213_217[84] U8G_FONT_SECTION("fontpage_97_213_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD5,0xD9,0x00,0x09,0x00,0x00, + 0x00,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x08,0x08,0x08,0x10,0x60,0x05,0x09,0x09, + 0x06,0x00,0x00,0x28,0x28,0x00,0xF8,0x08,0x08,0x08,0x10,0x60,0x05,0x09,0x09,0x06, + 0x00,0x00,0x18,0x18,0x00,0xF8,0x08,0x08,0x08,0x10,0x60,0x05,0x05,0x05,0x06,0x00, + 0x01,0x60,0xA0,0x10,0x10,0x08,0x05,0x08,0x08,0x06,0x00,0x01,0x28,0x28,0x00,0x60, + 0xA0,0x10,0x10,0x08}; +const u8g_fntpgm_uint8_t fontpage_97_219_220[45] U8G_FONT_SECTION("fontpage_97_219_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDB,0xDC,0x00,0x09,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0xF8,0x20,0xA8,0xA8,0xA8,0x20,0x05,0x09, + 0x09,0x06,0x00,0x00,0x28,0x08,0x20,0xF8,0x20,0xA8,0xA8,0xA8,0x20}; +const u8g_fntpgm_uint8_t fontpage_97_222_223[41] U8G_FONT_SECTION("fontpage_97_222_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDF,0x00,0x06,0x00,0x00, + 0x00,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x08,0x08,0x50,0x20,0x10,0x04,0x06,0x06, + 0x06,0x01,0x00,0xE0,0x00,0xE0,0x00,0xC0,0x30}; +const u8g_fntpgm_uint8_t fontpage_97_225_237[174] U8G_FONT_SECTION("fontpage_97_225_237") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xED,0x00,0x07,0x00,0x00, + 0x00,0x05,0x06,0x06,0x06,0x00,0x00,0x08,0x48,0x30,0x10,0x28,0xC0,0x05,0x06,0x06, + 0x06,0x00,0x00,0xF0,0x40,0xF8,0x40,0x40,0x38,0x05,0x05,0x05,0x06,0x00,0x00,0x40, + 0xF8,0x48,0x50,0x40,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x40,0xF8,0x48,0x50,0x40, + 0x40,0x04,0x05,0x05,0x06,0x00,0x00,0x60,0x20,0x20,0x20,0xF0,0x05,0x06,0x06,0x06, + 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0xF8,0x04,0x05,0x05,0x06,0x00,0x00,0xF0,0x10, + 0xF0,0x10,0xF0,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x08,0xF8,0x08,0x08,0xF8,0x05, + 0x07,0x07,0x06,0x00,0x00,0x70,0x00,0xF8,0x08,0x08,0x10,0x60,0x04,0x07,0x07,0x06, + 0x00,0x00,0x10,0x90,0x90,0x90,0x90,0x10,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x20, + 0x20,0xA0,0xA0,0xA8,0xA8,0xB0,0x05,0x06,0x06,0x06,0x00,0x00,0x80,0x80,0x80,0x88, + 0xB0,0xC0,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xF8}; +const u8g_fntpgm_uint8_t fontpage_97_242_243[41] U8G_FONT_SECTION("fontpage_97_242_243") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF3,0x00,0x06,0x00,0x00, + 0x00,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x08,0xF8,0x08,0x10,0x60,0x05,0x06,0x06, + 0x06,0x00,0x00,0xC0,0x08,0x08,0x08,0x10,0xE0}; +const u8g_fntpgm_uint8_t fontpage_97_252_252[25] U8G_FONT_SECTION("fontpage_97_252_252") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x05,0x00,0x00, + 0x00,0x05,0x02,0x02,0x06,0x00,0x03,0x80,0x78}; + +static const uxg_fontinfo_t g_fontinfo_jp_kana[] PROGMEM = { + FONTDATA_ITEM(97, 161, 164, fontpage_97_161_164), // 'ァ' -- 'イ' + FONTDATA_ITEM(97, 166, 166, fontpage_97_166_166), // 'ウ' -- 'ウ' + FONTDATA_ITEM(97, 168, 168, fontpage_97_168_168), // 'エ' -- 'エ' + FONTDATA_ITEM(97, 170, 187, fontpage_97_170_187), // 'オ' -- 'セ' + FONTDATA_ITEM(97, 189, 193, fontpage_97_189_193), // 'ソ' -- 'チ' + FONTDATA_ITEM(97, 195, 211, fontpage_97_195_211), // 'ッ' -- 'ビ' + FONTDATA_ITEM(97, 213, 217, fontpage_97_213_217), // 'フ' -- 'ベ' + FONTDATA_ITEM(97, 219, 220, fontpage_97_219_220), // 'ホ' -- 'ボ' + FONTDATA_ITEM(97, 222, 223, fontpage_97_222_223), // 'マ' -- 'ミ' + FONTDATA_ITEM(97, 225, 237, fontpage_97_225_237), // 'メ' -- 'ロ' + FONTDATA_ITEM(97, 242, 243, fontpage_97_242_243), // 'ヲ' -- 'ン' + FONTDATA_ITEM(97, 252, 252, fontpage_97_252_252), // 'ー' -- 'ー' +}; diff --git a/src/lcd/dogm/fontdata/langdata_ko_KR.h b/src/lcd/dogm/fontdata/langdata_ko_KR.h new file mode 100644 index 0000000..31cc0bc --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_ko_KR.h @@ -0,0 +1,548 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_344_240_240[34] U8G_FONT_SECTION("fontpage_344_240_240") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x09,0x11,0x17,0x21,0x41,0x81,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_345_224_224[41] U8G_FONT_SECTION("fontpage_345_224_224") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x08, + 0x80,0x08,0x80,0x09,0x00,0x08,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_347_248_248[41] U8G_FONT_SECTION("fontpage_347_248_248") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00, + 0x80,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_348_137_137[45] U8G_FONT_SECTION("fontpage_348_137_137") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x00,0x80,0x00,0x80,0x01,0x00,0xFF, + 0xC0,0x00,0x00,0x20,0x80,0x20,0x80,0x3F,0x00,0x20,0x80,0x3F,0x00}; +const u8g_fntpgm_uint8_t fontpage_348_176_176[34] U8G_FONT_SECTION("fontpage_348_176_176") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x09,0x11,0x11,0x21,0x41,0x81,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_348_197_197[34] U8G_FONT_SECTION("fontpage_348_197_197") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC5,0xC5,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x09,0x11,0x21,0xC1,0x1E,0x21,0x41, + 0x21,0x1E}; +const u8g_fntpgm_uint8_t fontpage_352_196_196[41] U8G_FONT_SECTION("fontpage_352_196_196") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC4,0xC4,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x7F,0x80,0x08,0x80,0x08,0x80,0x08,0x80,0x08, + 0x80,0x08,0x80,0x10,0x80,0x11,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_353_180_180[34] U8G_FONT_SECTION("fontpage_353_180_180") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xB4,0xB4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x85,0x85,0x85,0x85,0x87,0x85,0x85,0xFD,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_354_248_248[41] U8G_FONT_SECTION("fontpage_354_248_248") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x3F, + 0x80,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_356_132_132[43] U8G_FONT_SECTION("fontpage_356_132_132") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x09,0xFF,0x00, + 0x00,0x0A,0x0A,0x14,0x0A,0x00,0xFF,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x3F, + 0x80,0x00,0x00,0xFF,0xC0,0x04,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_356_244_244[43] U8G_FONT_SECTION("fontpage_356_244_244") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x09,0xFF,0x00, + 0x00,0x0A,0x0A,0x14,0x0A,0x00,0xFF,0x20,0x00,0x20,0x00,0x20,0x00,0x3F,0x80,0x00, + 0x00,0x00,0x00,0xFF,0xC0,0x12,0x00,0x12,0x00,0x12,0x00}; +const u8g_fntpgm_uint8_t fontpage_357_200_200[34] U8G_FONT_SECTION("fontpage_357_200_200") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x7D,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_357_228_228[45] U8G_FONT_SECTION("fontpage_357_228_228") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xE4,0xE4,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x81,0x00,0x81,0x00,0x81,0x00,0x81, + 0x80,0x81,0x00,0x81,0x00,0xFD,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_357_249_249[45] U8G_FONT_SECTION("fontpage_357_249_249") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF9,0xF9,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x81,0x00,0x81,0x00,0x81,0x80,0x81, + 0x00,0xFD,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x3E,0x00}; +const u8g_fntpgm_uint8_t fontpage_359_196_196[41] U8G_FONT_SECTION("fontpage_359_196_196") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC4,0xC4,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x20,0x00,0x20,0x00,0x20,0x00,0x3F, + 0x80,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_359_204_204[45] U8G_FONT_SECTION("fontpage_359_204_204") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x20,0x00,0x3F,0x80,0x04,0x00,0xFF, + 0xC0,0x00,0x00,0x3F,0x00,0x00,0x80,0x3F,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_359_217_217[45] U8G_FONT_SECTION("fontpage_359_217_217") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x20,0x00,0x20,0x00,0x3F,0x80,0x04, + 0x00,0xFF,0xC0,0x00,0x00,0x1F,0x00,0x20,0x80,0x20,0x80,0x1F,0x00}; +const u8g_fntpgm_uint8_t fontpage_360_152_152[45] U8G_FONT_SECTION("fontpage_360_152_152") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x98,0x98,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x7C,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7E, + 0x80,0x10,0x80,0x10,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_360_156_156[45] U8G_FONT_SECTION("fontpage_360_156_156") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x7C,0x80,0x40,0x80,0x40,0x80,0x7C,0x80,0x10, + 0x80,0x10,0x80,0xFF,0x80,0x00,0x80,0x20,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_360_168_168[34] U8G_FONT_SECTION("fontpage_360_168_168") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x81,0x81,0xF9,0x21,0xFF,0x00,0x7F,0x41, + 0x41,0x7F}; +const u8g_fntpgm_uint8_t fontpage_361_164_164[45] U8G_FONT_SECTION("fontpage_361_164_164") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x7C,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7C, + 0x80,0x00,0x80,0xFE,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80}; +const u8g_fntpgm_uint8_t fontpage_361_220_220[41] U8G_FONT_SECTION("fontpage_361_220_220") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x20,0x00,0x20,0x00,0x20,0x00,0x20, + 0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_362_148_148[34] U8G_FONT_SECTION("fontpage_362_148_148") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x94,0x94,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x81,0x81,0x81,0x81,0x81,0x81,0xFD,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_366_252_252[45] U8G_FONT_SECTION("fontpage_366_252_252") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x09,0x00,0x09,0x00,0xF9,0x00,0x81, + 0x80,0x81,0x00,0x81,0x00,0xFD,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_367_236_236[34] U8G_FONT_SECTION("fontpage_367_236_236") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xEC,0xEC,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF1,0x09,0x09,0xF1,0x87,0x81,0x81,0xF9,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_368_136_136[34] U8G_FONT_SECTION("fontpage_368_136_136") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF5,0x15,0x15,0xF5,0x8D,0x85,0x85,0xFD,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_368_165_165[34] U8G_FONT_SECTION("fontpage_368_165_165") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF1,0x17,0xF1,0x87,0x81,0xF9,0x00,0x7F,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_368_220_220[41] U8G_FONT_SECTION("fontpage_368_220_220") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x00,0x80,0x3F,0x80,0x20,0x00,0x20, + 0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_369_204_204[41] U8G_FONT_SECTION("fontpage_369_204_204") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x00,0x80,0x3F,0x80,0x20,0x00,0x20, + 0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_370_244_244[41] U8G_FONT_SECTION("fontpage_370_244_244") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x00,0x80,0x3F,0x80,0x20,0x00,0x20, + 0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_371_172_172[34] U8G_FONT_SECTION("fontpage_371_172_172") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x09,0xF9,0x81,0x81,0x81,0xFD,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_371_176_176[34] U8G_FONT_SECTION("fontpage_371_176_176") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x09,0xF9,0x81,0x81,0xFD,0x01,0x20, + 0x20,0x3F}; +const u8g_fntpgm_uint8_t fontpage_371_189_189[34] U8G_FONT_SECTION("fontpage_371_189_189") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xBD,0xBD,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0xF9,0x81,0x81,0xFD,0x00,0x41,0x3F, + 0x41,0x3F}; +const u8g_fntpgm_uint8_t fontpage_371_193_193[34] U8G_FONT_SECTION("fontpage_371_193_193") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC1,0xC1,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0xF9,0x81,0x81,0xFD,0x01,0x3E,0x21, + 0x21,0x3E}; +const u8g_fntpgm_uint8_t fontpage_372_200_200[34] U8G_FONT_SECTION("fontpage_372_200_200") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x89,0x89,0x8F,0x89,0xF9,0x00,0x3F,0x41, + 0x41,0x3F}; +const u8g_fntpgm_uint8_t fontpage_372_212_212[34] U8G_FONT_SECTION("fontpage_372_212_212") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF5,0x95,0x95,0x9D,0x95,0x95,0x95,0xF5,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_372_244_244[34] U8G_FONT_SECTION("fontpage_372_244_244") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x89,0x8F,0x89,0x8F,0xF9,0x01,0x21,0x20, + 0x20,0x3F}; +const u8g_fntpgm_uint8_t fontpage_373_168_168[41] U8G_FONT_SECTION("fontpage_373_168_168") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x3F, + 0x80,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_373_187_187[45] U8G_FONT_SECTION("fontpage_373_187_187") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xBB,0xBB,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x20,0x80,0x20,0x80,0x3F,0x00,0x04, + 0x00,0xFF,0xC0,0x00,0x00,0x04,0x00,0x0C,0x00,0x1A,0x00,0x61,0x80}; +const u8g_fntpgm_uint8_t fontpage_375_248_248[34] U8G_FONT_SECTION("fontpage_375_248_248") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x89,0x89,0x89,0x89,0x89,0x89,0xF9,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_376_128_128[34] U8G_FONT_SECTION("fontpage_376_128_128") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x89,0x89,0x89,0xF9,0x00,0x3F,0x01,0x3F, + 0x40,0x3F}; +const u8g_fntpgm_uint8_t fontpage_376_148_148[45] U8G_FONT_SECTION("fontpage_376_148_148") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x94,0x94,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x89,0x00,0x89,0x00,0x89,0x00,0xF9,0x00,0x89, + 0x80,0x89,0x00,0x89,0x00,0xF9,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_377_132_132[34] U8G_FONT_SECTION("fontpage_377_132_132") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x89,0x89,0x89,0xFF,0x89,0x89,0x89,0xF9,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_377_160_160[34] U8G_FONT_SECTION("fontpage_377_160_160") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x95,0x95,0x95,0xF5,0x9D,0x95,0x95,0xF5,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_377_168_168[34] U8G_FONT_SECTION("fontpage_377_168_168") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x95,0x95,0xFD,0x95,0xF5,0x00,0x3F,0x01,0x3F, + 0x40,0x3F}; +const u8g_fntpgm_uint8_t fontpage_377_248_248[45] U8G_FONT_SECTION("fontpage_377_248_248") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x20,0x80,0x20,0x80,0x3F,0x00,0x20,0x80,0x3F, + 0x00,0x04,0x00,0xFF,0xC0,0x00,0x00,0x20,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_380_196_196[34] U8G_FONT_SECTION("fontpage_380_196_196") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC4,0xC4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x89,0x89,0x89,0xF9,0x89,0x89,0x89,0xF9,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_385_172_172[45] U8G_FONT_SECTION("fontpage_385_172_172") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x61, + 0x80,0x51,0x00,0x99,0x00,0x89,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_385_189_189[45] U8G_FONT_SECTION("fontpage_385_189_189") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xBD,0xBD,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x21,0x00,0x21,0x00,0x21,0x00,0x51,0x80,0xD9, + 0x00,0x89,0x00,0x00,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x7E,0x00}; +const u8g_fntpgm_uint8_t fontpage_385_200_200[34] U8G_FONT_SECTION("fontpage_385_200_200") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x25,0x25,0x25,0x45,0x67,0x65,0x95,0x95,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_386_164_164[34] U8G_FONT_SECTION("fontpage_386_164_164") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x21,0x21,0x27,0x51,0x89,0x00,0x3F,0x01,0x3F, + 0x40,0x3F}; +const u8g_fntpgm_uint8_t fontpage_387_140_141[69] U8G_FONT_SECTION("fontpage_387_140_141") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x8C,0x8D,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x04,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x31, + 0x00,0x44,0x80,0x04,0x00,0x04,0x00,0xFF,0xC0,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x04, + 0x00,0x0C,0x00,0x13,0x00,0x65,0x80,0x04,0x00,0xFF,0xC0,0x00,0x00,0x3F,0x00,0x00, + 0x80,0x00,0x80,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_389_164_164[41] U8G_FONT_SECTION("fontpage_389_164_164") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x04,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x31, + 0x00,0x40,0x80,0x00,0x00,0x00,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_389_172_172[45] U8G_FONT_SECTION("fontpage_389_172_172") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x04,0x00,0x1A,0x00,0x61,0x80,0x00,0x00,0xFF, + 0xC0,0x00,0x00,0x3F,0x00,0x00,0x80,0x3F,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_389_220_221[51] U8G_FONT_SECTION("fontpage_389_220_221") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xDC,0xDD,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x21,0x21,0x21,0x21,0x21,0x51,0xC9,0x89,0x01, + 0x01,0x01,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x21,0x21,0x21,0x51,0xD9,0x89,0x00,0x7F, + 0x01,0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_395_180_180[34] U8G_FONT_SECTION("fontpage_395_180_180") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xB4,0xB4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x89,0x89,0x8F,0x89,0x89,0x89,0x71,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_395_198_198[45] U8G_FONT_SECTION("fontpage_395_198_198") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x71,0x00,0x89,0x00,0x8F,0x00,0x89,0x00,0x89, + 0x00,0x71,0x00,0x00,0x00,0x4A,0x00,0x72,0x00,0x4D,0x00,0x74,0x80}; +const u8g_fntpgm_uint8_t fontpage_395_209_209[34] U8G_FONT_SECTION("fontpage_395_209_209") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x65,0x95,0x95,0x9D,0x95,0x65,0x00,0x7F,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_395_212_212[45] U8G_FONT_SECTION("fontpage_395_212_212") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x65,0x00,0x95,0x00,0x95,0x00,0x9D,0x00,0x95, + 0x00,0x65,0x00,0x05,0x00,0x25,0x00,0x20,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_395_244_244[34] U8G_FONT_SECTION("fontpage_395_244_244") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x8F,0x89,0x8F,0x71,0x00,0x3F,0x01,0x3F, + 0x40,0x3F}; +const u8g_fntpgm_uint8_t fontpage_396_136_136[34] U8G_FONT_SECTION("fontpage_396_136_136") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x65,0x95,0x9D,0x95,0x95,0x9D,0x95,0x65,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_396_164_164[41] U8G_FONT_SECTION("fontpage_396_164_164") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x1E,0x00,0x21,0x00,0x20,0x80,0x20,0x80,0x21, + 0x00,0x1E,0x00,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_396_168_168[45] U8G_FONT_SECTION("fontpage_396_168_168") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x1F,0x00,0x20,0x80,0x20,0x80,0x1F,0x00,0x04, + 0x00,0x04,0x00,0xFF,0xC0,0x00,0x00,0x20,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_396_196_196[45] U8G_FONT_SECTION("fontpage_396_196_196") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC4,0xC4,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x38,0x80,0x44,0x80,0x44,0x80,0x44,0x80,0x38, + 0xC0,0x10,0x80,0xFE,0x80,0x00,0x80,0x20,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_397_208_208[34] U8G_FONT_SECTION("fontpage_397_208_208") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x89,0x89,0x71,0x01,0xFF,0x21,0x27,0x41, + 0x40,0x7F}; +const u8g_fntpgm_uint8_t fontpage_398_132_132[45] U8G_FONT_SECTION("fontpage_398_132_132") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x38,0x80,0x44,0x80,0x42,0x80,0x44,0x80,0x38, + 0x80,0x00,0x80,0xFE,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80}; +const u8g_fntpgm_uint8_t fontpage_398_188_188[41] U8G_FONT_SECTION("fontpage_398_188_188") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x1E,0x00,0x21,0x00,0x20,0x80,0x20,0x80,0x21, + 0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_398_204_204[45] U8G_FONT_SECTION("fontpage_398_204_204") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x1E,0x00,0x21,0x00,0x21,0x00,0x1E,0x00,0x00, + 0x00,0xFF,0xC0,0x00,0x00,0x3F,0x00,0x20,0x80,0x20,0x80,0x3F,0x00}; +const u8g_fntpgm_uint8_t fontpage_398_244_244[34] U8G_FONT_SECTION("fontpage_398_244_244") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x49,0x89,0x89,0x89,0x89,0x49,0x71,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_398_252_253[51] U8G_FONT_SECTION("fontpage_398_252_253") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xFC,0xFD,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x89,0x89,0x89,0x71,0x00,0x3F,0x01,0x3F, + 0x40,0x3F,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x89,0x89,0x89,0x71,0x00,0x77,0x11, + 0x71,0x41,0x79}; +const u8g_fntpgm_uint8_t fontpage_399_133_133[34] U8G_FONT_SECTION("fontpage_399_133_133") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x89,0x89,0x89,0x89,0x71,0x00,0x41,0x3F, + 0x41,0x3F}; +const u8g_fntpgm_uint8_t fontpage_399_144_145[73] U8G_FONT_SECTION("fontpage_399_144_145") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x90,0x91,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x09,0x00,0x11,0x00,0x11,0x00,0x21, + 0x80,0x71,0x00,0xC9,0x00,0x85,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x09,0x0B,0x16, + 0x0A,0x01,0xFE,0xF9,0x00,0x09,0x00,0x11,0x00,0x31,0x80,0x49,0x00,0x85,0x00,0x00, + 0x00,0x7E,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_399_152_152[45] U8G_FONT_SECTION("fontpage_399_152_152") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x98,0x98,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x11,0x00,0x11,0x80,0x79,0x00,0x85, + 0x00,0x00,0x00,0x7E,0x00,0x01,0x00,0x7E,0x00,0x40,0x00,0x7F,0x00}; +const u8g_fntpgm_uint8_t fontpage_399_165_165[45] U8G_FONT_SECTION("fontpage_399_165_165") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x09,0x00,0x11,0x00,0x31,0x80,0x79, + 0x00,0x85,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x3E,0x00}; +const u8g_fntpgm_uint8_t fontpage_399_172_172[45] U8G_FONT_SECTION("fontpage_399_172_172") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x7A,0x80,0x0A,0x80,0x0A,0x80,0x12,0x80,0x13, + 0x80,0x2A,0x80,0x6A,0x80,0xC6,0x80,0x02,0x80,0x02,0x80,0x02,0x80}; +const u8g_fntpgm_uint8_t fontpage_400_128_128[34] U8G_FONT_SECTION("fontpage_400_128_128") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x11,0x17,0x31,0x71,0xC9,0x85,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_400_132_132[34] U8G_FONT_SECTION("fontpage_400_132_132") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x17,0x31,0x49,0x85,0x01,0x21,0x20, + 0x20,0x3F}; +const u8g_fntpgm_uint8_t fontpage_400_149_149[34] U8G_FONT_SECTION("fontpage_400_149_149") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x95,0x95,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x17,0x31,0x49,0x85,0x00,0x3E,0x21, + 0x21,0x3E}; +const u8g_fntpgm_uint8_t fontpage_400_156_156[45] U8G_FONT_SECTION("fontpage_400_156_156") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x7A,0x80,0x0A,0x80,0x0A,0x80,0x16,0x80,0x12, + 0x80,0x2A,0x80,0x4A,0x80,0x86,0x80,0x02,0x80,0x02,0x80,0x02,0x80}; +const u8g_fntpgm_uint8_t fontpage_401_253_253[45] U8G_FONT_SECTION("fontpage_401_253_253") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x01,0x00,0x0E,0x00,0x71,0x80,0x00, + 0x00,0xFF,0xC0,0x04,0x00,0x3F,0x00,0x00,0x80,0x00,0x80,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_402_128_128[45] U8G_FONT_SECTION("fontpage_402_128_128") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x01,0x00,0x0E,0x00,0x71,0x80,0x00, + 0x00,0xFF,0xC0,0x04,0x00,0x24,0x00,0x24,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_402_145_145[45] U8G_FONT_SECTION("fontpage_402_145_145") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x01,0x00,0x0E,0x00,0x71,0x80,0x00, + 0x00,0xFF,0xC0,0x04,0x00,0x1F,0x00,0x20,0x80,0x20,0x80,0x1F,0x00}; +const u8g_fntpgm_uint8_t fontpage_403_144_144[45] U8G_FONT_SECTION("fontpage_403_144_144") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x90,0x90,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x3F,0x00,0x0E,0x00,0x71,0x80,0x00,0x00,0xFF, + 0xC0,0x00,0x00,0x3F,0x00,0x00,0x80,0x3F,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_403_192_192[34] U8G_FONT_SECTION("fontpage_403_192_192") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x09,0x11,0x31,0x31,0xC9,0x85,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_409_152_152[34] U8G_FONT_SECTION("fontpage_409_152_152") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x98,0x98,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x01,0xF9,0x11,0x17,0x31,0x49,0x85,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_410_136_136[41] U8G_FONT_SECTION("fontpage_410_136_136") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x02,0x00,0x0E, + 0x00,0x71,0x80,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_411_149_149[45] U8G_FONT_SECTION("fontpage_411_149_149") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x95,0x95,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x1E,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x73, + 0x80,0x00,0x00,0xFF,0xC0,0x04,0x00,0x3F,0x00,0x00,0x80,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_411_156_156[47] U8G_FONT_SECTION("fontpage_411_156_156") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x09,0xFD,0x00, + 0x00,0x0A,0x0C,0x18,0x0A,0x00,0xFD,0x1E,0x00,0x00,0x00,0x3F,0x00,0x1A,0x00,0x21, + 0x00,0xFF,0xC0,0x04,0x00,0x3F,0x00,0x00,0x80,0x3F,0x00,0x20,0x00,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_411_164_164[45] U8G_FONT_SECTION("fontpage_411_164_164") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x1E,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x73, + 0x80,0x00,0x00,0xFF,0xC0,0x04,0x00,0x3F,0x00,0x20,0x80,0x3F,0x00}; +const u8g_fntpgm_uint8_t fontpage_411_232_232[45] U8G_FONT_SECTION("fontpage_411_232_232") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x00,0xFE,0x38,0x80,0x00,0x80,0x7C,0x80,0x18,0x80,0x66, + 0x80,0x00,0x80,0xFE,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80}; +const u8g_fntpgm_uint8_t fontpage_412_216_216[34] U8G_FONT_SECTION("fontpage_412_216_216") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x01,0xF9,0x09,0x11,0x31,0x49,0x85,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_412_232_232[34] U8G_FONT_SECTION("fontpage_412_232_232") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x01,0xF9,0x09,0x31,0xCD,0x00,0x3F,0x41, + 0x41,0x3F}; +const u8g_fntpgm_uint8_t fontpage_412_244_244[45] U8G_FONT_SECTION("fontpage_412_244_244") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x09,0x00,0x09,0x00,0xF1,0x00,0x11, + 0x80,0x21,0x00,0x41,0x00,0x81,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_414_156_156[34] U8G_FONT_SECTION("fontpage_414_156_156") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x09,0x0F,0xF1,0x11,0x2F,0x41,0x81,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_417_209_209[45] U8G_FONT_SECTION("fontpage_417_209_209") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0xF9,0x00,0x81,0x00,0xF9,0x80,0x81,0x00,0x81, + 0x00,0xFD,0x00,0x00,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x7E,0x00}; +const u8g_fntpgm_uint8_t fontpage_418_176_176[34] U8G_FONT_SECTION("fontpage_418_176_176") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF9,0x81,0x81,0xF7,0x81,0x81,0x81,0xF9,0x01, + 0x01,0x01}; +const u8g_fntpgm_uint8_t fontpage_418_204_204[34] U8G_FONT_SECTION("fontpage_418_204_204") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0xF5,0x85,0x85,0xED,0x85,0x85,0x85,0xFD,0x05, + 0x05,0x05}; +const u8g_fntpgm_uint8_t fontpage_419_160_160[41] U8G_FONT_SECTION("fontpage_419_160_160") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x20,0x00,0x3F,0x00,0x20,0x00,0x20, + 0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_421_184_184[41] U8G_FONT_SECTION("fontpage_421_184_184") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xB8,0xB8,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x20,0x00,0x3F,0x00,0x20,0x00,0x20, + 0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_423_156_156[45] U8G_FONT_SECTION("fontpage_423_156_156") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0xFA,0x80,0x4A,0x80,0x4E,0x80,0x4A,0x80,0x4A, + 0x80,0xFE,0x80,0x02,0x80,0x12,0x80,0x10,0x00,0x10,0x00,0x1F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_426_132_132[41] U8G_FONT_SECTION("fontpage_426_132_132") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x09,0x00,0x00, + 0x00,0x0A,0x09,0x12,0x0A,0x00,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x12,0x00,0x12, + 0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_426_216_216[45] U8G_FONT_SECTION("fontpage_426_216_216") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x71,0x00,0x01,0x00,0xFD,0x00,0x01,0x00,0x71, + 0x80,0x89,0x00,0x89,0x00,0x89,0x00,0x71,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_426_233_233[45] U8G_FONT_SECTION("fontpage_426_233_233") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xE9,0xE9,0x00,0x09,0xFE,0x00, + 0x00,0x09,0x0B,0x16,0x0A,0x01,0xFE,0x71,0x00,0x01,0x00,0xFD,0x00,0x49,0x80,0x89, + 0x00,0x79,0x00,0x00,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x7E,0x00}; +const u8g_fntpgm_uint8_t fontpage_428_200_200[45] U8G_FONT_SECTION("fontpage_428_200_200") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x0E,0x00,0x00,0x00,0x7F,0x80,0x21,0x00,0x1E, + 0x00,0x04,0x00,0xFF,0xC0,0x00,0x00,0x3F,0x00,0x20,0x80,0x3F,0x00}; +const u8g_fntpgm_uint8_t fontpage_428_212_212[45] U8G_FONT_SECTION("fontpage_428_212_212") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x09,0xFE,0x00, + 0x00,0x0A,0x0B,0x16,0x0A,0x00,0xFE,0x38,0x80,0x00,0x80,0x7E,0x80,0x00,0x80,0x38, + 0x80,0x44,0xC0,0x3C,0x80,0x10,0x80,0xFE,0x80,0x00,0x80,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_431_136_136[34] U8G_FONT_SECTION("fontpage_431_136_136") = { + 0x00,0x0B,0x0D,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x09,0xFE,0x00, + 0x00,0x08,0x0B,0x0B,0x0A,0x01,0xFE,0x71,0x01,0xFD,0x01,0x71,0x49,0x89,0x49,0x71, + 0x01,0x01}; + +static const uxg_fontinfo_t g_fontinfo_ko_KR[] PROGMEM = { + FONTDATA_ITEM(344, 240, 240, fontpage_344_240_240), // '거' -- '거' + FONTDATA_ITEM(345, 224, 224, fontpage_345_224_224), // '고' -- '고' + FONTDATA_ITEM(347, 248, 248, fontpage_347_248_248), // '그' -- '그' + FONTDATA_ITEM(348, 137, 137, fontpage_348_137_137), // '급' -- '급' + FONTDATA_ITEM(348, 176, 176, fontpage_348_176_176), // '기' -- '기' + FONTDATA_ITEM(348, 197, 197, fontpage_348_197_197), // '깅' -- '깅' + FONTDATA_ITEM(352, 196, 196, fontpage_352_196_196), // '끄' -- '끄' + FONTDATA_ITEM(353, 180, 180, fontpage_353_180_180), // '내' -- '내' + FONTDATA_ITEM(354, 248, 248, fontpage_354_248_248), // '노' -- '노' + FONTDATA_ITEM(356, 132, 132, fontpage_356_132_132), // '누' -- '누' + FONTDATA_ITEM(356, 244, 244, fontpage_356_244_244), // '뉴' -- '뉴' + FONTDATA_ITEM(357, 200, 200, fontpage_357_200_200), // '니' -- '니' + FONTDATA_ITEM(357, 228, 228, fontpage_357_228_228), // '다' -- '다' + FONTDATA_ITEM(357, 249, 249, fontpage_357_249_249), // '당' -- '당' + FONTDATA_ITEM(359, 196, 196, fontpage_359_196_196), // '도' -- '도' + FONTDATA_ITEM(359, 204, 204, fontpage_359_204_204), // '돌' -- '돌' + FONTDATA_ITEM(359, 217, 217, fontpage_359_217_217), // '동' -- '동' + FONTDATA_ITEM(360, 152, 152, fontpage_360_152_152), // '되' -- '되' + FONTDATA_ITEM(360, 156, 156, fontpage_360_156_156), // '된' -- '된' + FONTDATA_ITEM(360, 168, 168, fontpage_360_168_168), // '됨' -- '됨' + FONTDATA_ITEM(361, 164, 164, fontpage_361_164_164), // '뒤' -- '뒤' + FONTDATA_ITEM(361, 220, 220, fontpage_361_220_220), // '드' -- '드' + FONTDATA_ITEM(362, 148, 148, fontpage_362_148_148), // '디' -- '디' + FONTDATA_ITEM(366, 252, 252, fontpage_366_252_252), // '라' -- '라' + FONTDATA_ITEM(367, 236, 236, fontpage_367_236_236), // '러' -- '러' + FONTDATA_ITEM(368, 136, 136, fontpage_368_136_136), // '레' -- '레' + FONTDATA_ITEM(368, 165, 165, fontpage_368_165_165), // '력' -- '력' + FONTDATA_ITEM(368, 220, 220, fontpage_368_220_220), // '로' -- '로' + FONTDATA_ITEM(369, 204, 204, fontpage_369_204_204), // '료' -- '료' + FONTDATA_ITEM(370, 244, 244, fontpage_370_244_244), // '르' -- '르' + FONTDATA_ITEM(371, 172, 172, fontpage_371_172_172), // '리' -- '리' + FONTDATA_ITEM(371, 176, 176, fontpage_371_176_176), // '린' -- '린' + FONTDATA_ITEM(371, 189, 189, fontpage_371_189_189), // '립' -- '립' + FONTDATA_ITEM(371, 193, 193, fontpage_371_193_193), // '링' -- '링' + FONTDATA_ITEM(372, 200, 200, fontpage_372_200_200), // '멈' -- '멈' + FONTDATA_ITEM(372, 212, 212, fontpage_372_212_212), // '메' -- '메' + FONTDATA_ITEM(372, 244, 244, fontpage_372_244_244), // '면' -- '면' + FONTDATA_ITEM(373, 168, 168, fontpage_373_168_168), // '모' -- '모' + FONTDATA_ITEM(373, 187, 187, fontpage_373_187_187), // '못' -- '못' + FONTDATA_ITEM(375, 248, 248, fontpage_375_248_248), // '미' -- '미' + FONTDATA_ITEM(376, 128, 128, fontpage_376_128_128), // '밀' -- '밀' + FONTDATA_ITEM(376, 148, 148, fontpage_376_148_148), // '바' -- '바' + FONTDATA_ITEM(377, 132, 132, fontpage_377_132_132), // '버' -- '버' + FONTDATA_ITEM(377, 160, 160, fontpage_377_160_160), // '베' -- '베' + FONTDATA_ITEM(377, 168, 168, fontpage_377_168_168), // '벨' -- '벨' + FONTDATA_ITEM(377, 248, 248, fontpage_377_248_248), // '본' -- '본' + FONTDATA_ITEM(380, 196, 196, fontpage_380_196_196), // '비' -- '비' + FONTDATA_ITEM(385, 172, 172, fontpage_385_172_172), // '사' -- '사' + FONTDATA_ITEM(385, 189, 189, fontpage_385_189_189), // '삽' -- '삽' + FONTDATA_ITEM(385, 200, 200, fontpage_385_200_200), // '새' -- '새' + FONTDATA_ITEM(386, 164, 164, fontpage_386_164_164), // '설' -- '설' + FONTDATA_ITEM(387, 140, 141, fontpage_387_140_141), // '소' -- '속' + FONTDATA_ITEM(389, 164, 164, fontpage_389_164_164), // '스' -- '스' + FONTDATA_ITEM(389, 172, 172, fontpage_389_172_172), // '슬' -- '슬' + FONTDATA_ITEM(389, 220, 221, fontpage_389_220_221), // '시' -- '식' + FONTDATA_ITEM(395, 180, 180, fontpage_395_180_180), // '어' -- '어' + FONTDATA_ITEM(395, 198, 198, fontpage_395_198_198), // '없' -- '없' + FONTDATA_ITEM(395, 209, 209, fontpage_395_209_209), // '엑' -- '엑' + FONTDATA_ITEM(395, 212, 212, fontpage_395_212_212), // '엔' -- '엔' + FONTDATA_ITEM(395, 244, 244, fontpage_395_244_244), // '열' -- '열' + FONTDATA_ITEM(396, 136, 136, fontpage_396_136_136), // '예' -- '예' + FONTDATA_ITEM(396, 164, 164, fontpage_396_164_164), // '오' -- '오' + FONTDATA_ITEM(396, 168, 168, fontpage_396_168_168), // '온' -- '온' + FONTDATA_ITEM(396, 196, 196, fontpage_396_196_196), // '완' -- '완' + FONTDATA_ITEM(397, 208, 208, fontpage_397_208_208), // '원' -- '원' + FONTDATA_ITEM(398, 132, 132, fontpage_398_132_132), // '위' -- '위' + FONTDATA_ITEM(398, 188, 188, fontpage_398_188_188), // '으' -- '으' + FONTDATA_ITEM(398, 204, 204, fontpage_398_204_204), // '음' -- '음' + FONTDATA_ITEM(398, 244, 244, fontpage_398_244_244), // '이' -- '이' + FONTDATA_ITEM(398, 252, 253, fontpage_398_252_253), // '일' -- '읽' + FONTDATA_ITEM(399, 133, 133, fontpage_399_133_133), // '입' -- '입' + FONTDATA_ITEM(399, 144, 145, fontpage_399_144_145), // '자' -- '작' + FONTDATA_ITEM(399, 152, 152, fontpage_399_152_152), // '잘' -- '잘' + FONTDATA_ITEM(399, 165, 165, fontpage_399_165_165), // '장' -- '장' + FONTDATA_ITEM(399, 172, 172, fontpage_399_172_172), // '재' -- '재' + FONTDATA_ITEM(400, 128, 128, fontpage_400_128_128), // '저' -- '저' + FONTDATA_ITEM(400, 132, 132, fontpage_400_132_132), // '전' -- '전' + FONTDATA_ITEM(400, 149, 149, fontpage_400_149_149), // '정' -- '정' + FONTDATA_ITEM(400, 156, 156, fontpage_400_156_156), // '제' -- '제' + FONTDATA_ITEM(401, 253, 253, fontpage_401_253_253), // '죽' -- '죽' + FONTDATA_ITEM(402, 128, 128, fontpage_402_128_128), // '준' -- '준' + FONTDATA_ITEM(402, 145, 145, fontpage_402_145_145), // '중' -- '중' + FONTDATA_ITEM(403, 144, 144, fontpage_403_144_144), // '즐' -- '즐' + FONTDATA_ITEM(403, 192, 192, fontpage_403_192_192), // '지' -- '지' + FONTDATA_ITEM(409, 152, 152, fontpage_409_152_152), // '처' -- '처' + FONTDATA_ITEM(410, 136, 136, fontpage_410_136_136), // '초' -- '초' + FONTDATA_ITEM(411, 149, 149, fontpage_411_149_149), // '축' -- '축' + FONTDATA_ITEM(411, 156, 156, fontpage_411_156_156), // '출' -- '출' + FONTDATA_ITEM(411, 164, 164, fontpage_411_164_164), // '춤' -- '춤' + FONTDATA_ITEM(411, 232, 232, fontpage_411_232_232), // '취' -- '취' + FONTDATA_ITEM(412, 216, 216, fontpage_412_216_216), // '치' -- '치' + FONTDATA_ITEM(412, 232, 232, fontpage_412_232_232), // '침' -- '침' + FONTDATA_ITEM(412, 244, 244, fontpage_412_244_244), // '카' -- '카' + FONTDATA_ITEM(414, 156, 156, fontpage_414_156_156), // '켜' -- '켜' + FONTDATA_ITEM(417, 209, 209, fontpage_417_209_209), // '탑' -- '탑' + FONTDATA_ITEM(418, 176, 176, fontpage_418_176_176), // '터' -- '터' + FONTDATA_ITEM(418, 204, 204, fontpage_418_204_204), // '테' -- '테' + FONTDATA_ITEM(419, 160, 160, fontpage_419_160_160), // '토' -- '토' + FONTDATA_ITEM(421, 184, 184, fontpage_421_184_184), // '트' -- '트' + FONTDATA_ITEM(423, 156, 156, fontpage_423_156_156), // '펜' -- '펜' + FONTDATA_ITEM(426, 132, 132, fontpage_426_132_132), // '프' -- '프' + FONTDATA_ITEM(426, 216, 216, fontpage_426_216_216), // '하' -- '하' + FONTDATA_ITEM(426, 233, 233, fontpage_426_233_233), // '합' -- '합' + FONTDATA_ITEM(428, 200, 200, fontpage_428_200_200), // '홈' -- '홈' + FONTDATA_ITEM(428, 212, 212, fontpage_428_212_212), // '화' -- '화' + FONTDATA_ITEM(431, 136, 136, fontpage_431_136_136), // '히' -- '히' +}; diff --git a/src/lcd/dogm/fontdata/langdata_nl.h b/src/lcd/dogm/fontdata/langdata_nl.h new file mode 100644 index 0000000..e76eff3 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_nl.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_nl[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_pl.h b/src/lcd/dogm/fontdata/langdata_pl.h new file mode 100644 index 0000000..e89a6c1 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_pl.h @@ -0,0 +1,41 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_132_133[45] U8G_FONT_SECTION("fontpage_2_132_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x84,0x85,0x00,0x07,0xFE,0x00, + 0x00,0x05,0x09,0x09,0x06,0x00,0xFE,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x10,0x08, + 0x05,0x07,0x07,0x06,0x00,0xFE,0x70,0x08,0x78,0x88,0x78,0x20,0x30}; +const u8g_fntpgm_uint8_t fontpage_2_135_135[31] U8G_FONT_SECTION("fontpage_2_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x80,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_2_153_153[30] U8G_FONT_SECTION("fontpage_2_153_153") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x99,0x99,0x00,0x05,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0xFE,0x70,0x88,0xF0,0x80,0x70,0x20,0x30}; +const u8g_fntpgm_uint8_t fontpage_2_193_196[73] U8G_FONT_SECTION("fontpage_2_193_196") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC1,0xC4,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x40,0x60,0xC0,0x40,0x40,0x78,0x03,0x07, + 0x07,0x06,0x01,0x00,0xC0,0x40,0x60,0xC0,0x40,0x40,0xE0,0x05,0x0A,0x0A,0x06,0x00, + 0x00,0x10,0x20,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x05,0x08,0x08,0x06,0x00, + 0x00,0x10,0x20,0x00,0xB0,0xC8,0x88,0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_2_218_219[47] U8G_FONT_SECTION("fontpage_2_218_219") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDA,0xDB,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x80,0x70,0x08,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x10,0x20,0x00,0x78,0x80,0x70,0x08,0xF0}; +const u8g_fntpgm_uint8_t fontpage_2_252_252[30] U8G_FONT_SECTION("fontpage_2_252_252") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x00,0xF8,0x10,0x20,0x40,0xF8}; + +static const uxg_fontinfo_t g_fontinfo_pl[] PROGMEM = { + FONTDATA_ITEM(2, 132, 133, fontpage_2_132_133), // 'Ą' -- 'ą' + FONTDATA_ITEM(2, 135, 135, fontpage_2_135_135), // 'ć' -- 'ć' + FONTDATA_ITEM(2, 153, 153, fontpage_2_153_153), // 'ę' -- 'ę' + FONTDATA_ITEM(2, 193, 196, fontpage_2_193_196), // 'Ł' -- 'ń' + FONTDATA_ITEM(2, 218, 219, fontpage_2_218_219), // 'Ś' -- 'ś' + FONTDATA_ITEM(2, 252, 252, fontpage_2_252_252), // 'ż' -- 'ż' +}; diff --git a/src/lcd/dogm/fontdata/langdata_pt.h b/src/lcd/dogm/fontdata/langdata_pt.h new file mode 100644 index 0000000..61f857e --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_pt.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_pt[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_pt_br.h b/src/lcd/dogm/fontdata/langdata_pt_br.h new file mode 100644 index 0000000..b0ed5ad --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_pt_br.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_pt_br[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_ro.h b/src/lcd/dogm/fontdata/langdata_ro.h new file mode 100644 index 0000000..6be4863 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_ro.h @@ -0,0 +1,10 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +static const uxg_fontinfo_t g_fontinfo_ro[] PROGMEM = {}; diff --git a/src/lcd/dogm/fontdata/langdata_ru.h b/src/lcd/dogm/fontdata/langdata_ru.h new file mode 100644 index 0000000..3f857a1 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_ru.h @@ -0,0 +1,74 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_8_144_168[348] U8G_FONT_SECTION("fontpage_8_144_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0xA8,0x00,0x0A,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF0,0x80,0x80,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80, + 0x80,0x80,0x80,0x80,0x80,0x05,0x08,0x08,0x06,0x00,0xFF,0x30,0x50,0x50,0x50,0x50, + 0x50,0xF8,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8, + 0x05,0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0x70,0x20,0x70,0xA8,0xA8,0x05,0x07,0x07, + 0x06,0x00,0x00,0x70,0x88,0x08,0x70,0x08,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00, + 0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x88,0x70,0x00, + 0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0, + 0xC0,0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x48,0x48, + 0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x88, + 0x88,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0x80, + 0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x05, + 0x07,0x07,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06, + 0x00,0x00,0x88,0x88,0x88,0x88,0x78,0x08,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x20, + 0x70,0xA8,0xA8,0xA8,0x70,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x50,0x20, + 0x50,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0xFE,0x90,0x90,0x90,0x90,0x90,0x90,0xF8, + 0x08,0x08,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x78,0x08,0x08,0x08,0x05, + 0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0xA8,0xA8,0xA8,0xA8,0xF8}; +const u8g_fntpgm_uint8_t fontpage_8_171_173[56] U8G_FONT_SECTION("fontpage_8_171_173") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAD,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xC8,0xA8,0xA8,0xC8,0x04,0x07, + 0x07,0x06,0x01,0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0xE0,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x08,0x78,0x08,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_8_175_207[400] U8G_FONT_SECTION("fontpage_8_175_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xCF,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x78,0x88,0x88,0x78,0x28,0x48,0x88,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00,0x00,0x70, + 0x80,0xF0,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF0,0x88,0xF0,0x88, + 0xF0,0x05,0x05,0x05,0x06,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x05,0x06,0x06,0x06, + 0x00,0xFF,0x30,0x50,0x50,0x50,0xF8,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88, + 0xF0,0x80,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0x70,0x20,0x70,0xA8,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x88,0x30,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x88, + 0x98,0xA8,0xC8,0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x88,0x70,0x00,0x88,0x98,0xA8, + 0xC8,0x88,0x04,0x05,0x05,0x06,0x01,0x00,0x90,0xA0,0xC0,0xA0,0x90,0x05,0x05,0x05, + 0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0xD8, + 0xA8,0x88,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0xF8,0x88,0x88,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF8, + 0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0xFE,0xF0,0x88,0x88,0x88,0xF0,0x80, + 0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x05,0x05,0x05,0x06, + 0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88, + 0x88,0x78,0x08,0x70,0x05,0x09,0x09,0x06,0x00,0xFE,0x20,0x20,0x70,0xA8,0xA8,0xA8, + 0x70,0x20,0x20,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x05,0x07, + 0x07,0x06,0x00,0xFE,0x90,0x90,0x90,0x90,0xF8,0x08,0x08,0x05,0x05,0x05,0x06,0x00, + 0x00,0x88,0x88,0x78,0x08,0x08,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0xA8,0xA8,0xA8, + 0xF8,0x05,0x07,0x07,0x06,0x00,0xFE,0xA8,0xA8,0xA8,0xA8,0xF8,0x08,0x08,0x05,0x05, + 0x05,0x06,0x00,0x00,0xC0,0x40,0x70,0x48,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x88, + 0x88,0xC8,0xA8,0xC8,0x04,0x05,0x05,0x06,0x01,0x00,0x80,0x80,0xE0,0x90,0xE0,0x04, + 0x05,0x05,0x06,0x01,0x00,0xE0,0x10,0x70,0x10,0xE0,0x05,0x05,0x05,0x06,0x00,0x00, + 0x90,0xA8,0xE8,0xA8,0x90,0x04,0x05,0x05,0x06,0x01,0x00,0x70,0x90,0x70,0x50,0x90 + }; +const u8g_fntpgm_uint8_t fontpage_8_209_209[30] U8G_FONT_SECTION("fontpage_8_209_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x50,0x00,0x70,0x88,0xF0,0x80,0x70}; + +static const uxg_fontinfo_t g_fontinfo_ru[] PROGMEM = { + FONTDATA_ITEM(8, 144, 168, fontpage_8_144_168), // 'А' -- 'Ш' + FONTDATA_ITEM(8, 171, 173, fontpage_8_171_173), // 'Ы' -- 'Э' + FONTDATA_ITEM(8, 175, 207, fontpage_8_175_207), // 'Я' -- 'я' + FONTDATA_ITEM(8, 209, 209, fontpage_8_209_209), // 'ё' -- 'ё' +}; diff --git a/src/lcd/dogm/fontdata/langdata_sk.h b/src/lcd/dogm/fontdata/langdata_sk.h new file mode 100644 index 0000000..4580ce5 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_sk.h @@ -0,0 +1,50 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_140_143[79] U8G_FONT_SECTION("fontpage_2_140_143") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8F,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x80,0x80,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x88,0x70,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0xF0,0x06, + 0x0A,0x0A,0x06,0x00,0x00,0x14,0x08,0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_2_186_186[33] U8G_FONT_SECTION("fontpage_2_186_186") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBA,0xBA,0x00,0x0A,0x00,0x00, + 0x00,0x03,0x0A,0x0A,0x06,0x01,0x00,0x20,0x40,0x00,0xC0,0x40,0x40,0x40,0x40,0x40, + 0xE0}; +const u8g_fntpgm_uint8_t fontpage_2_189_190[49] U8G_FONT_SECTION("fontpage_2_189_190") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBD,0xBE,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x80,0x80,0x80,0x80,0x80,0x80, + 0xF8,0x03,0x0A,0x0A,0x06,0x01,0x00,0xA0,0x40,0x00,0xC0,0x40,0x40,0x40,0x40,0x40, + 0xE0}; +const u8g_fntpgm_uint8_t fontpage_2_199_200[47] U8G_FONT_SECTION("fontpage_2_199_200") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC8,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88, + 0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0xB0,0xC8,0x88,0x88,0x88}; +const u8g_fntpgm_uint8_t fontpage_2_224_225[47] U8G_FONT_SECTION("fontpage_2_224_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE1,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x70,0x88,0x80,0x70,0x08,0x88, + 0x70,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0x78,0x80,0x70,0x08,0xF0}; +const u8g_fntpgm_uint8_t fontpage_2_229_229[33] U8G_FONT_SECTION("fontpage_2_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0x20,0x20,0xF8,0x20,0x20,0x20, + 0x18}; +const u8g_fntpgm_uint8_t fontpage_2_253_254[47] U8G_FONT_SECTION("fontpage_2_253_254") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFE,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x50,0x20,0x00,0xF8,0x08,0x10,0x20,0x40,0x80, + 0xF8,0x05,0x08,0x08,0x06,0x00,0x00,0x50,0x20,0x00,0xF8,0x10,0x20,0x40,0xF8}; + +static const uxg_fontinfo_t g_fontinfo_sk[] PROGMEM = { + FONTDATA_ITEM(2, 140, 143, fontpage_2_140_143), // 'Č' -- 'ď' + FONTDATA_ITEM(2, 186, 186, fontpage_2_186_186), // 'ĺ' -- 'ĺ' + FONTDATA_ITEM(2, 189, 190, fontpage_2_189_190), // 'Ľ' -- 'ľ' + FONTDATA_ITEM(2, 199, 200, fontpage_2_199_200), // 'Ň' -- 'ň' + FONTDATA_ITEM(2, 224, 225, fontpage_2_224_225), // 'Š' -- 'š' + FONTDATA_ITEM(2, 229, 229, fontpage_2_229_229), // 'ť' -- 'ť' + FONTDATA_ITEM(2, 253, 254, fontpage_2_253_254), // 'Ž' -- 'ž' +}; diff --git a/src/lcd/dogm/fontdata/langdata_test.h b/src/lcd/dogm/fontdata/langdata_test.h new file mode 100644 index 0000000..da76a31 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_test.h @@ -0,0 +1,232 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_8_128_255[1677] U8G_FONT_SECTION("fontpage_8_128_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x00,0x0A,0xFE,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40,0x20,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80, + 0xF8,0x05,0x09,0x09,0x06,0x00,0x00,0x50,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8, + 0x05,0x09,0x09,0x06,0x00,0xFE,0xE0,0x40,0x40,0x70,0x48,0x48,0x48,0x08,0x30,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0x10,0x20,0x00,0xF8,0x80,0x80,0x80,0x80,0x80,0x80,0x05, + 0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0xF0,0x80,0x88,0x70,0x05,0x07,0x07,0x06, + 0x00,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x03,0x07,0x07,0x06,0x01,0x00,0xE0, + 0x40,0x40,0x40,0x40,0x40,0xE0,0x03,0x09,0x09,0x06,0x01,0x00,0xA0,0x00,0xE0,0x40, + 0x40,0x40,0x40,0x40,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x38,0x10,0x10,0x10,0x10, + 0x90,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x60,0xA0,0xA0,0xB0,0xA8,0xA8,0xB0,0x05, + 0x07,0x07,0x06,0x00,0x00,0xA0,0xA0,0xA0,0xF0,0xA8,0xA8,0xB0,0x05,0x07,0x07,0x06, + 0x00,0x00,0xE0,0x40,0x40,0x70,0x48,0x48,0x48,0x05,0x0A,0x0A,0x06,0x00,0x00,0x10, + 0x20,0x00,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x40, + 0x20,0x00,0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x88, + 0x70,0x00,0x88,0x88,0x88,0x88,0x78,0x08,0x70,0x05,0x09,0x09,0x06,0x00,0xFE,0x88, + 0x88,0x88,0x88,0x88,0x88,0xF8,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88, + 0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x80,0x80,0xF0,0x88, + 0x88,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x05, + 0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x80,0x80,0x05,0x08,0x08,0x06, + 0x00,0xFF,0x30,0x50,0x50,0x50,0x50,0x50,0xF8,0x88,0x05,0x07,0x07,0x06,0x00,0x00, + 0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0x70, + 0x20,0x70,0xA8,0xA8,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x08,0x70,0x08,0x88, + 0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x0A, + 0x0A,0x06,0x00,0x00,0x88,0x70,0x00,0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x38,0x48,0x48,0x48,0x48,0x48,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8, + 0xA8,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88, + 0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05, + 0x07,0x07,0x06,0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06, + 0x00,0x00,0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70, + 0x88,0x80,0x80,0x80,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x20,0x20,0x20, + 0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x88,0x78,0x08,0x70, + 0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x70,0xA8,0xA8,0xA8,0x70,0x20,0x05,0x07,0x07, + 0x06,0x00,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0xFE, + 0x90,0x90,0x90,0x90,0x90,0x90,0xF8,0x08,0x08,0x05,0x07,0x07,0x06,0x00,0x00,0x88, + 0x88,0x88,0x78,0x08,0x08,0x08,0x05,0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0xA8,0xA8, + 0xA8,0xA8,0xF8,0x05,0x09,0x09,0x06,0x00,0xFE,0xA8,0xA8,0xA8,0xA8,0xA8,0xA8,0xF8, + 0x08,0x08,0x05,0x07,0x07,0x06,0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x70,0x05, + 0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xC8,0xA8,0xA8,0xC8,0x04,0x07,0x07,0x06, + 0x01,0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0xE0,0x05,0x07,0x07,0x06,0x00,0x00,0x70, + 0x88,0x08,0x78,0x08,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x90,0xA8,0xA8,0xE8, + 0xA8,0xA8,0x90,0x05,0x07,0x07,0x06,0x00,0x00,0x78,0x88,0x88,0x78,0x28,0x48,0x88, + 0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x80,0xF0,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF0,0x88, + 0xF0,0x88,0xF0,0x05,0x05,0x05,0x06,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x05,0x06, + 0x06,0x06,0x00,0xFF,0x30,0x50,0x50,0x50,0xF8,0x88,0x05,0x05,0x05,0x06,0x00,0x00, + 0x70,0x88,0xF0,0x80,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0x70,0x20,0x70,0xA8, + 0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x30,0x88,0x70,0x05,0x05,0x05,0x06,0x00, + 0x00,0x88,0x98,0xA8,0xC8,0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x88,0x70,0x00,0x88, + 0x98,0xA8,0xC8,0x88,0x04,0x05,0x05,0x06,0x01,0x00,0x90,0xA0,0xC0,0xA0,0x90,0x05, + 0x05,0x05,0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x88,0x05,0x05,0x05,0x06,0x00,0x00, + 0x88,0xD8,0xA8,0x88,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0xF8,0x88,0x88, + 0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00, + 0x00,0xF8,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0xFE,0xF0,0x88,0x88,0x88, + 0xF0,0x80,0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x05,0x05, + 0x05,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0xFE,0x88, + 0x88,0x88,0x88,0x78,0x08,0x70,0x05,0x09,0x09,0x06,0x00,0xFE,0x20,0x20,0x70,0xA8, + 0xA8,0xA8,0x70,0x20,0x20,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x50,0x20,0x50,0x88, + 0x05,0x07,0x07,0x06,0x00,0xFE,0x90,0x90,0x90,0x90,0xF8,0x08,0x08,0x05,0x05,0x05, + 0x06,0x00,0x00,0x88,0x88,0x78,0x08,0x08,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0xA8, + 0xA8,0xA8,0xF8,0x05,0x07,0x07,0x06,0x00,0xFE,0xA8,0xA8,0xA8,0xA8,0xF8,0x08,0x08, + 0x05,0x05,0x05,0x06,0x00,0x00,0xC0,0x40,0x70,0x48,0x70,0x05,0x05,0x05,0x06,0x00, + 0x00,0x88,0x88,0xC8,0xA8,0xC8,0x04,0x05,0x05,0x06,0x01,0x00,0x80,0x80,0xE0,0x90, + 0xE0,0x04,0x05,0x05,0x06,0x01,0x00,0xE0,0x10,0x70,0x10,0xE0,0x05,0x05,0x05,0x06, + 0x00,0x00,0x90,0xA8,0xE8,0xA8,0x90,0x04,0x05,0x05,0x06,0x01,0x00,0x70,0x90,0x70, + 0x50,0x90,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0x20,0x00,0x70,0x88,0xF0,0x80,0x70, + 0x05,0x07,0x07,0x06,0x00,0x00,0x50,0x00,0x70,0x88,0xF0,0x80,0x70,0x05,0x09,0x09, + 0x06,0x00,0xFE,0x40,0xE0,0x40,0x70,0x48,0x48,0x48,0x08,0x10,0x05,0x08,0x08,0x06, + 0x00,0x00,0x10,0x20,0x00,0xF8,0x80,0x80,0x80,0x80,0x04,0x05,0x05,0x06,0x01,0x00, + 0x70,0x80,0xE0,0x80,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x78,0x80,0x70,0x08,0xF0, + 0x03,0x06,0x06,0x06,0x01,0x00,0x40,0x00,0xC0,0x40,0x40,0xE0,0x03,0x06,0x06,0x06, + 0x01,0x00,0xA0,0x00,0xC0,0x40,0x40,0xE0,0x04,0x08,0x08,0x06,0x01,0xFE,0x10,0x00, + 0x30,0x10,0x10,0x10,0x90,0x60,0x05,0x05,0x05,0x06,0x00,0x00,0x60,0xA0,0xB0,0xA8, + 0xB0,0x05,0x05,0x05,0x06,0x00,0x00,0xA0,0xA0,0xF0,0xA8,0xB0,0x05,0x07,0x07,0x06, + 0x00,0x00,0x40,0xE0,0x40,0x70,0x48,0x48,0x48,0x04,0x08,0x08,0x06,0x01,0x00,0x20, + 0x40,0x00,0x90,0xA0,0xC0,0xA0,0x90,0x05,0x08,0x08,0x06,0x00,0x00,0x40,0x20,0x00, + 0x88,0x98,0xA8,0xC8,0x88,0x05,0x0A,0x0A,0x06,0x00,0xFE,0x88,0x70,0x00,0x88,0x88, + 0x88,0x88,0x78,0x08,0x70,0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88,0x88,0xF8, + 0x20,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x50,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x05, + 0x05,0x05,0x06,0x00,0x00,0x50,0x88,0xA8,0xA8,0x50,0x05,0x07,0x07,0x06,0x00,0x00, + 0x40,0xF0,0x40,0x70,0x48,0x48,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x40,0xF0, + 0x40,0x70,0x48,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x98,0xA0,0xA0,0xF8,0xA0,0xA0, + 0x98,0x05,0x05,0x05,0x06,0x00,0x00,0x98,0xA0,0xF8,0xA0,0x98,0x05,0x07,0x07,0x06, + 0x00,0x00,0x20,0x50,0x50,0x88,0xF8,0xA8,0xA8,0x05,0x06,0x06,0x06,0x00,0x00,0x20, + 0x50,0x50,0x88,0xF8,0xA8,0x05,0x07,0x07,0x06,0x00,0x00,0x90,0x90,0xB8,0xF8,0xB8, + 0xB8,0xB8,0x05,0x05,0x05,0x06,0x00,0x00,0x90,0x90,0xF8,0xB8,0xB8,0x05,0x08,0x08, + 0x06,0x00,0x00,0xF8,0x88,0x50,0x50,0x70,0xA8,0xA8,0xA8,0x05,0x06,0x06,0x06,0x00, + 0x00,0xF8,0x88,0x50,0x70,0xA8,0xA8,0x06,0x08,0x08,0x06,0x00,0x00,0xFC,0xC4,0xA8, + 0x90,0xF8,0xB8,0xB8,0xA8,0x06,0x06,0x06,0x06,0x00,0x00,0xFC,0xA8,0x90,0xF8,0xB8, + 0xA8,0x05,0x0C,0x0C,0x06,0x00,0xFE,0x50,0x20,0x00,0x70,0x88,0x08,0x30,0x08,0x08, + 0x70,0x80,0x70,0x05,0x0A,0x0A,0x06,0x00,0xFE,0x50,0x20,0x00,0x70,0x88,0x30,0x08, + 0x70,0x80,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0xA8,0x70,0x20,0x20,0x20, + 0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0xA8,0x70,0x20,0x20,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88, + 0xF8,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0x90,0x50,0x50,0x50,0x20, + 0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x90,0x50,0x50,0x20,0x05,0x0A,0x0A,0x06,0x00, + 0x00,0x90,0x48,0x00,0x88,0x90,0x90,0x50,0x50,0x50,0x20,0x05,0x08,0x08,0x06,0x00, + 0x00,0x90,0x48,0x00,0x88,0x90,0x50,0x50,0x20,0x05,0x09,0x09,0x06,0x00,0xFE,0x40, + 0xA0,0xA0,0xB8,0xB8,0xB8,0x58,0x08,0x10,0x05,0x07,0x07,0x06,0x00,0xFE,0x58,0xB8, + 0xB8,0xB8,0x58,0x08,0x10,0x05,0x0A,0x0A,0x06,0x00,0xFF,0x20,0x70,0xA8,0x88,0x88, + 0x88,0x88,0xA8,0x70,0x20,0x05,0x08,0x08,0x06,0x00,0xFF,0x20,0x70,0xA8,0x88,0x88, + 0xA8,0x70,0x20,0x05,0x09,0x09,0x06,0x00,0x00,0x70,0x00,0x20,0x20,0x88,0x88,0x88, + 0xA8,0x50,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x00,0x20,0xA8,0x88,0xA8,0x50,0x05, + 0x0A,0x0A,0x06,0x00,0x00,0xF8,0xA8,0x00,0x50,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x05, + 0x08,0x08,0x06,0x00,0x00,0xF8,0xA8,0x00,0x50,0x88,0xA8,0xA8,0x50}; +const u8g_fntpgm_uint8_t fontpage_97_129_191[911] U8G_FONT_SECTION("fontpage_97_129_191") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x81,0xBF,0x00,0x0D,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x04,0x00,0x4E,0x00,0x55,0x00,0x64, + 0x80,0x48,0x40,0xA8,0x40,0x90,0x40,0x90,0x80,0x61,0x00,0x06,0x00,0x08,0x0B,0x0B, + 0x0C,0x01,0xFF,0x20,0x10,0x70,0x1C,0x28,0xE2,0x39,0x21,0x21,0x12,0x0C,0x08,0x07, + 0x07,0x0C,0x02,0xFF,0x28,0x2E,0xF5,0x21,0x16,0x10,0x10,0x0B,0x0B,0x16,0x0C,0x00, + 0xFF,0x02,0x00,0x37,0x00,0x20,0x00,0x13,0xC0,0x9C,0x20,0x70,0x20,0x09,0xC0,0x08, + 0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x07,0x07,0x07,0x0C,0x03,0xFF,0x10,0x9C,0xB2, + 0xD2,0x9C,0x10,0x20,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x82,0x00,0x47,0x80, + 0x4A,0x40,0x52,0x20,0x62,0x20,0x6A,0x40,0x47,0x80,0x42,0x00,0x04,0x00,0x08,0x00, + 0x07,0x07,0x07,0x0C,0x02,0xFF,0x10,0x1C,0x10,0x10,0x78,0x96,0x60,0x09,0x0B,0x16, + 0x0C,0x01,0xFF,0x10,0x00,0x08,0x00,0x09,0x80,0x0E,0x00,0x08,0x00,0x08,0x00,0x08, + 0x00,0x78,0x00,0x8E,0x00,0x89,0x80,0x70,0x00,0x07,0x0B,0x0B,0x0C,0x02,0xFF,0x20, + 0x18,0x40,0x80,0x80,0xBC,0xC2,0x82,0x02,0x0C,0x70,0x07,0x0B,0x0B,0x0C,0x02,0xFF, + 0x88,0x54,0x52,0x62,0x62,0x42,0x42,0x04,0x04,0x08,0x10,0x08,0x0A,0x0A,0x0C,0x01, + 0xFF,0x4E,0x34,0x08,0x10,0x3E,0x61,0x81,0x19,0x26,0x1C,0x0B,0x0B,0x16,0x0C,0x00, + 0xFF,0x20,0x00,0x10,0x00,0x13,0x00,0x34,0x80,0xD8,0x80,0x10,0x80,0x10,0x80,0x30, + 0x80,0x50,0x80,0xB0,0x60,0x10,0x00,0x08,0x0A,0x0A,0x0C,0x01,0xFF,0x4E,0x34,0x08, + 0x10,0x3E,0x61,0x81,0x01,0x06,0x18,0x08,0x07,0x07,0x0C,0x02,0xFF,0x40,0x30,0xEE, + 0x31,0x61,0xA2,0x24,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x10,0x00,0x10,0x00, + 0x9B,0x80,0x7C,0x40,0x10,0x20,0x10,0x20,0x30,0x20,0x50,0x40,0xB1,0x80,0x10,0x00, + 0x0A,0x0A,0x14,0x0C,0x01,0xFF,0x4E,0x00,0x34,0x00,0x04,0x00,0x1F,0x00,0x28,0x80, + 0x48,0x40,0x90,0x40,0x96,0x40,0x69,0x80,0x47,0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF, + 0x20,0x00,0x1F,0x00,0x04,0x00,0x1F,0x00,0x20,0x80,0x4C,0x80,0x13,0x00,0x0C,0x00, + 0x00,0x00,0x59,0x80,0x86,0x40,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00, + 0x9E,0x00,0x70,0x00,0x21,0x80,0x72,0x00,0x8C,0x00,0x14,0x00,0x24,0x00,0x20,0x00, + 0x1F,0x00,0x0A,0x0A,0x14,0x0C,0x01,0xFF,0x10,0x00,0x08,0x00,0x08,0x00,0x10,0x00, + 0x10,0x00,0x38,0x00,0x24,0x00,0x44,0x40,0x44,0x80,0x83,0x00,0x0A,0x0B,0x16,0x0C, + 0x00,0xFF,0x10,0x00,0x0C,0x80,0x00,0x40,0x1D,0x00,0xE2,0x80,0x02,0x00,0x02,0x00, + 0x04,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0xFF,0xFF,0xFF,0xFF,0x04,0x03,0x03,0x06, + 0x00,0x05,0x20,0x90,0x40,0xFF,0x04,0x03,0x03,0x06,0x00,0x05,0x20,0x90,0x40,0x03, + 0x03,0x03,0x06,0x00,0x05,0x40,0xA0,0x40,0xFF,0xFF,0xFF,0x05,0x03,0x03,0x06,0x00, + 0x03,0xF8,0x00,0xF8,0x04,0x05,0x05,0x06,0x00,0x00,0xF0,0x10,0x60,0x40,0x80,0x05, + 0x07,0x07,0x06,0x00,0x00,0xF8,0x08,0x28,0x30,0x20,0x20,0x40,0x04,0x05,0x05,0x06, + 0x00,0x00,0x10,0x20,0x60,0xA0,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x08,0x10,0x20, + 0x60,0xA0,0x20,0x20,0x04,0x05,0x05,0x06,0x00,0x00,0x20,0xF0,0x90,0x10,0x20,0x05, + 0x07,0x07,0x06,0x00,0x00,0x20,0xF8,0x88,0x88,0x08,0x10,0x60,0x03,0x04,0x04,0x06, + 0x00,0x00,0xE0,0x40,0x40,0xE0,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x20,0x20,0x20, + 0x20,0xF8,0x04,0x05,0x05,0x06,0x00,0x00,0x20,0xF0,0x20,0x60,0xA0,0x05,0x07,0x07, + 0x06,0x00,0x00,0x10,0xF8,0x10,0x30,0x50,0x90,0x10,0x05,0x07,0x07,0x06,0x00,0x00, + 0x40,0xF8,0x48,0x48,0x48,0x48,0x98,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x40, + 0xF8,0x48,0x48,0x48,0x48,0x98,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0xF8,0x20,0x20, + 0xF8,0x10,0x10,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x20,0xF8,0x20,0x20,0xF8, + 0x10,0x10,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x78,0x48,0x88,0x08,0x10,0x60,0x05, + 0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x40,0x78,0x48,0x88,0x08,0x10,0x60,0x05,0x07, + 0x07,0x06,0x00,0x00,0x80,0xF8,0x90,0x90,0x10,0x10,0x20,0x05,0x09,0x09,0x06,0x00, + 0x00,0x28,0x28,0x80,0xF8,0x90,0x90,0x10,0x10,0x20,0x05,0x06,0x06,0x06,0x00,0x00, + 0xF8,0x08,0x08,0x08,0x08,0xF8,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0xF8, + 0x08,0x08,0x08,0x08,0xF8,0x05,0x07,0x07,0x06,0x00,0x00,0x50,0xF8,0x50,0x50,0x50, + 0x10,0x20,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x50,0xF8,0x50,0x50,0x50,0x10, + 0x20,0x05,0x06,0x06,0x06,0x00,0x00,0xC0,0x08,0xC8,0x08,0x10,0xE0,0x07,0x0D,0x0D, + 0x06,0x00,0x00,0x02,0x00,0x00,0x00,0x28,0x28,0x00,0xC0,0x08,0xC8,0x08,0x10,0xE0, + 0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x10,0x10,0x20,0x50,0x88,0x05,0x09,0x09,0x06, + 0x00,0x00,0x28,0x28,0x00,0x70,0x10,0x10,0x20,0x50,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x40,0x40,0xF8,0x48,0x50,0x40,0x38,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08, + 0x40,0x40,0xF8,0x48,0x50,0x40,0x38,0x05,0x06,0x06,0x06,0x00,0x00,0x88,0x48,0x48, + 0x10,0x10,0x20,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0x88,0x48,0x48,0x10, + 0x10,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x78,0x48,0xA8,0x18,0x10,0x60}; +const u8g_fntpgm_uint8_t fontpage_97_193_255[822] U8G_FONT_SECTION("fontpage_97_193_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC1,0xFF,0x00,0x09,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0x60,0x20,0xF8,0x20,0x20,0x40,0x05,0x09, + 0x09,0x06,0x00,0x00,0x28,0x08,0x10,0x60,0x20,0xF8,0x20,0x20,0x40,0x05,0x04,0x04, + 0x06,0x00,0x00,0xA8,0xA8,0x08,0x30,0x05,0x06,0x06,0x06,0x00,0x00,0xA8,0xA8,0xA8, + 0x08,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0xA8,0xA8,0xA8,0x08, + 0x10,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x00,0xF8,0x20,0x20,0x20,0x40,0x05, + 0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x70,0x00,0xF8,0x20,0x20,0x20,0x40,0x04,0x07, + 0x07,0x06,0x01,0x00,0x80,0x80,0xC0,0xA0,0x90,0x80,0x80,0x04,0x09,0x09,0x06,0x01, + 0x00,0x50,0x10,0x80,0x80,0xC0,0xA0,0x90,0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00, + 0x20,0x20,0xF8,0x20,0x20,0x40,0x80,0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x00,0x00, + 0x00,0x00,0xF8,0x05,0x06,0x06,0x06,0x00,0x00,0x78,0x08,0x28,0x10,0x28,0xC0,0x05, + 0x07,0x07,0x06,0x00,0x00,0x20,0x70,0x10,0x20,0x70,0xA8,0x20,0x03,0x06,0x06,0x06, + 0x01,0x00,0x20,0x20,0x20,0x40,0x40,0x80,0x05,0x06,0x06,0x06,0x00,0x00,0x10,0x50, + 0x50,0x48,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0x10,0x50,0x50, + 0x48,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0x00,0x18,0x18,0x00,0x10,0x50,0x50,0x48, + 0x88,0x88,0x04,0x06,0x06,0x06,0x00,0x00,0x80,0x90,0xE0,0x80,0x80,0x70,0x05,0x09, + 0x09,0x06,0x00,0x00,0x28,0x28,0x00,0x80,0x90,0xE0,0x80,0x80,0x70,0x05,0x09,0x09, + 0x06,0x00,0x00,0x18,0x18,0x00,0x80,0x90,0xE0,0x80,0x80,0x70,0x05,0x06,0x06,0x06, + 0x00,0x00,0xF8,0x08,0x08,0x08,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28, + 0x00,0xF8,0x08,0x08,0x08,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x18,0x18,0x00, + 0xF8,0x08,0x08,0x08,0x10,0x60,0x05,0x05,0x05,0x06,0x00,0x01,0x60,0xA0,0x10,0x10, + 0x08,0x05,0x08,0x08,0x06,0x00,0x01,0x28,0x28,0x00,0x60,0xA0,0x10,0x10,0x08,0x05, + 0x08,0x08,0x06,0x00,0x01,0x18,0x18,0x00,0x60,0xA0,0x10,0x10,0x08,0x05,0x07,0x07, + 0x06,0x00,0x00,0x20,0xF8,0x20,0xA8,0xA8,0xA8,0x20,0x05,0x09,0x09,0x06,0x00,0x00, + 0x28,0x08,0x20,0xF8,0x20,0xA8,0xA8,0xA8,0x20,0x05,0x09,0x09,0x06,0x00,0x00,0x18, + 0x18,0x20,0xF8,0x20,0xA8,0xA8,0xA8,0x20,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x08, + 0x08,0x50,0x20,0x10,0x04,0x06,0x06,0x06,0x01,0x00,0xE0,0x00,0xE0,0x00,0xC0,0x30, + 0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0x20,0x40,0x48,0xF8,0x08,0x05,0x06,0x06, + 0x06,0x00,0x00,0x08,0x48,0x30,0x10,0x28,0xC0,0x05,0x06,0x06,0x06,0x00,0x00,0xF0, + 0x40,0xF8,0x40,0x40,0x38,0x05,0x05,0x05,0x06,0x00,0x00,0x40,0xF8,0x48,0x50,0x40, + 0x05,0x07,0x07,0x06,0x00,0x00,0x40,0x40,0xF8,0x48,0x50,0x40,0x40,0x04,0x05,0x05, + 0x06,0x00,0x00,0x60,0x20,0x20,0x20,0xF0,0x05,0x06,0x06,0x06,0x00,0x00,0x70,0x10, + 0x10,0x10,0x10,0xF8,0x04,0x05,0x05,0x06,0x00,0x00,0xF0,0x10,0xF0,0x10,0xF0,0x05, + 0x06,0x06,0x06,0x00,0x00,0xF8,0x08,0xF8,0x08,0x08,0xF8,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x00,0xF8,0x08,0x08,0x10,0x60,0x04,0x07,0x07,0x06,0x00,0x00,0x10,0x90, + 0x90,0x90,0x90,0x10,0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x20,0x20,0xA0,0xA0,0xA8, + 0xA8,0xB0,0x05,0x06,0x06,0x06,0x00,0x00,0x80,0x80,0x80,0x88,0xB0,0xC0,0x05,0x06, + 0x06,0x06,0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xF8,0x04,0x05,0x05,0x06,0x00,0x00, + 0xF0,0x90,0x10,0x10,0x60,0x05,0x06,0x06,0x06,0x00,0x00,0xF8,0x88,0x88,0x08,0x10, + 0x60,0x05,0x07,0x07,0x06,0x00,0x00,0x10,0xF8,0x50,0x50,0xF8,0x10,0x10,0x05,0x06, + 0x06,0x06,0x00,0x00,0x70,0x10,0x20,0x20,0x20,0xF8,0x05,0x06,0x06,0x06,0x00,0x00, + 0xF8,0x08,0xF8,0x08,0x10,0x60,0x05,0x06,0x06,0x06,0x00,0x00,0xC0,0x08,0x08,0x08, + 0x10,0xE0,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x20,0xF8,0x88,0x88,0x08,0x10, + 0x60,0x04,0x05,0x05,0x06,0x00,0x00,0x40,0xF0,0x50,0x50,0xB0,0x04,0x05,0x05,0x06, + 0x00,0x00,0x80,0xF0,0xA0,0x20,0x40,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00, + 0xF8,0x88,0x88,0x08,0x10,0x60,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x08,0x10,0xF8, + 0x50,0x50,0xF8,0x10,0x10,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0x70,0x10, + 0x20,0x20,0x20,0xF8,0x05,0x09,0x09,0x06,0x00,0x00,0x28,0x28,0x00,0xF8,0x08,0xF8, + 0x08,0x10,0x60,0x02,0x02,0x02,0x06,0x02,0x03,0xC0,0xC0,0x05,0x02,0x02,0x06,0x00, + 0x03,0x80,0x78,0x05,0x04,0x04,0x06,0x00,0x02,0x80,0x60,0x10,0x08,0x05,0x07,0x07, + 0x06,0x00,0x02,0x28,0x28,0x00,0x80,0x60,0x10,0x08,0x05,0x06,0x06,0x06,0x00,0x00, + 0xF8,0x08,0x08,0x08,0x08,0x08}; + +static const uxg_fontinfo_t g_fontinfo_test[] PROGMEM = { + FONTDATA_ITEM(8, 128, 255, fontpage_8_128_255), // 'Ѐ' -- 'ѿ' + FONTDATA_ITEM(97, 129, 191, fontpage_97_129_191), // 'め' -- 'タ' + FONTDATA_ITEM(97, 193, 255, fontpage_97_193_255), // 'チ' -- 'ヿ' +}; diff --git a/src/lcd/dogm/fontdata/langdata_tr.h b/src/lcd/dogm/fontdata/langdata_tr.h new file mode 100644 index 0000000..0ac0243 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_tr.h @@ -0,0 +1,28 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_158_159[49] U8G_FONT_SECTION("fontpage_2_158_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9E,0x9F,0x00,0x0A,0xFE,0x00, + 0x00,0x05,0x0A,0x0A,0x06,0x00,0x00,0x88,0x70,0x00,0x70,0x88,0x80,0x80,0x98,0x88, + 0x70,0x05,0x0A,0x0A,0x06,0x00,0xFE,0x88,0x70,0x00,0x70,0x88,0x88,0x88,0x78,0x08, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_2_176_177[43] U8G_FONT_SECTION("fontpage_2_176_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB0,0xB1,0x00,0x09,0x00,0x00, + 0x00,0x03,0x09,0x09,0x06,0x01,0x00,0x40,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0xE0, + 0x03,0x05,0x05,0x06,0x01,0x00,0xC0,0x40,0x40,0x40,0xE0}; +const u8g_fntpgm_uint8_t fontpage_2_222_223[45] U8G_FONT_SECTION("fontpage_2_222_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDF,0x00,0x07,0xFE,0x00, + 0x00,0x05,0x09,0x09,0x06,0x00,0xFE,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x10,0x60, + 0x05,0x07,0x07,0x06,0x00,0xFE,0x78,0x80,0x70,0x08,0xF0,0x10,0x60}; + +static const uxg_fontinfo_t g_fontinfo_tr[] PROGMEM = { + FONTDATA_ITEM(2, 158, 159, fontpage_2_158_159), // 'Ğ' -- 'ğ' + FONTDATA_ITEM(2, 176, 177, fontpage_2_176_177), // 'İ' -- 'ı' + FONTDATA_ITEM(2, 222, 223, fontpage_2_222_223), // 'Ş' -- 'ş' +}; diff --git a/src/lcd/dogm/fontdata/langdata_uk.h b/src/lcd/dogm/fontdata/langdata_uk.h new file mode 100644 index 0000000..b25e2f6 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_uk.h @@ -0,0 +1,86 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_8_134_134[30] U8G_FONT_SECTION("fontpage_8_134_134") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x86,0x86,0x00,0x07,0x00,0x00, + 0x00,0x03,0x07,0x07,0x06,0x01,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0xE0}; +const u8g_fntpgm_uint8_t fontpage_8_144_169[363] U8G_FONT_SECTION("fontpage_8_144_169") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0xA9,0x00,0x0A,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0xF0,0x80,0x80,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00, + 0x00,0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80, + 0x80,0x80,0x80,0x80,0x80,0x05,0x08,0x08,0x06,0x00,0xFF,0x30,0x50,0x50,0x50,0x50, + 0x50,0xF8,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8, + 0x05,0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0x70,0x20,0x70,0xA8,0xA8,0x05,0x07,0x07, + 0x06,0x00,0x00,0x70,0x88,0x08,0x70,0x08,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00, + 0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x0A,0x0A,0x06,0x00,0x00,0x88,0x70,0x00, + 0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x90,0xA0, + 0xC0,0xA0,0x90,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x48,0x48, + 0x88,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x88,0x88,0x05,0x07, + 0x07,0x06,0x00,0x00,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00, + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0xF8,0x88, + 0x88,0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x88,0x88,0xF0,0x80, + 0x80,0x80,0x05,0x07,0x07,0x06,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x05, + 0x07,0x07,0x06,0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06, + 0x00,0x00,0x88,0x88,0x88,0x88,0x78,0x08,0x70,0x05,0x07,0x07,0x06,0x00,0x00,0x20, + 0x70,0xA8,0xA8,0xA8,0x70,0x20,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x50,0x20, + 0x50,0x88,0x88,0x05,0x09,0x09,0x06,0x00,0xFE,0x90,0x90,0x90,0x90,0x90,0x90,0xF8, + 0x08,0x08,0x05,0x07,0x07,0x06,0x00,0x00,0x88,0x88,0x88,0x78,0x08,0x08,0x08,0x05, + 0x07,0x07,0x06,0x00,0x00,0xA8,0xA8,0xA8,0xA8,0xA8,0xA8,0xF8,0x05,0x09,0x09,0x06, + 0x00,0xFE,0xA8,0xA8,0xA8,0xA8,0xA8,0xA8,0xF8,0x08,0x08}; +const u8g_fntpgm_uint8_t fontpage_8_172_172[30] U8G_FONT_SECTION("fontpage_8_172_172") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x07,0x00,0x00, + 0x00,0x04,0x07,0x07,0x06,0x01,0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0xE0}; +const u8g_fntpgm_uint8_t fontpage_8_175_201[334] U8G_FONT_SECTION("fontpage_8_175_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xC9,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x78,0x88,0x88,0x78,0x28,0x48,0x88,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x05,0x07,0x07,0x06,0x00,0x00,0x70, + 0x80,0xF0,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF0,0x88,0xF0,0x88, + 0xF0,0x05,0x05,0x05,0x06,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x05,0x06,0x06,0x06, + 0x00,0xFF,0x30,0x50,0x50,0x50,0xF8,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88, + 0xF0,0x80,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0x70,0x20,0x70,0xA8,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x88,0x30,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0x88, + 0x98,0xA8,0xC8,0x88,0x05,0x08,0x08,0x06,0x00,0x00,0x88,0x70,0x00,0x88,0x98,0xA8, + 0xC8,0x88,0x04,0x05,0x05,0x06,0x01,0x00,0x90,0xA0,0xC0,0xA0,0x90,0x05,0x05,0x05, + 0x06,0x00,0x00,0x38,0x48,0x48,0x48,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0xD8, + 0xA8,0x88,0x88,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x88,0xF8,0x88,0x88,0x05,0x05, + 0x05,0x06,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x05,0x05,0x05,0x06,0x00,0x00,0xF8, + 0x88,0x88,0x88,0x88,0x05,0x07,0x07,0x06,0x00,0xFE,0xF0,0x88,0x88,0x88,0xF0,0x80, + 0x80,0x05,0x05,0x05,0x06,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x05,0x05,0x05,0x06, + 0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x05,0x07,0x07,0x06,0x00,0xFE,0x88,0x88,0x88, + 0x88,0x78,0x08,0x70,0x05,0x09,0x09,0x06,0x00,0xFE,0x20,0x20,0x70,0xA8,0xA8,0xA8, + 0x70,0x20,0x20,0x05,0x05,0x05,0x06,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x05,0x07, + 0x07,0x06,0x00,0xFE,0x90,0x90,0x90,0x90,0xF8,0x08,0x08,0x05,0x05,0x05,0x06,0x00, + 0x00,0x88,0x88,0x78,0x08,0x08,0x05,0x05,0x05,0x06,0x00,0x00,0xA8,0xA8,0xA8,0xA8, + 0xF8,0x05,0x07,0x07,0x06,0x00,0xFE,0xA8,0xA8,0xA8,0xA8,0xF8,0x08,0x08}; +const u8g_fntpgm_uint8_t fontpage_8_204_204[28] U8G_FONT_SECTION("fontpage_8_204_204") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x05,0x00,0x00, + 0x00,0x04,0x05,0x05,0x06,0x01,0x00,0x80,0x80,0xE0,0x90,0xE0}; +const u8g_fntpgm_uint8_t fontpage_8_206_207[39] U8G_FONT_SECTION("fontpage_8_206_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCE,0xCF,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x90,0xA8,0xE8,0xA8,0x90,0x04,0x05,0x05,0x06, + 0x01,0x00,0x70,0x90,0x70,0x50,0x90}; +const u8g_fntpgm_uint8_t fontpage_8_212_212[28] U8G_FONT_SECTION("fontpage_8_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x05,0x00,0x00, + 0x00,0x04,0x05,0x05,0x06,0x01,0x00,0x70,0x80,0xE0,0x80,0x70}; +const u8g_fntpgm_uint8_t fontpage_8_214_215[41] U8G_FONT_SECTION("fontpage_8_214_215") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD6,0xD7,0x00,0x06,0x00,0x00, + 0x00,0x03,0x06,0x06,0x06,0x01,0x00,0x40,0x00,0xC0,0x40,0x40,0xE0,0x03,0x06,0x06, + 0x06,0x01,0x00,0xA0,0x00,0xC0,0x40,0x40,0xE0}; + +static const uxg_fontinfo_t g_fontinfo_uk[] PROGMEM = { + FONTDATA_ITEM(8, 134, 134, fontpage_8_134_134), // 'І' -- 'І' + FONTDATA_ITEM(8, 144, 169, fontpage_8_144_169), // 'А' -- 'Щ' + FONTDATA_ITEM(8, 172, 172, fontpage_8_172_172), // 'Ь' -- 'Ь' + FONTDATA_ITEM(8, 175, 201, fontpage_8_175_201), // 'Я' -- 'щ' + FONTDATA_ITEM(8, 204, 204, fontpage_8_204_204), // 'ь' -- 'ь' + FONTDATA_ITEM(8, 206, 207, fontpage_8_206_207), // 'ю' -- 'я' + FONTDATA_ITEM(8, 212, 212, fontpage_8_212_212), // 'є' -- 'є' + FONTDATA_ITEM(8, 214, 215, fontpage_8_214_215), // 'і' -- 'ї' +}; diff --git a/src/lcd/dogm/fontdata/langdata_vi.h b/src/lcd/dogm/fontdata/langdata_vi.h new file mode 100644 index 0000000..303c4c6 --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_vi.h @@ -0,0 +1,228 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_2_131_131[31] U8G_FONT_SECTION("fontpage_2_131_131") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x83,0x83,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x88,0x70,0x00,0x70,0x08,0x78,0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_2_144_145[44] U8G_FONT_SECTION("fontpage_2_144_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0x91,0x00,0x08,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0xF0,0x48,0x48,0xE8,0x48,0x48,0xF0,0x06,0x08, + 0x08,0x06,0x00,0x00,0x08,0x1C,0x08,0x78,0x88,0x88,0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_2_169_169[31] U8G_FONT_SECTION("fontpage_2_169_169") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA9,0xA9,0x00,0x08,0x00,0x00, + 0x00,0x04,0x08,0x08,0x06,0x00,0x00,0x50,0xA0,0x00,0x60,0x20,0x20,0x20,0x70}; +const u8g_fntpgm_uint8_t fontpage_3_161_161[30] U8G_FONT_SECTION("fontpage_3_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x07,0x00,0x00, + 0x00,0x05,0x07,0x07,0x06,0x00,0x00,0x08,0x08,0x70,0x88,0x88,0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_3_175_176[43] U8G_FONT_SECTION("fontpage_3_175_176") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xB0,0x00,0x08,0x00,0x00, + 0x00,0x05,0x08,0x08,0x06,0x00,0x00,0x08,0x98,0x90,0x90,0x90,0x90,0x90,0x60,0x05, + 0x06,0x06,0x06,0x00,0x00,0x08,0x98,0x90,0x90,0xB0,0x50}; +const u8g_fntpgm_uint8_t fontpage_6_131_131[25] U8G_FONT_SECTION("fontpage_6_131_131") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x83,0x83,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x02,0x02,0x06,0x00,0x08,0x68,0xB0}; +const u8g_fntpgm_uint8_t fontpage_6_137_137[26] U8G_FONT_SECTION("fontpage_6_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0x00,0x00, + 0x00,0x03,0x03,0x03,0x06,0x01,0x07,0xC0,0x20,0x40}; +const u8g_fntpgm_uint8_t fontpage_6_163_163[24] U8G_FONT_SECTION("fontpage_6_163_163") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA3,0xA3,0x00,0x00,0xFE,0x00, + 0x00,0x01,0x01,0x01,0x06,0x02,0xFE,0x80}; +const u8g_fntpgm_uint8_t fontpage_6_192_193[33] U8G_FONT_SECTION("fontpage_6_192_193") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC1,0x00,0x0A,0x00,0x00, + 0x00,0x02,0x02,0x02,0x06,0x01,0x08,0x80,0x40,0x02,0x02,0x02,0x06,0x02,0x08,0x40, + 0x80}; +const u8g_fntpgm_uint8_t fontpage_61_161_161[30] U8G_FONT_SECTION("fontpage_61_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x05,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x07,0x00,0xFE,0x70,0x08,0x78,0x88,0x78,0x00,0x20}; +const u8g_fntpgm_uint8_t fontpage_61_163_163[32] U8G_FONT_SECTION("fontpage_61_163_163") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA3,0xA3,0x00,0x09,0x00,0x00, + 0x00,0x05,0x09,0x09,0x07,0x00,0x00,0x30,0x10,0x20,0x00,0x70,0x08,0x78,0x88,0x78 + }; +const u8g_fntpgm_uint8_t fontpage_61_165_165[33] U8G_FONT_SECTION("fontpage_61_165_165") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x0A,0x00,0x00, + 0x00,0x06,0x0A,0x0A,0x07,0x00,0x00,0x04,0x08,0x30,0x48,0x00,0x70,0x08,0x78,0x88, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_61_167_167[33] U8G_FONT_SECTION("fontpage_61_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x10,0x08,0x30,0x48,0x00,0x70,0x08,0x78,0x88, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_61_169_169[34] U8G_FONT_SECTION("fontpage_61_169_169") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA9,0xA9,0x00,0x0B,0x00,0x00, + 0x00,0x06,0x0B,0x0B,0x07,0x00,0x00,0x0C,0x04,0x08,0x30,0x48,0x00,0x70,0x08,0x78, + 0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_61_173_173[33] U8G_FONT_SECTION("fontpage_61_173_173") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAD,0xAD,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0xFE,0x30,0x48,0x00,0x70,0x08,0x78,0x88,0x78,0x00, + 0x20}; +const u8g_fntpgm_uint8_t fontpage_61_175_175[33] U8G_FONT_SECTION("fontpage_61_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x08,0x10,0x48,0x30,0x00,0x70,0x08,0x78,0x88, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_61_177_177[33] U8G_FONT_SECTION("fontpage_61_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x40,0x20,0x48,0x30,0x00,0x70,0x08,0x78,0x88, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_61_179_179[34] U8G_FONT_SECTION("fontpage_61_179_179") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB3,0xB3,0x00,0x0B,0x00,0x00, + 0x00,0x05,0x0B,0x0B,0x07,0x00,0x00,0x18,0x08,0x10,0x48,0x30,0x00,0x70,0x08,0x78, + 0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_61_181_181[34] U8G_FONT_SECTION("fontpage_61_181_181") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB5,0xB5,0x00,0x0B,0x00,0x00, + 0x00,0x06,0x0B,0x0B,0x07,0x00,0x00,0x14,0x28,0x00,0x48,0x30,0x00,0x70,0x08,0x78, + 0x88,0x78}; +const u8g_fntpgm_uint8_t fontpage_61_183_183[33] U8G_FONT_SECTION("fontpage_61_183_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xB7,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0xFE,0x48,0x30,0x00,0x70,0x08,0x78,0x88,0x78,0x00, + 0x20}; +const u8g_fntpgm_uint8_t fontpage_61_191_191[33] U8G_FONT_SECTION("fontpage_61_191_191") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x00,0x0A,0x00,0x00, + 0x00,0x06,0x0A,0x0A,0x07,0x00,0x00,0x04,0x08,0x20,0x50,0x00,0x70,0x88,0xF0,0x80, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_61_193_193[33] U8G_FONT_SECTION("fontpage_61_193_193") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC1,0xC1,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x10,0x08,0x20,0x50,0x00,0x70,0x88,0xF0,0x80, + 0x78}; +const u8g_fntpgm_uint8_t fontpage_61_195_195[34] U8G_FONT_SECTION("fontpage_61_195_195") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC3,0xC3,0x00,0x0B,0x00,0x00, + 0x00,0x05,0x0B,0x0B,0x07,0x00,0x00,0x18,0x08,0x10,0x60,0x90,0x00,0x60,0x90,0xF0, + 0x80,0x70}; +const u8g_fntpgm_uint8_t fontpage_61_199_199[33] U8G_FONT_SECTION("fontpage_61_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0xFE,0x20,0x50,0x00,0x70,0x88,0xF0,0x80,0x78,0x00, + 0x20}; +const u8g_fntpgm_uint8_t fontpage_61_201_201[32] U8G_FONT_SECTION("fontpage_61_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x09,0x00,0x00, + 0x00,0x03,0x09,0x09,0x07,0x02,0x00,0x60,0x20,0x40,0x00,0xC0,0x40,0x40,0x40,0xE0 + }; +const u8g_fntpgm_uint8_t fontpage_61_203_203[32] U8G_FONT_SECTION("fontpage_61_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x07,0xFE,0x00, + 0x00,0x03,0x09,0x09,0x07,0x02,0xFE,0x40,0x00,0xC0,0x40,0x40,0x40,0xE0,0x00,0x40 + }; +const u8g_fntpgm_uint8_t fontpage_61_205_205[30] U8G_FONT_SECTION("fontpage_61_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x05,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x07,0x00,0xFE,0x70,0x88,0x88,0x88,0x70,0x00,0x20}; +const u8g_fntpgm_uint8_t fontpage_61_207_207[32] U8G_FONT_SECTION("fontpage_61_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x09,0x00,0x00, + 0x00,0x05,0x09,0x09,0x07,0x00,0x00,0x30,0x10,0x20,0x00,0x70,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_209_209[33] U8G_FONT_SECTION("fontpage_61_209_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x0A,0x00,0x00, + 0x00,0x06,0x0A,0x0A,0x07,0x00,0x00,0x04,0x08,0x20,0x50,0x00,0x70,0x88,0x88,0x88, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_61_211_211[33] U8G_FONT_SECTION("fontpage_61_211_211") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD3,0xD3,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x10,0x08,0x20,0x50,0x00,0x70,0x88,0x88,0x88, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_61_213_213[33] U8G_FONT_SECTION("fontpage_61_213_213") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD5,0xD5,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x18,0x08,0x30,0x50,0x00,0x70,0x88,0x88,0x88, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_61_215_215[34] U8G_FONT_SECTION("fontpage_61_215_215") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD7,0xD7,0x00,0x0B,0x00,0x00, + 0x00,0x05,0x0B,0x0B,0x07,0x00,0x00,0x28,0x50,0x00,0x20,0x50,0x00,0x70,0x88,0x88, + 0x88,0x70}; +const u8g_fntpgm_uint8_t fontpage_61_217_217[33] U8G_FONT_SECTION("fontpage_61_217_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x08,0xFE,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0xFE,0x20,0x50,0x00,0x70,0x88,0x88,0x88,0x70,0x00, + 0x20}; +const u8g_fntpgm_uint8_t fontpage_61_219_219[32] U8G_FONT_SECTION("fontpage_61_219_219") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDB,0xDB,0x00,0x09,0x00,0x00, + 0x00,0x05,0x09,0x09,0x07,0x00,0x00,0x20,0x40,0x10,0x08,0x70,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_221_221[32] U8G_FONT_SECTION("fontpage_61_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x09,0x00,0x00, + 0x00,0x05,0x09,0x09,0x07,0x00,0x00,0x80,0x40,0x10,0x08,0x70,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_223_223[33] U8G_FONT_SECTION("fontpage_61_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x60,0x20,0x40,0x10,0x08,0x70,0x88,0x88,0x88, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_61_225_225[32] U8G_FONT_SECTION("fontpage_61_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x09,0x00,0x00, + 0x00,0x05,0x09,0x09,0x07,0x00,0x00,0x50,0xA0,0x10,0x08,0x70,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_227_227[32] U8G_FONT_SECTION("fontpage_61_227_227") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE3,0xE3,0x00,0x07,0xFE,0x00, + 0x00,0x05,0x09,0x09,0x00,0x00,0xFE,0x10,0x08,0x70,0x88,0x88,0x88,0x70,0x00,0x20 + }; +const u8g_fntpgm_uint8_t fontpage_61_229_229[30] U8G_FONT_SECTION("fontpage_61_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x05,0xFE,0x00, + 0x00,0x05,0x07,0x07,0x07,0x00,0xFE,0x88,0x88,0x88,0x88,0x70,0x00,0x20}; +const u8g_fntpgm_uint8_t fontpage_61_231_231[33] U8G_FONT_SECTION("fontpage_61_231_231") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE7,0xE7,0x00,0x0A,0x00,0x00, + 0x00,0x05,0x0A,0x0A,0x07,0x00,0x00,0x30,0x10,0x20,0x00,0x00,0x88,0x88,0x88,0x88, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_61_233_233[32] U8G_FONT_SECTION("fontpage_61_233_233") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE9,0xE9,0x00,0x09,0x00,0x00, + 0x00,0x06,0x09,0x09,0x07,0x00,0x00,0x10,0x20,0x0C,0x04,0x88,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_235_235[32] U8G_FONT_SECTION("fontpage_61_235_235") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEB,0xEB,0x00,0x09,0x00,0x00, + 0x00,0x06,0x09,0x09,0x07,0x00,0x00,0x40,0x20,0x0C,0x04,0x88,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_237_237[33] U8G_FONT_SECTION("fontpage_61_237_237") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xED,0xED,0x00,0x0A,0x00,0x00, + 0x00,0x06,0x0A,0x0A,0x07,0x00,0x00,0x30,0x10,0x20,0x0C,0x04,0x88,0x88,0x88,0x88, + 0x70}; +const u8g_fntpgm_uint8_t fontpage_61_239_239[32] U8G_FONT_SECTION("fontpage_61_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x09,0x00,0x00, + 0x00,0x06,0x09,0x09,0x07,0x00,0x00,0x28,0x50,0x0C,0x04,0x88,0x88,0x88,0x88,0x70 + }; +const u8g_fntpgm_uint8_t fontpage_61_241_241[32] U8G_FONT_SECTION("fontpage_61_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x07,0xFE,0x00, + 0x00,0x06,0x09,0x09,0x07,0x00,0xFE,0x0C,0x04,0x88,0x88,0x88,0x88,0x70,0x00,0x20 + }; + +static const uxg_fontinfo_t g_fontinfo_vi[] PROGMEM = { + FONTDATA_ITEM(2, 131, 131, fontpage_2_131_131), // 'ă' -- 'ă' + FONTDATA_ITEM(2, 144, 145, fontpage_2_144_145), // 'Đ' -- 'đ' + FONTDATA_ITEM(2, 169, 169, fontpage_2_169_169), // 'ĩ' -- 'ĩ' + FONTDATA_ITEM(3, 161, 161, fontpage_3_161_161), // 'ơ' -- 'ơ' + FONTDATA_ITEM(3, 175, 176, fontpage_3_175_176), // 'Ư' -- 'ư' + FONTDATA_ITEM(6, 131, 131, fontpage_6_131_131), // '̃' -- '̃' + FONTDATA_ITEM(6, 137, 137, fontpage_6_137_137), // '̉' -- '̉' + FONTDATA_ITEM(6, 163, 163, fontpage_6_163_163), // '̣' -- '̣' + FONTDATA_ITEM(6, 192, 193, fontpage_6_192_193), // '̀' -- '́' + FONTDATA_ITEM(61, 161, 161, fontpage_61_161_161), // 'ạ' -- 'ạ' + FONTDATA_ITEM(61, 163, 163, fontpage_61_163_163), // 'ả' -- 'ả' + FONTDATA_ITEM(61, 165, 165, fontpage_61_165_165), // 'ấ' -- 'ấ' + FONTDATA_ITEM(61, 167, 167, fontpage_61_167_167), // 'ầ' -- 'ầ' + FONTDATA_ITEM(61, 169, 169, fontpage_61_169_169), // 'ẩ' -- 'ẩ' + FONTDATA_ITEM(61, 173, 173, fontpage_61_173_173), // 'ậ' -- 'ậ' + FONTDATA_ITEM(61, 175, 175, fontpage_61_175_175), // 'ắ' -- 'ắ' + FONTDATA_ITEM(61, 177, 177, fontpage_61_177_177), // 'ằ' -- 'ằ' + FONTDATA_ITEM(61, 179, 179, fontpage_61_179_179), // 'ẳ' -- 'ẳ' + FONTDATA_ITEM(61, 181, 181, fontpage_61_181_181), // 'ẵ' -- 'ẵ' + FONTDATA_ITEM(61, 183, 183, fontpage_61_183_183), // 'ặ' -- 'ặ' + FONTDATA_ITEM(61, 191, 191, fontpage_61_191_191), // 'ế' -- 'ế' + FONTDATA_ITEM(61, 193, 193, fontpage_61_193_193), // 'ề' -- 'ề' + FONTDATA_ITEM(61, 195, 195, fontpage_61_195_195), // 'ể' -- 'ể' + FONTDATA_ITEM(61, 199, 199, fontpage_61_199_199), // 'ệ' -- 'ệ' + FONTDATA_ITEM(61, 201, 201, fontpage_61_201_201), // 'ỉ' -- 'ỉ' + FONTDATA_ITEM(61, 203, 203, fontpage_61_203_203), // 'ị' -- 'ị' + FONTDATA_ITEM(61, 205, 205, fontpage_61_205_205), // 'ọ' -- 'ọ' + FONTDATA_ITEM(61, 207, 207, fontpage_61_207_207), // 'ỏ' -- 'ỏ' + FONTDATA_ITEM(61, 209, 209, fontpage_61_209_209), // 'ố' -- 'ố' + FONTDATA_ITEM(61, 211, 211, fontpage_61_211_211), // 'ồ' -- 'ồ' + FONTDATA_ITEM(61, 213, 213, fontpage_61_213_213), // 'ổ' -- 'ổ' + FONTDATA_ITEM(61, 215, 215, fontpage_61_215_215), // 'ỗ' -- 'ỗ' + FONTDATA_ITEM(61, 217, 217, fontpage_61_217_217), // 'ộ' -- 'ộ' + FONTDATA_ITEM(61, 219, 219, fontpage_61_219_219), // 'ớ' -- 'ớ' + FONTDATA_ITEM(61, 221, 221, fontpage_61_221_221), // 'ờ' -- 'ờ' + FONTDATA_ITEM(61, 223, 223, fontpage_61_223_223), // 'ở' -- 'ở' + FONTDATA_ITEM(61, 225, 225, fontpage_61_225_225), // 'ỡ' -- 'ỡ' + FONTDATA_ITEM(61, 227, 227, fontpage_61_227_227), // 'ợ' -- 'ợ' + FONTDATA_ITEM(61, 229, 229, fontpage_61_229_229), // 'ụ' -- 'ụ' + FONTDATA_ITEM(61, 231, 231, fontpage_61_231_231), // 'ủ' -- 'ủ' + FONTDATA_ITEM(61, 233, 233, fontpage_61_233_233), // 'ứ' -- 'ứ' + FONTDATA_ITEM(61, 235, 235, fontpage_61_235_235), // 'ừ' -- 'ừ' + FONTDATA_ITEM(61, 237, 237, fontpage_61_237_237), // 'ử' -- 'ử' + FONTDATA_ITEM(61, 239, 239, fontpage_61_239_239), // 'ữ' -- 'ữ' + FONTDATA_ITEM(61, 241, 241, fontpage_61_241_241), // 'ự' -- 'ự' +}; diff --git a/src/lcd/dogm/fontdata/langdata_zh_CN.h b/src/lcd/dogm/fontdata/langdata_zh_CN.h new file mode 100644 index 0000000..664fa5f --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_zh_CN.h @@ -0,0 +1,1824 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_64_157_157[26] U8G_FONT_SECTION("fontpage_64_157_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9D,0x9D,0x00,0x07,0x00,0x00, + 0x00,0x05,0x03,0x03,0x06,0x00,0x04,0xD8,0x48,0x90}; +const u8g_fntpgm_uint8_t fontpage_69_191_191[28] U8G_FONT_SECTION("fontpage_69_191_191") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x08,0x18,0x28,0x48,0xF8}; +const u8g_fntpgm_uint8_t fontpage_156_128_128[27] U8G_FONT_SECTION("fontpage_156_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x06,0x00,0x00, + 0x00,0x0B,0x02,0x04,0x0C,0x00,0x04,0x00,0x40,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_156_137_139[97] U8G_FONT_SECTION("fontpage_156_137_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x3F, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xE0,0x0B,0x0B,0x16,0x0C,0x00, + 0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x07,0xC0,0x04,0x00,0x04,0x00,0x04, + 0x00,0x04,0x00,0x04,0x00,0xFF,0xE0,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0xFF,0xE0,0x04, + 0x00,0x04,0x00,0x06,0x00,0x05,0x00,0x04,0x80,0x04,0x80,0x04,0x00,0x04,0x00,0x04, + 0x00}; +const u8g_fntpgm_uint8_t fontpage_156_141_141[45] U8G_FONT_SECTION("fontpage_156_141_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x02,0x00,0x02,0x00,0x04,0x00,0x0D, + 0x00,0x14,0x80,0x24,0x40,0x44,0x20,0x84,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_156_147_147[45] U8G_FONT_SECTION("fontpage_156_147_147") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x93,0x93,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x3F,0xC0,0x04,0x00,0x04,0x00,0xFF, + 0xE0,0x08,0x00,0x1F,0xC0,0x00,0x80,0x0D,0x00,0x02,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_156_157_157[45] U8G_FONT_SECTION("fontpage_156_157_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9D,0x9D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x29,0x40,0x4A,0x40,0xF7, + 0x80,0x10,0x80,0x21,0x00,0x42,0x00,0xF7,0xC0,0x00,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_156_170_170[45] U8G_FONT_SECTION("fontpage_156_170_170") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAA,0xAA,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x49, + 0x00,0x88,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_156_173_173[45] U8G_FONT_SECTION("fontpage_156_173_173") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAD,0xAD,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0xFF,0x80,0x88,0x80,0x88, + 0x80,0x88,0x80,0xFF,0x80,0x88,0x80,0x08,0x00,0x08,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_156_186_187[73] U8G_FONT_SECTION("fontpage_156_186_187") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBA,0xBB,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x48,0x00,0x28,0x00,0x08,0x00,0xFF,0x80,0x08, + 0x80,0x0C,0x80,0x12,0x80,0x12,0x80,0x20,0x80,0x44,0x80,0x83,0x00,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x08,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x7F, + 0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_156_201_201[45] U8G_FONT_SECTION("fontpage_156_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x80,0x24,0x80,0x24,0x80,0x21,0x00,0x11, + 0x00,0x12,0x00,0x0A,0x00,0x04,0x00,0x0A,0x00,0x31,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_156_203_203[45] U8G_FONT_SECTION("fontpage_156_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x04,0x00,0x7F,0xC0,0x00,0x80,0x01, + 0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x30,0x00,0x48,0x00,0x87,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_134_134[45] U8G_FONT_SECTION("fontpage_157_134_134") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x86,0x86,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0x80,0x01,0x00,0x02,0x00,0x0C,0x00,0x08, + 0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x28,0x00,0x10,0x00}; +const u8g_fntpgm_uint8_t fontpage_157_140_140[39] U8G_FONT_SECTION("fontpage_157_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x08,0x00,0x00, + 0x00,0x0B,0x08,0x10,0x0C,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_142_142[45] U8G_FONT_SECTION("fontpage_157_142_142") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8E,0x8E,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0xFF, + 0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x1C,0x00}; +const u8g_fntpgm_uint8_t fontpage_157_164_164[45] U8G_FONT_SECTION("fontpage_157_164_164") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x00,0x00,0x11,0x00,0x20, + 0x80,0x51,0x40,0x11,0x00,0x0A,0x00,0x04,0x00,0x1B,0x00,0x60,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_174_174[45] U8G_FONT_SECTION("fontpage_157_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x11,0x00,0x1F,0x00,0x00, + 0x00,0xFF,0xE0,0x80,0x20,0x1F,0x00,0x11,0x00,0x21,0x20,0xC0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_206_206[45] U8G_FONT_SECTION("fontpage_157_206_206") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCE,0xCE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11, + 0x00,0x11,0x00,0x2A,0x80,0x2A,0x80,0x44,0x40,0x88,0x40,0x10,0x20}; +const u8g_fntpgm_uint8_t fontpage_157_228_229[73] U8G_FONT_SECTION("fontpage_157_228_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE4,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x24, + 0x80,0xC2,0x60,0x3F,0x80,0x01,0x00,0x0A,0x00,0x04,0x00,0x02,0x00,0x0A,0x0B,0x16, + 0x0C,0x01,0xFF,0x01,0x00,0x81,0x00,0x91,0x00,0x89,0x00,0x89,0x00,0x81,0x00,0x91, + 0x00,0xA1,0x00,0xC2,0x80,0x84,0x40,0x18,0x40}; +const u8g_fntpgm_uint8_t fontpage_157_246_246[45] U8G_FONT_SECTION("fontpage_157_246_246") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF6,0xF6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x15,0x00,0x25,0x00,0x2F,0xC0,0x71, + 0x00,0xA1,0x00,0x2F,0xE0,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_157_253_253[45] U8G_FONT_SECTION("fontpage_157_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x80,0x12,0x80,0x22,0x40,0x24,0x40,0x68, + 0x20,0xA7,0xC0,0x22,0x40,0x22,0x40,0x22,0x40,0x24,0x40,0x28,0xC0}; +const u8g_fntpgm_uint8_t fontpage_158_145_145[45] U8G_FONT_SECTION("fontpage_158_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x21,0x00,0x3F,0xE0,0x61, + 0x00,0xA3,0x80,0x23,0x80,0x25,0x40,0x29,0x20,0x31,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_158_160_160[45] U8G_FONT_SECTION("fontpage_158_160_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x27,0xE0,0x21,0x00,0x6F, + 0xE0,0xA2,0x00,0x27,0xE0,0x20,0x40,0x22,0x80,0x21,0x00,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_158_205_206[73] U8G_FONT_SECTION("fontpage_158_205_206") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x11,0x00,0x20,0x00,0x2F,0xE0,0x60, + 0x00,0xA4,0x40,0x22,0x40,0x22,0x80,0x20,0x80,0x21,0x00,0x2F,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x10,0xC0,0x1F,0x00,0x29,0x00,0x29,0x00,0x69,0x00,0xAF,0xE0,0x29, + 0x00,0x29,0x20,0x2A,0xA0,0x2D,0x60,0x28,0xA0}; +const u8g_fntpgm_uint8_t fontpage_158_211_211[45] U8G_FONT_SECTION("fontpage_158_211_211") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD3,0xD3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x22,0x00,0x5F,0xC0,0x42,0x00,0xC7, + 0x00,0x4A,0x80,0x52,0x40,0x62,0x20,0x4F,0x80,0x42,0x00,0x42,0x00}; +const u8g_fntpgm_uint8_t fontpage_158_217_217[45] U8G_FONT_SECTION("fontpage_158_217_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xDF, + 0x60,0x04,0x00,0x7F,0xC0,0x04,0x00,0x15,0x00,0x24,0x80,0x4C,0x40}; +const u8g_fntpgm_uint8_t fontpage_158_220_220[45] U8G_FONT_SECTION("fontpage_158_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x14,0x00,0x14,0x00,0x27,0xE0,0x2A,0x00,0x72, + 0x00,0xA3,0xC0,0x22,0x00,0x22,0x00,0x23,0xE0,0x22,0x00,0x22,0x00}; +const u8g_fntpgm_uint8_t fontpage_158_255_255[45] U8G_FONT_SECTION("fontpage_158_255_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x1F,0xE0,0x21,0x00,0x2F,0xE0,0x69, + 0x20,0xAF,0xE0,0x29,0x00,0x25,0x00,0x22,0x00,0x25,0x80,0x38,0x60}; +const u8g_fntpgm_uint8_t fontpage_159_155_155[45] U8G_FONT_SECTION("fontpage_159_155_155") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9B,0x9B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x14,0x80,0x14,0x80,0x24,0x80,0x2F,0xE0,0x64, + 0x80,0xA4,0x80,0x3F,0xE0,0x20,0x00,0x24,0x80,0x28,0x40,0x30,0x20}; +const u8g_fntpgm_uint8_t fontpage_159_181_181[45] U8G_FONT_SECTION("fontpage_159_181_181") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB5,0xB5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xC0,0x20,0x40,0x4F,0xC0,0x40,0x40,0xDF, + 0xE0,0x50,0x20,0x4F,0xC0,0x44,0x80,0x43,0x00,0x44,0x80,0x58,0x60}; +const u8g_fntpgm_uint8_t fontpage_159_221_221[45] U8G_FONT_SECTION("fontpage_159_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x17,0xC0,0x14,0x40,0x24,0x40,0x27,0xC0,0x61, + 0x00,0xAF,0xE0,0x21,0x00,0x23,0x80,0x25,0x40,0x29,0x20,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_159_225_225[45] U8G_FONT_SECTION("fontpage_159_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x11,0x00,0x2F,0xE0,0x20,0x00,0x67, + 0xC0,0xA0,0x00,0x27,0xC0,0x20,0x00,0x27,0xC0,0x24,0x40,0x27,0xC0}; +const u8g_fntpgm_uint8_t fontpage_160_188_188[45] U8G_FONT_SECTION("fontpage_160_188_188") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x1F,0xE0,0x22,0x00,0x27,0xC0,0x64, + 0x40,0xA7,0xC0,0x24,0x40,0x27,0x40,0x25,0xC0,0x24,0x40,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_160_190_190[45] U8G_FONT_SECTION("fontpage_160_190_190") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBE,0xBE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x13,0xE0,0x19,0x00,0x2B,0xE0,0x2E,0x20,0x6A, + 0xA0,0xAA,0xA0,0x2A,0xA0,0x2E,0xA0,0x2A,0xA0,0x21,0x40,0x26,0x20}; +const u8g_fntpgm_uint8_t fontpage_160_207_207[45] U8G_FONT_SECTION("fontpage_160_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x28,0x20,0x2F,0xE0,0x68, + 0x00,0xAF,0xE0,0x2A,0xA0,0x2F,0xE0,0x2A,0xA0,0x3A,0xA0,0x28,0x60}; +const u8g_fntpgm_uint8_t fontpage_160_220_220[45] U8G_FONT_SECTION("fontpage_160_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x3F,0xE0,0x20,0x00,0x4F,0xC0,0x48, + 0x40,0xDF,0xE0,0x50,0x20,0x4F,0xC0,0x41,0x00,0x41,0x00,0x47,0x00}; +const u8g_fntpgm_uint8_t fontpage_161_168_168[45] U8G_FONT_SECTION("fontpage_161_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x61,0x20,0x57,0xC0,0x41,0x40,0x77,0xE0,0xD1, + 0x00,0x53,0xC0,0x56,0x40,0x53,0xC0,0x5A,0x40,0x52,0x40,0x43,0xC0}; +const u8g_fntpgm_uint8_t fontpage_161_207_207[45] U8G_FONT_SECTION("fontpage_161_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x13,0xC0,0x14,0x80,0x2F,0xE0,0x35,0x20,0x67, + 0xE0,0xA2,0x20,0x2D,0x40,0x22,0x80,0x2D,0xC0,0x22,0xA0,0x2D,0x80}; +const u8g_fntpgm_uint8_t fontpage_162_197_197[45] U8G_FONT_SECTION("fontpage_162_197_197") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC5,0xC5,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x04,0x00,0xFF,0xC0,0x08,0x00,0x11,0x00,0x7F, + 0x80,0x12,0x80,0x12,0x00,0x12,0x00,0x22,0x40,0x22,0x40,0xC1,0xC0}; +const u8g_fntpgm_uint8_t fontpage_162_200_201[73] U8G_FONT_SECTION("fontpage_162_200_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC8,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x24,0x00,0x3F,0xC0,0x44,0x00,0x84, + 0x00,0xFF,0xE0,0x12,0x00,0x12,0x00,0x12,0x20,0x22,0x20,0xC1,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x04,0x00,0x44,0x40,0x24,0x80,0x04,0x00,0xFF,0xE0,0x12,0x00,0x12, + 0x00,0x12,0x20,0x12,0x20,0x22,0x20,0xC1,0xE0}; +const u8g_fntpgm_uint8_t fontpage_162_229_229[45] U8G_FONT_SECTION("fontpage_162_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x18,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0A, + 0x00,0x0A,0x00,0x11,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x80,0x20}; +const u8g_fntpgm_uint8_t fontpage_162_232_232[45] U8G_FONT_SECTION("fontpage_162_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xDF, + 0x60,0x04,0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_162_241_241[45] U8G_FONT_SECTION("fontpage_162_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x7F,0xC0,0x11,0x00,0x11, + 0x00,0x11,0x00,0xFF,0xE0,0x00,0x00,0x11,0x00,0x20,0x80,0x40,0x40}; +const u8g_fntpgm_uint8_t fontpage_162_243_243[45] U8G_FONT_SECTION("fontpage_162_243_243") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF3,0xF3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x11,0x00,0x7F,0xC0,0x04,0x00,0x04, + 0x00,0xFF,0xC0,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_162_247_247[45] U8G_FONT_SECTION("fontpage_162_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x3F, + 0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF,0xE0,0x11,0x00,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_163_151_151[43] U8G_FONT_SECTION("fontpage_163_151_151") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x97,0x97,0x00,0x09,0xFF,0x00, + 0x00,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0x7F,0xE0,0x40,0x20,0x9F,0x40,0x11,0x00,0x11, + 0x00,0x11,0x00,0x11,0x00,0x21,0x20,0x41,0x20,0x80,0xE0}; +const u8g_fntpgm_uint8_t fontpage_163_183_183[45] U8G_FONT_SECTION("fontpage_163_183_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x82,0x00,0x42,0x00,0x05,0x00,0x28,0x80,0x32, + 0x60,0x41,0x00,0x4F,0xC0,0x80,0x80,0x87,0x00,0x81,0x00,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_163_198_198[45] U8G_FONT_SECTION("fontpage_163_198_198") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0A,0x00,0x89,0x00,0x4F,0xE0,0x59,0x00,0x09, + 0x00,0x2F,0xC0,0x29,0x00,0xCF,0xC0,0x49,0x00,0x49,0x00,0x4F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_163_250_251[73] U8G_FONT_SECTION("fontpage_163_250_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFA,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x44,0x40,0x44,0x40,0x44,0x40,0x7F, + 0xC0,0x04,0x00,0x84,0x20,0x84,0x20,0x84,0x20,0x84,0x20,0xFF,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04, + 0x00,0x44,0x40,0x44,0x40,0x44,0x40,0x7F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_164_134_135[73] U8G_FONT_SECTION("fontpage_164_134_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x86,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x20,0x80,0x20,0x80,0x40, + 0x40,0xBF,0xA0,0x08,0x80,0x08,0x80,0x10,0x80,0x20,0x80,0xC3,0x00,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x20,0x00,0x27,0xE0,0x21,0x20,0x39,0x20,0xE1,0x20,0x21,0x20,0x29, + 0x20,0x32,0x20,0x22,0x20,0x04,0x20,0x08,0xC0}; +const u8g_fntpgm_uint8_t fontpage_164_155_155[45] U8G_FONT_SECTION("fontpage_164_155_155") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9B,0x9B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x20,0x18,0x20,0x24,0xA0,0x42,0xA0,0xBC, + 0xA0,0x24,0xA0,0x24,0xA0,0x38,0xA0,0x22,0x20,0x22,0x20,0x1E,0x60}; +const u8g_fntpgm_uint8_t fontpage_164_157_157[45] U8G_FONT_SECTION("fontpage_164_157_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9D,0x9D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0x27,0xE0,0xF9,0x20,0x11,0x20,0x21, + 0x20,0x69,0x20,0xB1,0x20,0x29,0x20,0x22,0x20,0x24,0x20,0x28,0xC0}; +const u8g_fntpgm_uint8_t fontpage_164_171_171[45] U8G_FONT_SECTION("fontpage_164_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7C,0x20,0x44,0x20,0x44,0xA0,0x7C,0xA0,0x10, + 0xA0,0xFE,0xA0,0x12,0xA0,0x22,0xA0,0x22,0x20,0x42,0x20,0x8C,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_176_176[45] U8G_FONT_SECTION("fontpage_164_176_176") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFE,0x20,0x10,0x20,0x20,0xA0,0x44,0xA0,0xFE, + 0xA0,0x10,0xA0,0x7C,0xA0,0x10,0xA0,0x10,0x20,0x1E,0x20,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_182_183[73] U8G_FONT_SECTION("fontpage_164_182_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB6,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x20,0x50,0xA0,0x7E,0xA0,0x90,0xA0,0xFE, + 0xA0,0x10,0xA0,0x7E,0xA0,0x52,0xA0,0x52,0x20,0x56,0x20,0x10,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x7E,0x20,0x42,0x20,0x7E,0xA0,0x48,0xA0,0x48,0xA0,0x7E,0xA0,0x6A, + 0xA0,0xAA,0xA0,0xAA,0xA0,0x2E,0x20,0x08,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_242_242[45] U8G_FONT_SECTION("fontpage_164_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x20,0xFE,0x20,0x92,0xA0,0x7C,0xA0,0x10, + 0xA0,0x7C,0xA0,0x10,0xA0,0xFE,0xA0,0x44,0x20,0x44,0x20,0x7C,0xE0}; +const u8g_fntpgm_uint8_t fontpage_165_155_155[45] U8G_FONT_SECTION("fontpage_165_155_155") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9B,0x9B,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0x80,0x08, + 0x80,0x08,0x80,0x10,0x80,0x10,0x80,0x20,0x80,0x40,0x80,0x87,0x00}; +const u8g_fntpgm_uint8_t fontpage_165_159_160[73] U8G_FONT_SECTION("fontpage_165_159_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0x01,0x00,0xF9,0x00,0x27,0xE0,0x21, + 0x20,0x21,0x20,0x21,0x20,0x3A,0x20,0xC2,0x20,0x04,0x20,0x18,0xC0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x20,0x00,0x20,0x00,0xFD,0xE0,0x25,0x20,0x25,0x20,0x25,0x20,0x25, + 0x20,0x25,0x20,0x45,0x20,0x55,0xE0,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_165_168_168[45] U8G_FONT_SECTION("fontpage_165_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0x79,0x00,0x01,0x00,0x03,0xE0,0xFD, + 0x20,0x21,0x20,0x21,0x20,0x49,0x20,0xFA,0x20,0x0A,0x20,0x04,0xC0}; +const u8g_fntpgm_uint8_t fontpage_166_150_150[45] U8G_FONT_SECTION("fontpage_166_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x12,0x00,0x22,0x40,0x22,0x80,0x63, + 0x00,0xA2,0x00,0x26,0x00,0x2A,0x00,0x22,0x20,0x22,0x20,0x21,0xE0}; +const u8g_fntpgm_uint8_t fontpage_166_199_199[45] U8G_FONT_SECTION("fontpage_166_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x0D,0x00,0x71,0x00,0x11,0x00,0x11,0x00,0x11, + 0x00,0xFF,0xC0,0x11,0x00,0x11,0x00,0x21,0x00,0x41,0x00,0x81,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_202_202[45] U8G_FONT_SECTION("fontpage_166_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x44,0x40,0x24,0x80,0x15,0x00,0x7F, + 0xC0,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_207_207[45] U8G_FONT_SECTION("fontpage_166_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x42,0x00,0x4F,0x80,0xE2,0x80,0x42, + 0x80,0x4A,0xC0,0x52,0xA0,0x44,0x80,0x44,0x80,0x4A,0x80,0x51,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_213_213[45] U8G_FONT_SECTION("fontpage_166_213_213") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD5,0xD5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x0A,0x00,0x7F,0xC0,0x44,0x40,0x7F, + 0xC0,0x44,0x40,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_225_225[45] U8G_FONT_SECTION("fontpage_166_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x0F,0x80,0x08,0x00,0x08,0x00,0xFF, + 0xE0,0x08,0x00,0x0A,0x00,0x09,0x00,0x08,0x80,0x08,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_240_241[73] U8G_FONT_SECTION("fontpage_166_240_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x10,0x00,0xE7,0xC0,0x84,0x40,0x84,0x40,0xF4, + 0x40,0x84,0x40,0x84,0x40,0x94,0x40,0xE5,0x80,0x84,0x00,0x04,0x00,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x10,0x00,0x1F,0x80,0x21,0x00,0x7F,0xE0,0x20,0x00,0x2F,0x80,0x28, + 0x80,0x28,0x80,0x2B,0x20,0x48,0x20,0x87,0xE0}; +const u8g_fntpgm_uint8_t fontpage_166_244_244[45] U8G_FONT_SECTION("fontpage_166_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x11,0xE0,0x7D,0x20,0x11,0x20,0x11, + 0x20,0xFF,0x20,0x11,0x20,0x21,0x20,0x4D,0x60,0x75,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_248_248[45] U8G_FONT_SECTION("fontpage_166_248_248") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0x7D,0xE0,0x91,0x20,0x11,0x20,0xFF, + 0x20,0x11,0x20,0x5D,0x20,0x51,0x20,0x51,0xA0,0x5D,0x40,0xE1,0x00}; +const u8g_fntpgm_uint8_t fontpage_167_139_139[45] U8G_FONT_SECTION("fontpage_167_139_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8B,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xE0,0x20,0x00,0x22,0x00,0x22,0x00,0x22, + 0x00,0x3F,0xC0,0x22,0x00,0x22,0x80,0x42,0x40,0x42,0x00,0xBF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_167_159_159[45] U8G_FONT_SECTION("fontpage_167_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xE0,0x22,0x00,0x2F,0xC0,0x28,0x40,0x2F, + 0xC0,0x28,0x40,0x2F,0xC0,0x22,0x00,0x2A,0x80,0x52,0x60,0xA6,0x20}; +const u8g_fntpgm_uint8_t fontpage_167_204_205[71] U8G_FONT_SECTION("fontpage_167_204_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0xFF,0xE0,0x0A,0x40,0x4A,0x40,0x2A,0x40,0x11, + 0x40,0x11,0x40,0x28,0x80,0x45,0x80,0x82,0x40,0x04,0x20,0x0B,0x0B,0x16,0x0C,0x00, + 0xFF,0x01,0xC0,0x3E,0x00,0x20,0x00,0x20,0x00,0x3F,0xC0,0x28,0x80,0x25,0x00,0x22, + 0x00,0x45,0x00,0x48,0x80,0xB0,0x60}; +const u8g_fntpgm_uint8_t fontpage_167_214_214[45] U8G_FONT_SECTION("fontpage_167_214_214") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD6,0xD6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFC,0x00,0x4B,0xE0,0x4A,0x20,0x7A,0x20,0x49, + 0x40,0x79,0x40,0x48,0x80,0x4C,0x80,0xF9,0x40,0x0A,0x40,0x0C,0x20}; +const u8g_fntpgm_uint8_t fontpage_167_216_216[45] U8G_FONT_SECTION("fontpage_167_216_216") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0xFF,0xC0,0x12,0x00,0x52,0x80,0x92, + 0x40,0x00,0x00,0x7F,0x80,0x12,0x00,0x0C,0x00,0x12,0x00,0xE1,0xC0}; +const u8g_fntpgm_uint8_t fontpage_167_240_240[45] U8G_FONT_SECTION("fontpage_167_240_240") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x10,0x00,0x22,0x00,0x41,0x00,0xFF, + 0x80,0x00,0x80,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00}; +const u8g_fntpgm_uint8_t fontpage_168_131_131[45] U8G_FONT_SECTION("fontpage_168_131_131") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x83,0x83,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0xF2,0x00,0x97,0xE0,0x98,0x00,0x97, + 0xC0,0x90,0x80,0x91,0x00,0xF2,0x00,0x94,0x20,0x04,0x20,0x03,0xE0}; +const u8g_fntpgm_uint8_t fontpage_168_136_136[45] U8G_FONT_SECTION("fontpage_168_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xDF, + 0x60,0x00,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x3F,0x80,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_168_141_142[73] U8G_FONT_SECTION("fontpage_168_141_142") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8E,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x1F,0xC0,0x10,0x80,0x29,0x00,0x46, + 0x00,0x04,0x00,0x1F,0xC0,0xF0,0x40,0x10,0x40,0x10,0x40,0x1F,0xC0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x01,0xC0,0x3E,0x00,0x20,0x00,0x3F,0xE0,0x20,0x00,0x20,0x00,0x2F, + 0xC0,0x28,0x40,0x48,0x40,0x4F,0xC0,0x88,0x40}; +const u8g_fntpgm_uint8_t fontpage_168_145_145[45] U8G_FONT_SECTION("fontpage_168_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x10,0x00,0xFF,0xC0,0x80,0x40,0x9E, + 0x40,0x92,0x40,0x92,0x40,0x9E,0x40,0x80,0x40,0x80,0x40,0x81,0xC0}; +const u8g_fntpgm_uint8_t fontpage_168_166_166[45] U8G_FONT_SECTION("fontpage_168_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x04,0x00,0x0D,0x80,0x34,0x40,0xC4, + 0x20,0x04,0x00,0x3F,0xC0,0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40}; +const u8g_fntpgm_uint8_t fontpage_168_175_175[45] U8G_FONT_SECTION("fontpage_168_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x3F,0xC0,0x20,0x40,0x20,0x40,0x3F, + 0xC0,0x20,0x00,0x3F,0xC0,0x30,0x40,0x50,0x40,0x5F,0xC0,0x90,0x40}; +const u8g_fntpgm_uint8_t fontpage_168_202_202[45] U8G_FONT_SECTION("fontpage_168_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x00,0x24,0x00,0x3F,0xC0,0x44,0x00,0x04, + 0x00,0xFF,0xE0,0x00,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_168_232_232[45] U8G_FONT_SECTION("fontpage_168_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xE0,0x22,0x20,0x2F,0xA0,0x22,0x20,0x3F, + 0xE0,0x20,0x20,0x2F,0xA0,0x28,0xA0,0x4F,0xA0,0x40,0x20,0x80,0x60}; +const u8g_fntpgm_uint8_t fontpage_168_253_253[45] U8G_FONT_SECTION("fontpage_168_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0xEE,0xE0,0x00, + 0x00,0x7B,0xC0,0x4A,0x40,0x4A,0x40,0x7A,0x40,0x4A,0xC0,0x02,0x00}; +const u8g_fntpgm_uint8_t fontpage_169_140_140[45] U8G_FONT_SECTION("fontpage_169_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0C,0x00,0x70,0x00,0x11,0xE0,0xFD,0x20,0x11, + 0x20,0x39,0x20,0x35,0x20,0x55,0x20,0x91,0x20,0x11,0xE0,0x10,0x00}; +const u8g_fntpgm_uint8_t fontpage_169_205_205[45] U8G_FONT_SECTION("fontpage_169_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0x02,0x00,0xEF,0xE0,0xA8,0x20,0xAB, + 0xA0,0xAA,0xA0,0xAA,0xA0,0xEB,0xA0,0x08,0x20,0x08,0x20,0x08,0x60}; +const u8g_fntpgm_uint8_t fontpage_171_183_183[45] U8G_FONT_SECTION("fontpage_171_183_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0xEF,0xE0,0xA5,0x40,0xAF,0xE0,0xA4, + 0x40,0xAF,0xE0,0xE8,0x20,0xA9,0x20,0x09,0x20,0x02,0x80,0x0C,0x60}; +const u8g_fntpgm_uint8_t fontpage_172_180_180[45] U8G_FONT_SECTION("fontpage_172_180_180") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB4,0xB4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0xA0,0xEB,0xC0,0xAA,0xA0,0xBF,0xE0,0xA4, + 0x80,0xAF,0xE0,0xF9,0x20,0x0F,0xE0,0x09,0x20,0x0F,0xE0,0x11,0x20}; +const u8g_fntpgm_uint8_t fontpage_172_232_232[45] U8G_FONT_SECTION("fontpage_172_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7B,0xC0,0x4A,0x40,0x4A,0x40,0x7B,0xC0,0x04, + 0x80,0xFF,0xE0,0x11,0x00,0xFB,0xE0,0x4A,0x40,0x4A,0x40,0x7B,0xC0}; +const u8g_fntpgm_uint8_t fontpage_172_244_244[45] U8G_FONT_SECTION("fontpage_172_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0xEF,0xE0,0xA5,0x40,0xAF,0xE0,0xA4, + 0x40,0xA7,0xC0,0xE4,0x40,0x07,0xC0,0x04,0x40,0x07,0xC0,0x0C,0x60}; +const u8g_fntpgm_uint8_t fontpage_173_222_222[45] U8G_FONT_SECTION("fontpage_173_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x80,0x40,0x80,0x40,0x9E,0x40,0x92, + 0x40,0x92,0x40,0x9E,0x40,0x92,0x40,0x80,0x40,0xFF,0xC0,0x80,0x40}; +const u8g_fntpgm_uint8_t fontpage_173_224_224[45] U8G_FONT_SECTION("fontpage_173_224_224") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x84,0x20,0x84,0x20,0xBF,0xA0,0x84, + 0x20,0x84,0x20,0x8A,0x20,0x91,0x20,0xA0,0xA0,0x80,0x20,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_173_250_250[45] U8G_FONT_SECTION("fontpage_173_250_250") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFA,0xFA,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x88,0x40,0x88,0x40,0xFF,0x40,0x88, + 0x40,0xBE,0x40,0xA2,0x40,0xA2,0x40,0xBE,0x40,0x80,0x40,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_173_254_254[45] U8G_FONT_SECTION("fontpage_173_254_254") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x90,0x40,0x9F,0x40,0xB2,0x40,0xCC, + 0x40,0x92,0x40,0xE9,0xC0,0x84,0x40,0x88,0x40,0x84,0x40,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_174_168_168[45] U8G_FONT_SECTION("fontpage_174_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0xFF,0xC0,0x10,0x00,0x22, + 0x00,0x62,0x00,0xAF,0x80,0x22,0x00,0x22,0x00,0x22,0x00,0x3F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_174_207_207[45] U8G_FONT_SECTION("fontpage_174_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x2F,0xE0,0x20,0x80,0xF8,0x80,0x21, + 0x00,0x21,0x80,0x23,0x40,0x35,0x20,0xC9,0x20,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_174_215_215[45] U8G_FONT_SECTION("fontpage_174_215_215") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD7,0xD7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x27,0xC0,0xF9,0x40,0x21, + 0x40,0x21,0x40,0x2F,0xE0,0x31,0x00,0xC2,0x80,0x04,0x40,0x18,0x20}; +const u8g_fntpgm_uint8_t fontpage_175_139_139[45] U8G_FONT_SECTION("fontpage_175_139_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8B,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7E,0x40,0x29,0x40,0x29,0x40,0xFF,0x40,0x29, + 0x40,0x28,0x40,0x4C,0xC0,0x04,0x00,0x3F,0x80,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_175_171_171[45] U8G_FONT_SECTION("fontpage_175_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0xFF,0x80,0x22,0x80,0x36,0xA0,0xE3, + 0xA0,0x2C,0xE0,0x64,0x00,0x04,0x00,0x3F,0xC0,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_176_235_235[45] U8G_FONT_SECTION("fontpage_176_235_235") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEB,0xEB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x21,0x00,0xF7,0xC0,0x24, + 0x40,0x27,0x40,0x25,0xC0,0x34,0x40,0xEF,0xE0,0x02,0x80,0x0C,0x60}; +const u8g_fntpgm_uint8_t fontpage_177_243_243[45] U8G_FONT_SECTION("fontpage_177_243_243") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF3,0xF3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x04,0x00,0x3F,0xC0,0x00, + 0x00,0xFF,0xE0,0x80,0x20,0x1F,0x00,0x11,0x20,0x21,0x20,0xC0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_178_135_135[45] U8G_FONT_SECTION("fontpage_178_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x1F,0x80,0x31,0x00,0x4E,0x00,0x0B, + 0x00,0x30,0xE0,0xFF,0x80,0x24,0x80,0x3F,0x80,0x24,0x80,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_178_141_141[45] U8G_FONT_SECTION("fontpage_178_141_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x3F,0xE0,0x60,0x80,0xBF,0x80,0x20, + 0x80,0x3F,0x80,0x10,0x00,0x3F,0x80,0xC9,0x00,0x06,0x00,0xF9,0xE0}; +const u8g_fntpgm_uint8_t fontpage_178_150_150[45] U8G_FONT_SECTION("fontpage_178_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x3D,0x00,0x25,0x00,0x45, + 0x80,0xA5,0x40,0x19,0x20,0x09,0x00,0x11,0x00,0x21,0x00,0x41,0x00}; +const u8g_fntpgm_uint8_t fontpage_178_154_154[45] U8G_FONT_SECTION("fontpage_178_154_154") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9A,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x1F,0x00,0x21,0x00,0x52,0x00,0x0C, + 0x00,0x34,0x00,0xCF,0x80,0x10,0x80,0x69,0x00,0x06,0x00,0xF8,0x00}; +const u8g_fntpgm_uint8_t fontpage_178_167_167[45] U8G_FONT_SECTION("fontpage_178_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04, + 0x00,0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_178_169_170[73] U8G_FONT_SECTION("fontpage_178_169_170") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA9,0xAA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0xFF, + 0xE0,0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x0A,0x00,0x0A, + 0x00,0x11,0x00,0x19,0x00,0x24,0x80,0xC4,0x60}; +const u8g_fntpgm_uint8_t fontpage_178_177_177[45] U8G_FONT_SECTION("fontpage_178_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x00,0x24,0x00,0x3F,0xC0,0x44,0x00,0x04, + 0x00,0xFF,0xE0,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_178_180_180[45] U8G_FONT_SECTION("fontpage_178_180_180") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB4,0xB4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x0A,0x00,0x22,0x00,0x12,0x00,0x02, + 0x00,0xFF,0xE0,0x02,0x00,0x05,0x00,0x08,0x80,0x10,0x40,0x60,0x20}; +const u8g_fntpgm_uint8_t fontpage_178_253_253[45] U8G_FONT_SECTION("fontpage_178_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x23,0xE0,0xF8,0x40,0x28,0x80,0x28, + 0x80,0x4F,0xE0,0x50,0x80,0x30,0x80,0x28,0x80,0x48,0x80,0x83,0x80}; +const u8g_fntpgm_uint8_t fontpage_179_203_203[45] U8G_FONT_SECTION("fontpage_179_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0xFA,0x40,0x2A,0x20,0x2F, + 0xE0,0x48,0x00,0x53,0xE0,0x32,0x20,0x2A,0x20,0x4B,0xE0,0x82,0x20}; +const u8g_fntpgm_uint8_t fontpage_182_208_208[45] U8G_FONT_SECTION("fontpage_182_208_208") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x04, + 0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x14,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_182_216_216[45] U8G_FONT_SECTION("fontpage_182_216_216") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0xFF,0xE0,0x10,0x00,0x2F,0xC0,0x20, + 0x80,0x61,0x00,0xBF,0xE0,0x21,0x00,0x21,0x00,0x21,0x00,0x27,0x00}; +const u8g_fntpgm_uint8_t fontpage_183_137_137[45] U8G_FONT_SECTION("fontpage_183_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x88,0x40,0x08, + 0x00,0xFF,0xE0,0x11,0x00,0x31,0x00,0x0E,0x00,0x09,0x80,0x70,0x60}; +const u8g_fntpgm_uint8_t fontpage_183_140_140[45] U8G_FONT_SECTION("fontpage_183_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x9F,0x40,0x00, + 0x00,0x7F,0xE0,0x0A,0x00,0x12,0x00,0x12,0x20,0x22,0x20,0x41,0xE0}; +const u8g_fntpgm_uint8_t fontpage_183_154_154[45] U8G_FONT_SECTION("fontpage_183_154_154") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x80,0x40,0x3F, + 0xC0,0x04,0x00,0x24,0x00,0x27,0x80,0x24,0x00,0x54,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_183_162_162[45] U8G_FONT_SECTION("fontpage_183_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0xFF,0xC0,0x90,0x40,0x3F,0x00,0x52, + 0x00,0x8C,0x00,0x33,0x00,0xFF,0xC0,0x21,0x00,0x21,0x00,0x3F,0x00}; +const u8g_fntpgm_uint8_t fontpage_183_171_171[45] U8G_FONT_SECTION("fontpage_183_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0xFF,0xC0,0x80,0x40,0x3F,0x00,0x21, + 0x00,0x3F,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x7F,0x80,0x40,0x80}; +const u8g_fntpgm_uint8_t fontpage_183_249_249[45] U8G_FONT_SECTION("fontpage_183_249_249") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF9,0xF9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x00,0x80,0xF0,0x80,0x1F,0xE0,0x90,0x80,0x50, + 0x80,0x24,0x80,0x22,0x80,0x50,0x80,0x50,0x80,0x82,0x80,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_184_134_134[45] U8G_FONT_SECTION("fontpage_184_134_134") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x86,0x86,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x27,0xC0,0xA4,0x80,0x6B,0x00,0x22, + 0x80,0x24,0x80,0x6F,0xE0,0xA4,0x80,0x22,0x80,0x20,0x80,0x21,0x80}; +const u8g_fntpgm_uint8_t fontpage_184_143_143[45] U8G_FONT_SECTION("fontpage_184_143_143") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8F,0x8F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0x24,0x80,0x24, + 0x40,0x44,0x40,0x44,0x20,0x84,0x20,0x04,0x00,0x14,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_184_177_177[45] U8G_FONT_SECTION("fontpage_184_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFD,0x40,0x01,0x20,0x7F,0xE0,0x4A, + 0x80,0x7A,0x80,0x12,0x80,0x5A,0xA0,0x56,0xA0,0x92,0xA0,0x34,0x60}; +const u8g_fntpgm_uint8_t fontpage_184_207_207[45] U8G_FONT_SECTION("fontpage_184_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xE0,0x20,0x20,0x3F,0xE0,0x28,0x40,0x24, + 0x80,0x3F,0xE0,0x24,0x80,0x3F,0xE0,0x24,0x80,0x48,0x80,0x90,0x80}; +const u8g_fntpgm_uint8_t fontpage_187_229_229[41] U8G_FONT_SECTION("fontpage_187_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x09,0x00,0x00, + 0x00,0x0B,0x09,0x12,0x0C,0x00,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04, + 0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_187_238_238[45] U8G_FONT_SECTION("fontpage_187_238_238") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x80,0x09,0x00,0xFF,0xE0,0x04,0x00,0x7F, + 0xC0,0x08,0x00,0xFF,0xE0,0x10,0x00,0x2F,0x80,0x42,0x00,0xBF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_187_242_242[43] U8G_FONT_SECTION("fontpage_187_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x09,0xFF,0x00, + 0x00,0x0A,0x0A,0x14,0x0C,0x01,0xFF,0xFF,0x00,0x01,0x00,0x01,0x00,0x81,0x00,0xFF, + 0x00,0x80,0x00,0x80,0x40,0x80,0x40,0x80,0x40,0x7F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_188_243_243[45] U8G_FONT_SECTION("fontpage_188_243_243") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF3,0xF3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0x24,0x80,0x15,0x00,0x04, + 0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_188_246_246[45] U8G_FONT_SECTION("fontpage_188_246_246") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF6,0xF6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x11,0x00,0x7F,0xC0,0x11,0x00,0x11, + 0x00,0x11,0x00,0xFF,0xE0,0x11,0x00,0x11,0x00,0x21,0x00,0x41,0x00}; +const u8g_fntpgm_uint8_t fontpage_189_138_138[45] U8G_FONT_SECTION("fontpage_189_138_138") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8A,0x8A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0x7F,0xE0,0x42,0x00,0x42,0x00,0x7F, + 0xE0,0x42,0x00,0x47,0x00,0x4A,0x80,0x52,0x40,0xA2,0x20,0x82,0x00}; +const u8g_fntpgm_uint8_t fontpage_189_148_148[45] U8G_FONT_SECTION("fontpage_189_148_148") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x94,0x94,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x02,0x00,0x7F,0xE0,0x40,0x00,0x44, + 0x40,0x52,0x40,0x4A,0x40,0x48,0x80,0x40,0x80,0x81,0x00,0x9F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_189_159_159[45] U8G_FONT_SECTION("fontpage_189_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0x3F,0xE0,0x2A,0x80,0x2A,0x40,0x3F, + 0xE0,0x24,0x00,0x27,0xC0,0x2A,0x40,0x31,0x80,0x42,0x40,0x8C,0x20}; +const u8g_fntpgm_uint8_t fontpage_189_166_166[45] U8G_FONT_SECTION("fontpage_189_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x49,0x00,0x7F,0xC0,0x49, + 0x00,0x4F,0x00,0x40,0x00,0x5F,0x80,0x49,0x00,0x86,0x00,0xB9,0xC0}; +const u8g_fntpgm_uint8_t fontpage_190_128_128[45] U8G_FONT_SECTION("fontpage_190_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x11,0x00,0x11,0x00,0x11,0x00,0x11, + 0x00,0xFF,0xE0,0x11,0x00,0x21,0x00,0x21,0x00,0x41,0x00,0x81,0x00}; +const u8g_fntpgm_uint8_t fontpage_190_131_131[45] U8G_FONT_SECTION("fontpage_190_131_131") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x83,0x83,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x08,0x00,0x10,0x80,0x3F, + 0xC0,0x11,0x00,0xFF,0xE0,0x11,0x00,0x11,0x00,0x21,0x00,0x41,0x00}; +const u8g_fntpgm_uint8_t fontpage_190_143_143[45] U8G_FONT_SECTION("fontpage_190_143_143") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8F,0x8F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x80,0x02,0x40,0x02,0x00,0xFF,0xE0,0x02, + 0x00,0x7A,0x00,0x12,0x00,0x11,0x00,0x11,0x20,0x18,0xA0,0xE0,0x60}; +const u8g_fntpgm_uint8_t fontpage_190_149_149[45] U8G_FONT_SECTION("fontpage_190_149_149") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x95,0x95,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFC,0x40,0x04,0x40,0x04,0x40,0x7C,0x40,0x40, + 0x40,0xFC,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x28,0x40,0x10,0x40}; +const u8g_fntpgm_uint8_t fontpage_190_185_185[45] U8G_FONT_SECTION("fontpage_190_185_185") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB9,0xB9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xE4,0x40,0x22,0x80,0x2F,0xE0,0xE9,0x20,0x8F, + 0xE0,0x89,0x20,0xEF,0xE0,0x21,0x00,0x2F,0xE0,0xA1,0x00,0x41,0x00}; +const u8g_fntpgm_uint8_t fontpage_190_210_210[45] U8G_FONT_SECTION("fontpage_190_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x10,0x00,0x17,0xC0,0x90,0x40,0x90,0x40,0x90, + 0x40,0x97,0xC0,0x90,0x40,0x90,0x40,0x20,0x40,0x4F,0xC0,0x80,0x40}; +const u8g_fntpgm_uint8_t fontpage_191_132_133[73] U8G_FONT_SECTION("fontpage_191_132_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x84,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x17,0xC0,0x20,0x80,0x49,0x00,0x92,0x80,0x24, + 0x40,0x68,0x20,0xA7,0xC0,0x21,0x00,0x21,0x00,0x21,0x00,0x2F,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x11,0x00,0x21,0x00,0x47,0xC0,0x91,0x00,0x1F,0xE0,0x20,0x80,0x6F, + 0xE0,0xA4,0x80,0x22,0x80,0x20,0x80,0x21,0x80}; +const u8g_fntpgm_uint8_t fontpage_191_170_170[45] U8G_FONT_SECTION("fontpage_191_170_170") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAA,0xAA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x1F,0xE0,0x28,0x80,0x4F,0xE0,0x98,0x80,0x2B, + 0xE0,0x6A,0x20,0xAB,0xE0,0x2A,0x20,0x2B,0xE0,0x2A,0x20,0x33,0xE0}; +const u8g_fntpgm_uint8_t fontpage_191_174_174[45] U8G_FONT_SECTION("fontpage_191_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2A,0x80,0x6A,0x80,0xBE,0x80,0x01,0xE0,0x5D, + 0x40,0xC3,0x40,0x5D,0x40,0x54,0x80,0x56,0x80,0x55,0x40,0x62,0x20}; +const u8g_fntpgm_uint8_t fontpage_191_195_195[45] U8G_FONT_SECTION("fontpage_191_195_195") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC3,0xC3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x02,0x00,0x12,0x00,0x12,0x00,0x10, + 0x40,0x50,0x20,0x50,0x20,0x50,0xA0,0x90,0x80,0x10,0x80,0x0F,0x80}; +const u8g_fntpgm_uint8_t fontpage_191_253_253[45] U8G_FONT_SECTION("fontpage_191_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x3F,0xC0,0x2A,0x40,0x4A,0x40,0x14, + 0x40,0x28,0x40,0x05,0x80,0x12,0x40,0x50,0xA0,0x50,0xA0,0x8F,0x80}; +const u8g_fntpgm_uint8_t fontpage_192_167_167[45] U8G_FONT_SECTION("fontpage_192_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x25,0x00,0xB5,0x00,0xAF,0xE0,0xA9, + 0x00,0xB1,0x00,0x27,0xC0,0x21,0x00,0x21,0x00,0x21,0x00,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_192_187_187[45] U8G_FONT_SECTION("fontpage_192_187_187") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBB,0xBB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x0A,0x00,0x3F,0x80,0x20,0x80,0x20, + 0x80,0x3F,0x80,0x20,0x80,0x04,0x40,0x52,0xA0,0x50,0xA0,0x8F,0x80}; +const u8g_fntpgm_uint8_t fontpage_192_226_226[45] U8G_FONT_SECTION("fontpage_192_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x2F,0xE0,0xB2,0x00,0xAA,0x80,0xA4, + 0x80,0xA5,0xA0,0x2A,0xC0,0x30,0x80,0x21,0x40,0x22,0x40,0x24,0x20}; +const u8g_fntpgm_uint8_t fontpage_192_239_239[45] U8G_FONT_SECTION("fontpage_192_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20, + 0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x54,0x40,0x52,0xA0,0x8F,0x80}; +const u8g_fntpgm_uint8_t fontpage_194_159_159[45] U8G_FONT_SECTION("fontpage_194_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x40,0x7F,0xE0,0x41,0x00,0x7F,0x40,0x5D, + 0x40,0x52,0x80,0x9D,0xA0,0x82,0x60,0x24,0x40,0xA2,0xA0,0x9F,0x80}; +const u8g_fntpgm_uint8_t fontpage_196_143_144[73] U8G_FONT_SECTION("fontpage_196_143_144") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8F,0x90,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x80,0x7A,0x40,0x0A,0x00,0x4F,0xE0,0x2A, + 0x00,0x12,0x40,0x12,0x80,0x29,0x00,0x41,0x20,0x86,0xA0,0x00,0x60,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x02,0x80,0x02,0x40,0x7F,0xE0,0x42,0x00,0x42,0x00,0x7A,0x40,0x4A, + 0x40,0x4A,0x80,0x49,0x20,0x52,0xA0,0x84,0x60}; +const u8g_fntpgm_uint8_t fontpage_196_183_183[45] U8G_FONT_SECTION("fontpage_196_183_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x02,0x00,0x3F,0xC0,0x20,0x40,0x20, + 0x40,0x3F,0xC0,0x20,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x80,0x00}; +const u8g_fntpgm_uint8_t fontpage_196_192_192[45] U8G_FONT_SECTION("fontpage_196_192_192") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x18,0x60,0x63,0x80,0x42,0x00,0x7A,0x00,0x4B, + 0xE0,0x4A,0x40,0x7A,0x40,0x42,0x40,0x42,0x40,0x44,0x40,0x88,0x40}; +const u8g_fntpgm_uint8_t fontpage_196_199_199[45] U8G_FONT_SECTION("fontpage_196_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x7F,0xE0,0x40, + 0x00,0x7D,0xE0,0x44,0x20,0x54,0xA0,0x4C,0x60,0x54,0xA0,0xA9,0x60}; +const u8g_fntpgm_uint8_t fontpage_196_203_203[45] U8G_FONT_SECTION("fontpage_196_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x03,0xC0,0x7C,0x00,0x04,0x00,0x7F,0xC0,0x04, + 0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00}; +const u8g_fntpgm_uint8_t fontpage_196_211_211[45] U8G_FONT_SECTION("fontpage_196_211_211") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD3,0xD3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xE0,0xF8,0x80,0x20,0x80,0x28, + 0x80,0x30,0x80,0x60,0x80,0xA0,0x80,0x20,0x80,0x20,0x80,0xE3,0x80}; +const u8g_fntpgm_uint8_t fontpage_196_231_231[45] U8G_FONT_SECTION("fontpage_196_231_231") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE7,0xE7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x22,0x00,0xFF,0x80,0x22,0x80,0x2A, + 0x80,0x36,0x80,0x62,0x80,0xA7,0xA0,0x24,0xA0,0xA8,0xA0,0x50,0x60}; +const u8g_fntpgm_uint8_t fontpage_196_249_249[45] U8G_FONT_SECTION("fontpage_196_249_249") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF9,0xF9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x80,0x24,0x80,0xFC,0x80,0x24,0xA0,0x2F, + 0xC0,0x34,0x80,0x64,0x80,0xA4,0x80,0x25,0xA0,0x26,0xA0,0xE4,0x60}; +const u8g_fntpgm_uint8_t fontpage_197_150_150[45] U8G_FONT_SECTION("fontpage_197_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x40,0x22,0x40,0xF9,0x40,0x20,0x40,0x2A, + 0x40,0x31,0x40,0x60,0xE0,0xAF,0x40,0x20,0x40,0x20,0x40,0xE0,0x40}; +const u8g_fntpgm_uint8_t fontpage_197_165_165[45] U8G_FONT_SECTION("fontpage_197_165_165") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x24,0x40,0xFC,0x40,0x25,0x80,0x2C, + 0x00,0x37,0xE0,0x65,0x40,0xA5,0x40,0x24,0x80,0x25,0x40,0xE6,0x20}; +const u8g_fntpgm_uint8_t fontpage_197_172_172[45] U8G_FONT_SECTION("fontpage_197_172_172") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0xFA,0x40,0x27,0xA0,0x28, + 0x20,0x30,0x00,0x67,0xE0,0xA4,0x20,0x24,0x20,0x27,0xE0,0xE4,0x20}; +const u8g_fntpgm_uint8_t fontpage_197_189_189[45] U8G_FONT_SECTION("fontpage_197_189_189") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBD,0xBD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x20,0x80,0xF8,0x80,0x27,0xE0,0x2C, + 0xA0,0x34,0xA0,0x67,0xE0,0xA4,0xA0,0x24,0xA0,0x27,0xE0,0xE4,0x20}; +const u8g_fntpgm_uint8_t fontpage_197_212_212[45] U8G_FONT_SECTION("fontpage_197_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x80,0x22,0x40,0xFF,0xE0,0x22,0x00,0x2B, + 0xC0,0x32,0x40,0x65,0x40,0xA4,0x80,0x28,0x80,0x29,0x40,0xE6,0x20}; +const u8g_fntpgm_uint8_t fontpage_197_233_233[45] U8G_FONT_SECTION("fontpage_197_233_233") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE9,0xE9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xE0,0x22,0x40,0xF9,0x80,0x22,0x40,0x2C, + 0x20,0x31,0x00,0x67,0xC0,0xA1,0x00,0x2F,0xE0,0x21,0x00,0xE1,0x00}; +const u8g_fntpgm_uint8_t fontpage_198_137_137[45] U8G_FONT_SECTION("fontpage_198_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x20,0x80,0xFF,0xE0,0x25,0x20,0x29, + 0x00,0x37,0xE0,0x62,0x40,0xA6,0x40,0x21,0x80,0x22,0x80,0xEC,0x60}; +const u8g_fntpgm_uint8_t fontpage_198_161_161[45] U8G_FONT_SECTION("fontpage_198_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x25,0x20,0xFB,0x40,0x21,0x00,0x2F, + 0xE0,0x30,0x20,0x60,0x20,0xA7,0xE0,0x20,0x20,0x20,0x20,0xEF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_198_164_164[45] U8G_FONT_SECTION("fontpage_198_164_164") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xE0,0xFA,0x40,0x21,0x80,0x2E, + 0x60,0x30,0x00,0x62,0x40,0xA2,0x40,0x22,0x40,0x24,0x40,0xE8,0x40}; +const u8g_fntpgm_uint8_t fontpage_198_223_223[45] U8G_FONT_SECTION("fontpage_198_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x23,0xC0,0x22,0x40,0xFB,0xC0,0x20,0x00,0x2F, + 0xE0,0x34,0x20,0x65,0x20,0xA5,0x20,0x25,0x20,0x22,0x80,0xEC,0x60}; +const u8g_fntpgm_uint8_t fontpage_198_226_226[45] U8G_FONT_SECTION("fontpage_198_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xC0,0xFC,0x80,0x27,0xC0,0x2D, + 0x40,0x35,0x40,0x6F,0xE0,0xA1,0x00,0x22,0x80,0x24,0x40,0xE8,0x20}; +const u8g_fntpgm_uint8_t fontpage_199_137_137[45] U8G_FONT_SECTION("fontpage_199_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0xE0,0xF9,0x00,0x27,0xC0,0x2C, + 0x40,0x37,0xC0,0x64,0x40,0xA7,0xC0,0x21,0x00,0x2F,0xE0,0xE1,0x00}; +const u8g_fntpgm_uint8_t fontpage_199_162_162[45] U8G_FONT_SECTION("fontpage_199_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xE0,0x28,0x20,0xF2,0x80,0x24,0x40,0x29, + 0x20,0x31,0x00,0x6F,0xE0,0xA1,0x00,0x25,0x80,0x29,0x40,0xF1,0x20}; +const u8g_fntpgm_uint8_t fontpage_199_165_165[45] U8G_FONT_SECTION("fontpage_199_165_165") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0xF4,0x40,0x22,0x80,0x2F, + 0xE0,0x31,0x00,0x6F,0xE0,0xA2,0x40,0x26,0x80,0x21,0x40,0xEE,0x20}; +const u8g_fntpgm_uint8_t fontpage_199_167_167[45] U8G_FONT_SECTION("fontpage_199_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0xF8,0x20,0x22,0x80,0x24, + 0x40,0x38,0x20,0x67,0xC0,0xA1,0x00,0x21,0x00,0x21,0x00,0xEF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_199_208_208[45] U8G_FONT_SECTION("fontpage_199_208_208") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x24,0x40,0xFF,0xC0,0x24,0x40,0x27, + 0xC0,0x30,0x00,0x6F,0xE0,0xA5,0x00,0x25,0xE0,0x2B,0x00,0xF1,0xE0}; +const u8g_fntpgm_uint8_t fontpage_199_210_210[45] U8G_FONT_SECTION("fontpage_199_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0xC0,0x27,0x00,0xF1,0x00,0x2F,0xE0,0x21, + 0x00,0x35,0x60,0x69,0x20,0xAD,0x60,0x29,0x20,0x29,0x20,0xEF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_202_182_182[45] U8G_FONT_SECTION("fontpage_202_182_182") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB6,0xB6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x12,0x00,0x93,0xE0,0x94,0x40,0x9A, + 0x40,0x92,0x40,0xB2,0x80,0xD1,0x00,0x91,0x80,0x12,0x40,0x14,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_190_190[45] U8G_FONT_SECTION("fontpage_202_190_190") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBE,0xBE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x11,0x00,0xFD,0xE0,0x22,0x40,0x25, + 0x40,0x39,0x40,0x29,0x40,0x28,0x80,0x49,0x80,0x4A,0x40,0x94,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_240_240[45] U8G_FONT_SECTION("fontpage_202_240_240") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x95,0x00,0x59,0x00,0xFD,0xE0,0x33,0x40,0x59, + 0x40,0x95,0x40,0xFD,0x40,0x29,0x40,0x68,0x80,0x11,0x40,0xEE,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_242_242[45] U8G_FONT_SECTION("fontpage_202_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x80,0xFE,0xE0,0x00,0x80,0x78,0x80,0x4B, + 0xE0,0x79,0x40,0x01,0x40,0xFF,0x40,0xAA,0x80,0xBB,0x40,0x86,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_244_244[45] U8G_FONT_SECTION("fontpage_202_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFF,0xE0,0x55,0x40,0x7C,0x80,0x39, + 0x40,0x56,0x20,0x7F,0xC0,0x04,0x00,0x27,0x80,0x24,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_203_135_135[45] U8G_FONT_SECTION("fontpage_203_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x04,0x00,0xFF,0xE0,0x11,0x00,0x11, + 0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x1B,0x00,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_203_153_153[45] U8G_FONT_SECTION("fontpage_203_153_153") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x99,0x99,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0xAC,0x80,0x72,0x80,0x20,0x80,0xFC, + 0x80,0x22,0x80,0x30,0xE0,0x6F,0x80,0xA0,0x80,0x20,0x80,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_203_156_156[45] U8G_FONT_SECTION("fontpage_203_156_156") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x40,0x29,0x40,0x44,0xC0,0xB8,0x40,0x12, + 0x40,0x7D,0x40,0x10,0x60,0x55,0xC0,0x52,0x40,0x92,0x40,0x30,0x40}; +const u8g_fntpgm_uint8_t fontpage_203_173_173[45] U8G_FONT_SECTION("fontpage_203_173_173") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAD,0xAD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x60,0xD5,0x80,0xB9,0x00,0x91,0x00,0xFD, + 0xE0,0xB1,0x40,0xD9,0x40,0xD5,0x40,0x91,0x40,0xFA,0x40,0x04,0x40}; +const u8g_fntpgm_uint8_t fontpage_203_176_176[45] U8G_FONT_SECTION("fontpage_203_176_176") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x60,0xFD,0x80,0x45,0x00,0x29,0x00,0xFD, + 0xE0,0x11,0x40,0xFD,0x40,0x11,0x40,0x55,0x40,0x92,0x40,0x34,0x40}; +const u8g_fntpgm_uint8_t fontpage_203_185_185[45] U8G_FONT_SECTION("fontpage_203_185_185") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB9,0xB9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x04,0x00,0xFF,0xE0,0x08,0x00,0x08, + 0x00,0x0F,0x80,0x10,0x80,0x10,0x80,0x20,0x80,0x40,0x80,0x87,0x00}; +const u8g_fntpgm_uint8_t fontpage_203_224_224[45] U8G_FONT_SECTION("fontpage_203_224_224") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0xFF, + 0xE0,0x0A,0x00,0x0A,0x00,0x12,0x00,0x12,0x20,0x22,0x20,0xC1,0xE0}; +const u8g_fntpgm_uint8_t fontpage_203_246_246[45] U8G_FONT_SECTION("fontpage_203_246_246") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF6,0xF6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x00,0x80,0xF0,0x80,0x9F,0xE0,0x90,0x80,0x94, + 0x80,0xF2,0x80,0x92,0x80,0x90,0x80,0x90,0x80,0xF0,0x80,0x03,0x80}; +const u8g_fntpgm_uint8_t fontpage_204_142_142[45] U8G_FONT_SECTION("fontpage_204_142_142") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8E,0x8E,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x03,0xE0,0xF2,0x20,0x92,0x20,0x93,0xE0,0xF2, + 0x20,0x92,0x20,0x93,0xE0,0xF2,0x20,0x04,0x20,0x08,0xA0,0x30,0x40}; +const u8g_fntpgm_uint8_t fontpage_204_175_175[45] U8G_FONT_SECTION("fontpage_204_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x1F,0x80,0x10,0x80,0x1F,0x80,0x10,0x80,0x1F, + 0x80,0x00,0x00,0xFF,0xE0,0x24,0x00,0x27,0x80,0x54,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_205_130_130[45] U8G_FONT_SECTION("fontpage_205_130_130") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x82,0x82,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x40,0xFB,0x80,0x52,0x00,0xFB,0xE0,0x12, + 0x80,0xF4,0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_205_171_171[45] U8G_FONT_SECTION("fontpage_205_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0xE0,0xFF,0x00,0x55,0xE0,0x7D,0x40,0x55, + 0x40,0xFF,0xC0,0x10,0x40,0x1F,0xC0,0x10,0x40,0x1F,0xC0,0x10,0x40}; +const u8g_fntpgm_uint8_t fontpage_205_244_244[45] U8G_FONT_SECTION("fontpage_205_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xE0,0x02,0x00,0x3F,0xC0,0x22,0x40,0x3F, + 0xC0,0x22,0x40,0x3F,0xC0,0x0A,0x00,0x04,0x00,0x1B,0x00,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_206_128_128[45] U8G_FONT_SECTION("fontpage_206_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF, + 0xE0,0x48,0x00,0x7F,0xC0,0x4A,0x40,0x79,0x80,0xC9,0x80,0x0E,0x60}; +const u8g_fntpgm_uint8_t fontpage_206_137_137[45] U8G_FONT_SECTION("fontpage_206_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0xFF,0xE0,0x10,0x00,0x1F,0x80,0x30, + 0x80,0x5F,0x80,0x90,0x80,0x1F,0x80,0x10,0x80,0x10,0x80,0x11,0x80}; +const u8g_fntpgm_uint8_t fontpage_206_159_159[45] U8G_FONT_SECTION("fontpage_206_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x49,0xE0,0xFD,0x20,0x49,0x20,0x79,0xE0,0x49, + 0x20,0x79,0x20,0x49,0xE0,0xFD,0x20,0x01,0x20,0x49,0x20,0x86,0x60}; +const u8g_fntpgm_uint8_t fontpage_206_186_186[45] U8G_FONT_SECTION("fontpage_206_186_186") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBA,0xBA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0x80,0x24,0x80,0xFC,0x80,0x24, + 0x80,0x74,0x80,0x6C,0x80,0xA4,0x80,0xA4,0x80,0x28,0xA0,0x30,0xE0}; +const u8g_fntpgm_uint8_t fontpage_206_192_192[45] U8G_FONT_SECTION("fontpage_206_192_192") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x19,0x00,0x06,0x00,0x19,0x00,0x64, + 0xC0,0x04,0x00,0xFF,0xE0,0x15,0x00,0x24,0x80,0xC4,0x60,0x0C,0x00}; +const u8g_fntpgm_uint8_t fontpage_206_223_223[45] U8G_FONT_SECTION("fontpage_206_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x04,0x00,0x3F,0x80,0x24, + 0x80,0x24,0x80,0x3F,0x80,0x0E,0x00,0x15,0x00,0x24,0x80,0xC4,0x60}; +const u8g_fntpgm_uint8_t fontpage_206_225_225[45] U8G_FONT_SECTION("fontpage_206_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x1F,0x80,0x29,0x00,0x46,0x00,0x0A, + 0x00,0x35,0x80,0xC4,0x60,0x3F,0x80,0x15,0x00,0x24,0x80,0xDC,0x40}; +const u8g_fntpgm_uint8_t fontpage_206_229_229[45] U8G_FONT_SECTION("fontpage_206_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x24,0x80,0x15,0x00,0xFF, + 0xE0,0x04,0x00,0x0E,0x00,0x15,0x00,0x24,0x80,0xC4,0x60,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_206_255_255[45] U8G_FONT_SECTION("fontpage_206_255_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0xC0,0x27,0x00,0xFC,0x00,0x24,0x00,0x27, + 0xC0,0x74,0x40,0x6E,0x40,0xA5,0x80,0x28,0x80,0x29,0x40,0x36,0x20}; +const u8g_fntpgm_uint8_t fontpage_207_151_151[45] U8G_FONT_SECTION("fontpage_207_151_151") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x97,0x97,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0xFF,0xE0,0x21,0x00,0x71, + 0x00,0x6B,0x80,0xA5,0x40,0xA9,0x20,0x21,0x00,0x21,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_207_241_241[45] U8G_FONT_SECTION("fontpage_207_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x21,0x00,0xFF,0xE0,0x21,0x00,0x71, + 0x00,0x69,0x00,0xA7,0xC0,0xA1,0x00,0x21,0x00,0x21,0x00,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_208_161_161[45] U8G_FONT_SECTION("fontpage_208_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x21,0x00,0x2F,0xE0,0xF0,0x00,0x22, + 0x80,0x74,0x40,0x6A,0xA0,0xA2,0x80,0x21,0x00,0x22,0x80,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_208_188_188[45] U8G_FONT_SECTION("fontpage_208_188_188") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xC0,0xF4,0x40,0x2A,0x80,0x21, + 0x00,0x72,0x80,0x6C,0x60,0xA7,0xC0,0x24,0x40,0x24,0x40,0x27,0xC0}; +const u8g_fntpgm_uint8_t fontpage_209_175_175[45] U8G_FONT_SECTION("fontpage_209_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x40,0x22,0x80,0x27,0xC0,0xF9,0x40,0x27, + 0xC0,0x75,0x00,0x6F,0xE0,0xA3,0x20,0x25,0x20,0x29,0xC0,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_209_192_192[45] U8G_FONT_SECTION("fontpage_209_192_192") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x22,0x80,0xFC,0x40,0x28,0x20,0x27, + 0xC0,0x70,0x00,0x69,0x20,0xA4,0xA0,0x22,0x40,0x22,0x80,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_211_253_253[45] U8G_FONT_SECTION("fontpage_211_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x80,0x2F,0xE0,0xFA,0xA0,0x2F,0xE0,0x2A, + 0xA0,0x3F,0xE0,0x64,0x40,0xA7,0xC0,0x24,0x40,0x27,0xC0,0x24,0x40}; +const u8g_fntpgm_uint8_t fontpage_212_161_161[45] U8G_FONT_SECTION("fontpage_212_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x80,0x2F,0xE0,0xF2,0x80,0x27,0xC0,0x34, + 0x40,0x6F,0xC0,0x64,0x40,0xAF,0xE0,0x21,0x00,0x22,0x80,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_212_217_217[45] U8G_FONT_SECTION("fontpage_212_217_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0x40,0x2A,0xA0,0xF4,0x40,0x27,0xC0,0x38, + 0x20,0x27,0xC0,0x64,0x40,0xA7,0xC0,0x24,0x40,0x22,0x80,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_214_226_227[71] U8G_FONT_SECTION("fontpage_214_226_227") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE3,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0x24,0x00,0x27, + 0x80,0x24,0x00,0x24,0x00,0x24,0x00,0x24,0x00,0x24,0x00,0xFF,0xC0,0x0B,0x0A,0x14, + 0x0C,0x00,0xFF,0xFF,0xE0,0x04,0x00,0x04,0x00,0x24,0x00,0x27,0xC0,0x24,0x00,0x24, + 0x00,0x24,0x00,0x24,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_214_229_229[45] U8G_FONT_SECTION("fontpage_214_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x27,0xC0,0x24,0x00,0x24,0x00,0xFF, + 0xE0,0x04,0x00,0x14,0x40,0x24,0x80,0x41,0x00,0x06,0x00,0xF8,0x00}; +const u8g_fntpgm_uint8_t fontpage_215_212_212[45] U8G_FONT_SECTION("fontpage_215_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x84,0x00,0x84,0x00,0x84,0x80,0x85,0x00,0xF6, + 0x00,0x84,0x00,0x84,0x00,0x84,0x00,0xB4,0x40,0xC4,0x40,0x83,0xC0}; +const u8g_fntpgm_uint8_t fontpage_217_161_161[45] U8G_FONT_SECTION("fontpage_217_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0x80,0x24,0x80,0x84,0x80,0x48,0xE0,0x10, + 0x00,0x2F,0xC0,0x24,0x80,0x42,0x80,0xC3,0x00,0x44,0x80,0x58,0x60}; +const u8g_fntpgm_uint8_t fontpage_217_226_226[45] U8G_FONT_SECTION("fontpage_217_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x21,0x00,0x8F,0xE0,0x49,0x20,0x19, + 0x00,0x2F,0xC0,0x28,0x40,0xCA,0x80,0x49,0x00,0x52,0x80,0x6C,0x60}; +const u8g_fntpgm_uint8_t fontpage_217_232_232[45] U8G_FONT_SECTION("fontpage_217_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x21,0x00,0x8F,0xE0,0x51,0x00,0x11, + 0x00,0x21,0x00,0x27,0xC0,0xC1,0x00,0x41,0x00,0x41,0x00,0x4F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_218_151_151[45] U8G_FONT_SECTION("fontpage_218_151_151") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x97,0x97,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x25,0x00,0x87,0xC0,0x49,0x00,0x21, + 0x00,0x3F,0xE0,0x42,0x80,0xC2,0x80,0x44,0xA0,0x48,0xA0,0x50,0xE0}; +const u8g_fntpgm_uint8_t fontpage_218_187_187[45] U8G_FONT_SECTION("fontpage_218_187_187") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBB,0xBB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0xC0,0x27,0x00,0x81,0x00,0x5F,0xE0,0x11, + 0x00,0x21,0x00,0x27,0xC0,0xC4,0x40,0x44,0x40,0x47,0xC0,0x44,0x40}; +const u8g_fntpgm_uint8_t fontpage_218_193_193[45] U8G_FONT_SECTION("fontpage_218_193_193") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC1,0xC1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x82,0x00,0x5F,0xE0,0x04,0x00,0x88,0x80,0x5F, + 0xC0,0x20,0x40,0x2A,0x80,0xCA,0x80,0x4A,0xA0,0x4A,0xA0,0x52,0x60}; +const u8g_fntpgm_uint8_t fontpage_218_203_203[45] U8G_FONT_SECTION("fontpage_218_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xBE,0x20,0x62,0xA0,0x2A,0xA0,0xAA,0xA0,0x6A, + 0xA0,0x2A,0xA0,0x2A,0xA0,0xC8,0xA0,0x54,0x20,0x62,0x20,0x40,0xE0}; +const u8g_fntpgm_uint8_t fontpage_219_136_136[45] U8G_FONT_SECTION("fontpage_219_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x49,0x20,0x25,0x40,0x81,0x00,0x57,0xE0,0x14, + 0x20,0x27,0xE0,0x24,0x20,0xC7,0xE0,0x44,0x20,0x44,0x20,0x44,0x60}; +const u8g_fntpgm_uint8_t fontpage_219_225_225[45] U8G_FONT_SECTION("fontpage_219_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x25,0x40,0x09,0x80,0x82,0x80,0x54, + 0x40,0x29,0x20,0x25,0x40,0xC5,0x80,0x49,0x00,0x42,0x80,0x5C,0x60}; +const u8g_fntpgm_uint8_t fontpage_219_247_247[45] U8G_FONT_SECTION("fontpage_219_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xC0,0x28,0x40,0x0F,0xC0,0x88,0x40,0x5F, + 0xC0,0x29,0x20,0x29,0x40,0xCF,0x80,0x49,0x20,0x4B,0x20,0x4C,0xE0}; +const u8g_fntpgm_uint8_t fontpage_220_133_133[45] U8G_FONT_SECTION("fontpage_220_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x2F,0xE0,0x01,0x00,0x97,0xC0,0x51, + 0x00,0x2F,0xE0,0x24,0x40,0xC7,0x40,0x45,0xC0,0x44,0x40,0x44,0xC0}; +const u8g_fntpgm_uint8_t fontpage_220_169_169[45] U8G_FONT_SECTION("fontpage_220_169_169") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA9,0xA9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xC0,0x24,0x40,0x07,0xC0,0x94,0x40,0x57, + 0xC0,0x20,0x00,0x2F,0xE0,0xCA,0xA0,0x4A,0xA0,0x4A,0xA0,0x5F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_220_184_184[45] U8G_FONT_SECTION("fontpage_220_184_184") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB8,0xB8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x48,0x80,0x24,0xE0,0x1F,0x00,0x88,0xE0,0x5E, + 0x20,0x2A,0x40,0x2B,0xE0,0xCA,0x40,0x4A,0x40,0x52,0x40,0x66,0xC0}; +const u8g_fntpgm_uint8_t fontpage_221_144_144[45] U8G_FONT_SECTION("fontpage_221_144_144") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0x90,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x28,0x80,0x8B,0xE0,0x4A,0x20,0x1B, + 0xE0,0x2A,0x20,0x2B,0xE0,0xC8,0x80,0x4A,0xC0,0x54,0xA0,0x69,0xA0}; +const u8g_fntpgm_uint8_t fontpage_221_162_162[45] U8G_FONT_SECTION("fontpage_221_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x40,0x22,0x80,0x0F,0xE0,0x82,0x80,0x44, + 0x40,0x28,0x20,0x3F,0xE0,0xCA,0xA0,0x4A,0xA0,0x4A,0xA0,0x5F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_221_209_209[45] U8G_FONT_SECTION("fontpage_221_209_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xC0,0x24,0x40,0x07,0x40,0x85,0x40,0x5F, + 0xE0,0x34,0x60,0x27,0xC0,0xC4,0x40,0x47,0xC0,0x44,0x40,0x44,0xC0}; +const u8g_fntpgm_uint8_t fontpage_222_143_143[45] U8G_FONT_SECTION("fontpage_222_143_143") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8F,0x8F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x28,0x20,0x0F,0xE0,0x98,0x00,0x5F, + 0xE0,0x29,0x00,0x2F,0xE0,0xCD,0xA0,0x4B,0x60,0x5D,0xA0,0x49,0x60}; +const u8g_fntpgm_uint8_t fontpage_223_192_192[45] U8G_FONT_SECTION("fontpage_223_192_192") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x80,0x3E,0x80,0x12,0xE0,0x9E,0xA0,0x53, + 0xA0,0x3E,0xA0,0x28,0xA0,0xDF,0xA0,0x4A,0x40,0x52,0xA0,0x65,0x20}; +const u8g_fntpgm_uint8_t fontpage_224_239_239[45] U8G_FONT_SECTION("fontpage_224_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x17,0xE0,0x54,0x80,0x58,0x80,0x50, + 0x80,0x90,0x80,0x10,0x80,0x10,0x80,0x28,0x80,0x44,0x80,0x81,0x80}; +const u8g_fntpgm_uint8_t fontpage_225_185_185[45] U8G_FONT_SECTION("fontpage_225_185_185") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB9,0xB9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x07,0xC0,0x04,0x00,0x3F, + 0x80,0x20,0x80,0x20,0x80,0x3F,0x80,0x00,0x00,0x52,0x40,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_225_237_237[45] U8G_FONT_SECTION("fontpage_225_237_237") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xED,0xED,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0xF7,0x80,0x22,0x80,0x32,0x80,0x66, + 0x80,0xA3,0x80,0x24,0xA0,0x68,0x60,0x00,0x00,0x52,0x40,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_228_199_199[45] U8G_FONT_SECTION("fontpage_228_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x21,0x00,0x3F,0xE0,0x20, + 0x00,0x20,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x40,0x80,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_228_233_233[45] U8G_FONT_SECTION("fontpage_228_233_233") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE9,0xE9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0xA2,0x00,0xA7,0xE0,0xFA,0xA0,0xA2, + 0xA0,0x32,0xA0,0x64,0xA0,0xA9,0x20,0x22,0x20,0x25,0x20,0x28,0xC0}; +const u8g_fntpgm_uint8_t fontpage_228_249_249[45] U8G_FONT_SECTION("fontpage_228_249_249") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF9,0xF9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0xA7,0xC0,0xF1,0x00,0xA1,0x00,0xAF, + 0xE0,0x30,0x80,0x6F,0xE0,0xA4,0x80,0x22,0x80,0x20,0x80,0x23,0x80}; +const u8g_fntpgm_uint8_t fontpage_231_135_135[45] U8G_FONT_SECTION("fontpage_231_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x88,0x40,0x52,0x80,0x0C, + 0x00,0x2A,0x80,0xDF,0x40,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_231_175_175[45] U8G_FONT_SECTION("fontpage_231_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x07,0xE0,0xF9,0x00,0x21,0x00,0x23,0x00,0x73, + 0x80,0x25,0x40,0x25,0x20,0x39,0x20,0xC1,0x00,0x01,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_234_168_168[45] U8G_FONT_SECTION("fontpage_234_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x44,0x40,0x44,0x40,0x7F,0xC0,0x44, + 0x40,0x44,0x40,0x7F,0xC0,0x44,0x40,0x44,0x40,0x84,0x40,0x84,0xC0}; +const u8g_fntpgm_uint8_t fontpage_234_181_181[45] U8G_FONT_SECTION("fontpage_234_181_181") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB5,0xB5,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0xFF,0x80,0x88,0x80,0xFF, + 0x80,0x88,0x80,0x88,0x80,0xFF,0x80,0x08,0x40,0x08,0x40,0x07,0xC0}; +const u8g_fntpgm_uint8_t fontpage_234_229_229[45] U8G_FONT_SECTION("fontpage_234_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0xFB,0xC0,0xAE,0x40,0xA9,0x80,0xFA, + 0x40,0xAC,0x20,0xAB,0xC0,0xAA,0x40,0xFA,0x40,0x8B,0xC0,0x02,0x40}; +const u8g_fntpgm_uint8_t fontpage_236_253_253[34] U8G_FONT_SECTION("fontpage_236_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x08,0x0B,0x0B,0x0C,0x02,0xFF,0x10,0x20,0xFF,0x81,0x81,0xFF,0x81,0x81,0x81, + 0xFF,0x81}; +const u8g_fntpgm_uint8_t fontpage_237_132_132[45] U8G_FONT_SECTION("fontpage_237_132_132") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x22,0x00,0x42,0x00,0xF7,0xC0,0x98,0x40,0x90, + 0x40,0xF4,0x40,0x92,0x40,0x92,0x40,0x90,0x40,0xF0,0x40,0x91,0x80}; +const u8g_fntpgm_uint8_t fontpage_237_209_209[45] U8G_FONT_SECTION("fontpage_237_209_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0A,0x00,0x4A,0x00,0x4B,0xE0,0x4A,0x00,0x4C, + 0x80,0x48,0x40,0x08,0x00,0x7F,0xC0,0x4A,0x40,0x4A,0x40,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_237_244_244[45] U8G_FONT_SECTION("fontpage_237_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x04,0x00,0x3F,0x80,0x20, + 0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x20,0x80,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_238_129_129[45] U8G_FONT_SECTION("fontpage_238_129_129") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x81,0x81,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x14,0x80,0x25,0x60,0x46,0x20,0x1F, + 0x80,0x30,0x80,0xDF,0x80,0x10,0x80,0x1F,0x80,0x10,0x80,0x1F,0x80}; +const u8g_fntpgm_uint8_t fontpage_238_160_160[45] U8G_FONT_SECTION("fontpage_238_160_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x07,0xE0,0xF4,0x20,0x97,0xE0,0xF4,0x80,0x94, + 0x80,0x97,0xE0,0xF4,0x80,0x94,0x80,0xF4,0xA0,0x96,0x60,0x04,0x20}; +const u8g_fntpgm_uint8_t fontpage_240_238_238[45] U8G_FONT_SECTION("fontpage_240_238_238") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0xF3,0xC0,0x24,0x80,0x4F,0xE0,0xF5, + 0x20,0x57,0xE0,0x55,0x20,0x57,0xE0,0x75,0x20,0x45,0x20,0x08,0x60}; +const u8g_fntpgm_uint8_t fontpage_243_187_187[45] U8G_FONT_SECTION("fontpage_243_187_187") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBB,0xBB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x2A,0x80,0x24,0x80,0x2A, + 0x80,0x3F,0x80,0x04,0x00,0x7F,0xC0,0x49,0x40,0x5F,0x40,0x40,0xC0}; +const u8g_fntpgm_uint8_t fontpage_243_251_251[45] U8G_FONT_SECTION("fontpage_243_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xE3,0xE0,0x24,0x20,0xFA,0x40,0x21, + 0x80,0x36,0x80,0x29,0xE0,0x62,0x20,0xA5,0x40,0x20,0x80,0x27,0x00}; +const u8g_fntpgm_uint8_t fontpage_244_250_250[45] U8G_FONT_SECTION("fontpage_244_250_250") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFA,0xFA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x89,0x00,0x10, + 0x80,0x60,0x40,0x1F,0x80,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_245_239_239[45] U8G_FONT_SECTION("fontpage_245_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x81,0x00,0x45,0x20,0xF7,0xE0,0x00,0x00,0xAF, + 0xE0,0xA1,0x00,0xAF,0xE0,0x4A,0xA0,0x6A,0xA0,0x8A,0xA0,0x08,0x60}; +const u8g_fntpgm_uint8_t fontpage_246_172_172[45] U8G_FONT_SECTION("fontpage_246_172_172") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x7B,0xE0,0x54,0x80,0xBF,0xC0,0x04, + 0x40,0x7F,0xC0,0x44,0x00,0x7F,0xE0,0x14,0x20,0x24,0xC0,0xC4,0x00}; +const u8g_fntpgm_uint8_t fontpage_246_201_201[45] U8G_FONT_SECTION("fontpage_246_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x7B,0xE0,0x94,0x80,0x7F,0xC0,0x04, + 0x00,0xFF,0xE0,0x01,0x00,0x7F,0xC0,0x11,0x00,0x09,0x00,0x03,0x00}; +const u8g_fntpgm_uint8_t fontpage_247_128_128[45] U8G_FONT_SECTION("fontpage_247_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x7B,0xE0,0x94,0x80,0x27,0xC0,0x50, + 0x40,0x4F,0x40,0x49,0x40,0x4F,0x40,0x49,0x40,0x4F,0x40,0x40,0xC0}; +const u8g_fntpgm_uint8_t fontpage_247_177_177[45] U8G_FONT_SECTION("fontpage_247_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x3D,0xE0,0x4A,0x80,0x94,0x40,0x7F, + 0xC0,0x12,0x40,0x3B,0xC0,0x56,0x40,0x93,0xC0,0x12,0x40,0x13,0xC0}; +const u8g_fntpgm_uint8_t fontpage_248_251_251[45] U8G_FONT_SECTION("fontpage_248_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x80,0x15,0x00,0xFF,0xE0,0x15,0x00,0x24, + 0x80,0x40,0x40,0x04,0x00,0xFF,0xE0,0x0A,0x00,0x11,0x00,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_250_162_162[45] U8G_FONT_SECTION("fontpage_250_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0x91, + 0x20,0x3E,0x00,0x08,0x80,0x7F,0xC0,0x04,0x40,0x24,0x80,0xCC,0x60}; +const u8g_fntpgm_uint8_t fontpage_250_171_171[45] U8G_FONT_SECTION("fontpage_250_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x51,0x40,0x5D,0x80,0x51,0x20,0xFD, + 0xE0,0x08,0x80,0x3F,0x00,0x08,0x80,0x7F,0xC0,0x24,0x80,0xCC,0x60}; +const u8g_fntpgm_uint8_t fontpage_253_162_162[45] U8G_FONT_SECTION("fontpage_253_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xC0,0x41,0x00,0x51,0x00,0xE1, + 0x00,0x21,0x00,0x41,0x00,0xF1,0x00,0x01,0x00,0x31,0x00,0xCF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_253_167_167[45] U8G_FONT_SECTION("fontpage_253_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xC0,0x22,0x40,0x4A,0x40,0x52,0x80,0xE2, + 0xE0,0x22,0x20,0x42,0x20,0xF5,0x40,0x0C,0x80,0x35,0x40,0xCA,0x20}; +const u8g_fntpgm_uint8_t fontpage_253_191_191[45] U8G_FONT_SECTION("fontpage_253_191_191") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x80,0x22,0x40,0x43,0xC0,0x4E,0x00,0xE3, + 0xE0,0x2E,0x00,0x42,0x40,0xF2,0x80,0x09,0x20,0x32,0xA0,0xCC,0x60}; +const u8g_fntpgm_uint8_t fontpage_253_198_198[45] U8G_FONT_SECTION("fontpage_253_198_198") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xE0,0x44,0xA0,0x54,0xA0,0xE4, + 0xA0,0x27,0xE0,0x44,0xA0,0xF4,0xA0,0x04,0xA0,0x37,0xE0,0xC4,0x20}; +const u8g_fntpgm_uint8_t fontpage_253_200_200[45] U8G_FONT_SECTION("fontpage_253_200_200") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xC0,0x54,0x40,0xEA,0x80,0x21, + 0x00,0x42,0x80,0xEC,0x60,0x01,0x00,0x30,0xC0,0xC3,0x00,0x00,0xC0}; +const u8g_fntpgm_uint8_t fontpage_253_211_211[45] U8G_FONT_SECTION("fontpage_253_211_211") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD3,0xD3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x4F,0xE0,0x51,0x00,0xE7, + 0xC0,0x20,0x00,0x47,0xC0,0xF4,0x40,0x0C,0x40,0x37,0xC0,0xC4,0x40}; +const u8g_fntpgm_uint8_t fontpage_253_217_217[45] U8G_FONT_SECTION("fontpage_253_217_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x42,0x80,0x54,0x40,0xE8, + 0x20,0x27,0xC0,0x40,0x00,0xF7,0xC0,0x0C,0x40,0x34,0x40,0xC7,0xC0}; +const u8g_fntpgm_uint8_t fontpage_253_223_223[45] U8G_FONT_SECTION("fontpage_253_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x42,0x00,0x54,0x40,0xEF, + 0xE0,0x22,0xA0,0x42,0x80,0xF2,0x80,0x02,0xA0,0x34,0xA0,0xC8,0xE0}; +const u8g_fntpgm_uint8_t fontpage_253_231_231[45] U8G_FONT_SECTION("fontpage_253_231_231") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE7,0xE7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x80,0x26,0xA0,0x45,0xC0,0x54,0x80,0xE7, + 0xE0,0x24,0x80,0x45,0xC0,0xF6,0xA0,0x04,0x80,0x34,0x80,0xC7,0xE0}; +const u8g_fntpgm_uint8_t fontpage_253_234_234[45] U8G_FONT_SECTION("fontpage_253_234_234") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEA,0xEA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xA0,0x49,0x40,0x57,0xE0,0xE1, + 0x00,0x23,0xE0,0x46,0x20,0xF3,0xE0,0x0A,0x20,0x33,0xE0,0xC2,0x20}; +const u8g_fntpgm_uint8_t fontpage_253_237_237[45] U8G_FONT_SECTION("fontpage_253_237_237") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xED,0xED,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xC0,0x41,0x00,0x57,0xE0,0xE4, + 0xA0,0x2A,0x80,0x44,0x80,0xEF,0xE0,0x01,0x00,0x32,0xC0,0xCC,0x20}; +const u8g_fntpgm_uint8_t fontpage_253_255_255[45] U8G_FONT_SECTION("fontpage_253_255_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x20,0x40,0x43,0xC0,0xF0,0x40,0x2F, + 0xE0,0x41,0x20,0xF5,0x40,0x03,0x80,0x35,0x40,0xC9,0x20,0x03,0x00}; +const u8g_fntpgm_uint8_t fontpage_254_150_150[45] U8G_FONT_SECTION("fontpage_254_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x48,0x20,0x5F,0xE0,0xE8, + 0x00,0x2F,0xE0,0x4A,0xA0,0xFF,0xE0,0x0A,0xA0,0x3A,0xA0,0xC8,0x60}; +const u8g_fntpgm_uint8_t fontpage_254_186_186[45] U8G_FONT_SECTION("fontpage_254_186_186") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBA,0xBA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x41,0x00,0x7B,0xC0,0xA1,0x40,0x21, + 0x40,0xFF,0xE0,0x21,0x00,0xA9,0x00,0xAA,0x80,0xFA,0x40,0x04,0x20}; +const u8g_fntpgm_uint8_t fontpage_254_209_209[45] U8G_FONT_SECTION("fontpage_254_209_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x80,0x40,0x91,0x40,0xD5,0x40,0xA2, + 0x40,0x92,0x40,0xAD,0x40,0xC5,0x40,0x88,0x40,0x80,0x40,0x81,0xC0}; +const u8g_fntpgm_uint8_t fontpage_254_238_238[45] U8G_FONT_SECTION("fontpage_254_238_238") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x4A,0x40,0x7F,0xC0,0x04,0x00,0xFF, + 0xE0,0x20,0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_254_242_242[45] U8G_FONT_SECTION("fontpage_254_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xE0,0x49,0x20,0x7F,0xE0,0x04,0x40,0x3F, + 0x80,0x05,0x00,0xFF,0xE0,0x30,0x80,0xDF,0x80,0x10,0x80,0x1F,0x80}; +const u8g_fntpgm_uint8_t fontpage_256_133_133[45] U8G_FONT_SECTION("fontpage_256_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x3F,0x40,0x04,0x80,0x05,0x00,0xFF, + 0xE0,0x08,0x00,0x3F,0x80,0xD0,0x80,0x1F,0x80,0x10,0x80,0x1F,0x80}; +const u8g_fntpgm_uint8_t fontpage_256_234_234[45] U8G_FONT_SECTION("fontpage_256_234_234") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEA,0xEA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x40,0xFA,0x80,0x57,0xC0,0x54,0x40,0x74, + 0x40,0x57,0xC0,0x71,0x00,0x5A,0xA0,0xF6,0xA0,0x1A,0x40,0x11,0xC0}; +const u8g_fntpgm_uint8_t fontpage_257_253_253[45] U8G_FONT_SECTION("fontpage_257_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x49,0x40,0xFD,0x80,0x01,0x20,0x7D, + 0xE0,0x44,0x00,0x7D,0x40,0x45,0x80,0x7D,0x20,0x45,0x20,0x4D,0xE0}; +const u8g_fntpgm_uint8_t fontpage_259_234_234[34] U8G_FONT_SECTION("fontpage_259_234_234") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEA,0xEA,0x00,0x0A,0xFF,0x00, + 0x00,0x07,0x0B,0x0B,0x0C,0x02,0xFF,0x20,0xFE,0x82,0x82,0xFE,0x82,0xFE,0x82,0x82, + 0xFE,0x82}; +const u8g_fntpgm_uint8_t fontpage_259_243_243[45] U8G_FONT_SECTION("fontpage_259_243_243") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF3,0xF3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x08,0x00,0x11,0x00,0x20,0x80,0x7F, + 0xC0,0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_263_220_220[45] U8G_FONT_SECTION("fontpage_263_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFF,0xE0,0x11,0x00,0x01,0xC0,0x7E, + 0x80,0x28,0x80,0x15,0x00,0xFF,0xE0,0x15,0x00,0x24,0x80,0xC4,0x60}; +const u8g_fntpgm_uint8_t fontpage_265_221_221[45] U8G_FONT_SECTION("fontpage_265_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFF,0xE0,0x11,0x00,0x52,0x00,0x53, + 0xC0,0x55,0x00,0x10,0x80,0x7F,0xC0,0x4A,0x40,0x4A,0x40,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_269_199_199[45] U8G_FONT_SECTION("fontpage_269_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x20,0x80,0x27,0xE0,0xFC,0x20,0xAA, + 0x00,0xAA,0x40,0xFB,0x80,0x22,0x00,0x2A,0x20,0x3A,0x20,0xC9,0xE0}; +const u8g_fntpgm_uint8_t fontpage_272_204_204[45] U8G_FONT_SECTION("fontpage_272_204_204") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x40,0x00,0x80,0x00,0x10,0x00,0x2F, + 0xE0,0x60,0x80,0xA0,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x23,0x80}; +const u8g_fntpgm_uint8_t fontpage_273_171_171[45] U8G_FONT_SECTION("fontpage_273_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x80,0x20,0x80,0xFF,0xE0,0x14,0xA0,0x2C, + 0x80,0x77,0xE0,0xAD,0x40,0x25,0x40,0x24,0x80,0x29,0x40,0x36,0x20}; +const u8g_fntpgm_uint8_t fontpage_273_197_197[45] U8G_FONT_SECTION("fontpage_273_197_197") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC5,0xC5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x9F,0xE0,0x51,0x00,0x31,0x00,0xD7, + 0xC0,0x12,0x00,0xFF,0xE0,0x0C,0x40,0x32,0x80,0xD1,0x00,0x18,0xE0}; +const u8g_fntpgm_uint8_t fontpage_275_129_129[45] U8G_FONT_SECTION("fontpage_275_129_129") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x81,0x81,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x0A,0x00,0x7F,0xC0,0x4A,0x40,0x7F, + 0xC0,0x08,0x00,0xFF,0xE0,0x11,0x00,0x3A,0x00,0x0F,0x00,0x70,0xC0}; +const u8g_fntpgm_uint8_t fontpage_275_210_210[45] U8G_FONT_SECTION("fontpage_275_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x1F,0x00,0x22,0x00,0x7F,0xC0,0xA4, + 0x40,0x3F,0xC0,0x24,0x40,0x3F,0xC0,0x24,0x40,0x45,0x40,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_279_161_161[45] U8G_FONT_SECTION("fontpage_279_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x21,0x00,0x01,0x00,0x0F,0xE0,0xE1, + 0x00,0x21,0x00,0x21,0x00,0x29,0x00,0x31,0x00,0x21,0x00,0x01,0x00}; +const u8g_fntpgm_uint8_t fontpage_279_174_174[45] U8G_FONT_SECTION("fontpage_279_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x21,0x40,0x05,0x40,0x04,0x40,0xE4, + 0x40,0x22,0x80,0x22,0x80,0x29,0x00,0x32,0x80,0x24,0x40,0x08,0x20}; +const u8g_fntpgm_uint8_t fontpage_279_190_190[45] U8G_FONT_SECTION("fontpage_279_190_190") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBE,0xBE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0x80,0x24,0x80,0x04,0x80,0x08,0xE0,0xE0, + 0x00,0x2F,0xC0,0x24,0x40,0x22,0x80,0x31,0x00,0x22,0x80,0x1C,0x60}; +const u8g_fntpgm_uint8_t fontpage_279_213_213[45] U8G_FONT_SECTION("fontpage_279_213_213") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD5,0xD5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x40,0x21,0x20,0x1F,0xE0,0x01,0x00,0xEF, + 0x00,0x25,0x00,0x25,0x00,0x24,0xA0,0x26,0xA0,0x38,0x60,0x20,0x20}; +const u8g_fntpgm_uint8_t fontpage_279_239_239[45] U8G_FONT_SECTION("fontpage_279_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xC0,0x24,0x40,0x04,0x40,0x07,0xC0,0xE0, + 0x00,0x27,0xC0,0x21,0x00,0x2F,0xE0,0x32,0x80,0x24,0x40,0x08,0x20}; +const u8g_fntpgm_uint8_t fontpage_279_247_247[45] U8G_FONT_SECTION("fontpage_279_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x2F,0xE0,0x21,0x00,0x07,0xC0,0xE1, + 0x00,0x2F,0xE0,0x24,0x40,0x27,0xC0,0x24,0x40,0x37,0xC0,0x24,0x40}; +const u8g_fntpgm_uint8_t fontpage_279_251_251[45] U8G_FONT_SECTION("fontpage_279_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x27,0xC0,0x01,0x00,0xEF,0xE0,0x22, + 0xA0,0x25,0x80,0x22,0x80,0x2F,0xE0,0x31,0x80,0x22,0x40,0x0C,0x20}; +const u8g_fntpgm_uint8_t fontpage_280_131_131[45] U8G_FONT_SECTION("fontpage_280_131_131") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x83,0x83,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x29,0x20,0x0B,0xA0,0xE9,0x20,0x2F, + 0xE0,0x28,0x20,0x2B,0xA0,0x2A,0xA0,0x3B,0xA0,0x28,0x20,0x10,0xE0}; +const u8g_fntpgm_uint8_t fontpage_282_165_165[45] U8G_FONT_SECTION("fontpage_282_165_165") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF9,0x00,0x89,0x00,0xA9,0xE0,0xA9,0x40,0xAB, + 0x40,0xAD,0x40,0xA9,0x40,0x21,0x40,0x50,0x80,0x49,0x40,0x8A,0x20}; +const u8g_fntpgm_uint8_t fontpage_282_170_170[45] U8G_FONT_SECTION("fontpage_282_170_170") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAA,0xAA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x35,0x80,0xDF,0x60,0x01, + 0x00,0x3F,0x80,0x24,0x80,0x24,0x80,0x2A,0x80,0x11,0x00,0x60,0xC0}; +const u8g_fntpgm_uint8_t fontpage_282_247_247[45] U8G_FONT_SECTION("fontpage_282_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x13,0xC0,0x7C,0x40,0x10,0x40,0xFF, + 0xC0,0x12,0x00,0x52,0x20,0x5E,0x20,0x53,0xE0,0xB0,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_283_133_133[45] U8G_FONT_SECTION("fontpage_283_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x17,0xC0,0x11,0x40,0x7D,0x40,0x12,0xC0,0xFC, + 0x00,0x13,0xC0,0x5E,0x40,0x52,0x40,0x73,0xC0,0x98,0x00,0x87,0xE0}; +const u8g_fntpgm_uint8_t fontpage_283_221_221[45] U8G_FONT_SECTION("fontpage_283_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7B,0xE0,0x4A,0x00,0x4A,0x00,0x7B,0xE0,0x12, + 0x20,0x52,0x20,0x5A,0x20,0x53,0xE0,0x52,0x00,0x5E,0x00,0xE3,0xE0}; +const u8g_fntpgm_uint8_t fontpage_286_236_236[45] U8G_FONT_SECTION("fontpage_286_236_236") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEC,0xEC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0xF7,0xC0,0x41,0x00,0x6F,0xE0,0xA2, + 0x00,0xF7,0xC0,0x20,0x40,0x3A,0x80,0xE1,0x00,0x20,0x80,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_286_239_239[45] U8G_FONT_SECTION("fontpage_286_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x42,0x00,0xFB,0xE0,0x42,0x20,0xA5, + 0x40,0xF9,0x00,0x21,0x00,0x3A,0x80,0xE2,0x80,0x24,0x40,0x28,0x20}; +const u8g_fntpgm_uint8_t fontpage_286_244_244[45] U8G_FONT_SECTION("fontpage_286_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0xF8,0x80,0x47,0xE0,0x64,0xA0,0xA4, + 0xA0,0xFC,0xA0,0x27,0xE0,0x3C,0xA0,0xE4,0xA0,0x27,0xE0,0x24,0x20}; +const u8g_fntpgm_uint8_t fontpage_286_253_253[45] U8G_FONT_SECTION("fontpage_286_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x7D,0x40,0x11,0x20,0xFF,0xE0,0x21, + 0x00,0xFD,0x20,0x51,0x40,0x7C,0x80,0x10,0xA0,0xFD,0x60,0x12,0x20}; +const u8g_fntpgm_uint8_t fontpage_287_145_145[45] U8G_FONT_SECTION("fontpage_287_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x23,0xC0,0xFA,0x40,0x43,0xC0,0x60,0x00,0xA7, + 0xE0,0xFA,0x40,0x23,0x40,0x3A,0xC0,0xE2,0x60,0x2F,0xC0,0x20,0x40}; +const u8g_fntpgm_uint8_t fontpage_287_147_147[45] U8G_FONT_SECTION("fontpage_287_147_147") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x93,0x93,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x42,0x80,0xF4,0x40,0x4B,0xA0,0xA0, + 0x00,0xFE,0x20,0x2A,0xA0,0x3E,0xA0,0xEA,0xA0,0x2E,0xA0,0x2A,0x60}; +const u8g_fntpgm_uint8_t fontpage_287_185_185[45] U8G_FONT_SECTION("fontpage_287_185_185") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB9,0xB9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x21,0x00,0x2F,0xE0,0x01,0x20,0xE1, + 0x20,0x21,0x20,0x22,0x20,0x24,0x20,0x28,0xC0,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_193_193[45] U8G_FONT_SECTION("fontpage_287_193_193") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC1,0xC1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0xC0,0x27,0x00,0x21,0x00,0x01,0x00,0xEF, + 0xE0,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_208_209[73] U8G_FONT_SECTION("fontpage_287_208_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xC0,0x20,0x00,0x20,0x00,0x0F,0xE0,0xE2, + 0x00,0x22,0x80,0x24,0x40,0x2F,0xA0,0x24,0x20,0x50,0x00,0x8F,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x40,0xC0,0x27,0x00,0x24,0x00,0x07,0xE0,0xE4,0x80,0x24,0x80,0x24, + 0x80,0x24,0x80,0x28,0x80,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_212_212[45] U8G_FONT_SECTION("fontpage_287_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x60,0x27,0x80,0x24,0x00,0x07,0xE0,0xE6, + 0x20,0x25,0x40,0x24,0x80,0x29,0x40,0x26,0x20,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_216_216[45] U8G_FONT_SECTION("fontpage_287_216_216") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x20,0x80,0x21,0x00,0x01,0x00,0xE3, + 0x40,0x25,0x20,0x29,0x20,0x21,0x00,0x21,0x00,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_219_219[45] U8G_FONT_SECTION("fontpage_287_219_219") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDB,0xDB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x80,0x24,0x80,0x2F,0xC0,0x04,0x80,0xE4, + 0x80,0x3F,0xE0,0x24,0x80,0x24,0x80,0x28,0x80,0x50,0x80,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_222_222[45] U8G_FONT_SECTION("fontpage_287_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x2F,0xE0,0x22,0x00,0x05,0x00,0xEF, + 0xC0,0x21,0x00,0x2F,0xE0,0x21,0x00,0x21,0x00,0x51,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_247_247[45] U8G_FONT_SECTION("fontpage_287_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x29,0x20,0x25,0x40,0x01,0x00,0xEF, + 0xE0,0x21,0x00,0x23,0x80,0x25,0x40,0x29,0x20,0x51,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_128_128[45] U8G_FONT_SECTION("fontpage_288_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x8F,0xC0,0x48,0x40,0x4F,0xC0,0x08,0x40,0xCF, + 0xC0,0x48,0x00,0x4B,0x40,0x48,0x80,0x4E,0x40,0xB0,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_137_137[45] U8G_FONT_SECTION("fontpage_288_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x45,0x00,0x25,0x00,0x27,0xC0,0x09,0x00,0xEF, + 0xE0,0x22,0x80,0x22,0xA0,0x24,0xA0,0x28,0x60,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_159_159[45] U8G_FONT_SECTION("fontpage_288_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x3F,0xE0,0x21,0x00,0x0F,0xE0,0xE9, + 0x20,0x2F,0xE0,0x23,0x80,0x25,0x40,0x29,0x20,0x51,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_289_232_232[45] U8G_FONT_SECTION("fontpage_289_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0xE0,0xFF,0x20,0x45,0x20,0x29,0x40,0xFF, + 0x80,0x01,0x40,0x7D,0x20,0x45,0x20,0x45,0xA0,0x7D,0x40,0x45,0x00}; +const u8g_fntpgm_uint8_t fontpage_290_205_205[45] U8G_FONT_SECTION("fontpage_290_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFB,0xE0,0x50,0x20,0x50,0x20,0xF8,0x20,0xAB, + 0xE0,0xDA,0x00,0x8A,0x00,0xFA,0x00,0x8A,0x20,0xFA,0x20,0x8B,0xE0}; +const u8g_fntpgm_uint8_t fontpage_291_202_202[45] U8G_FONT_SECTION("fontpage_291_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x1F,0xC0,0xE2,0x80,0xA9,0x00,0x72,0x80,0xFD, + 0x60,0x31,0x00,0x6F,0xC0,0xA1,0x00,0xAF,0xE0,0x21,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_291_205_205[45] U8G_FONT_SECTION("fontpage_291_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0x24,0x80,0x3F, + 0x80,0x24,0x80,0x3F,0x80,0x04,0x00,0x7F,0xC0,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_291_207_207[45] U8G_FONT_SECTION("fontpage_291_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF, + 0xE0,0x24,0x80,0x3F,0x80,0x24,0x80,0x7F,0xC0,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_297_136_136[45] U8G_FONT_SECTION("fontpage_297_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x80,0x40,0x80,0x78,0x80,0x80,0x80,0xFB, + 0xE0,0x20,0x80,0xF8,0x80,0x20,0x80,0x28,0x80,0x30,0x80,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_297_174_174[45] U8G_FONT_SECTION("fontpage_297_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0x47,0xC0,0x79,0x40,0x81,0x40,0xF9, + 0x40,0x27,0xC0,0xFA,0x40,0x22,0x40,0x2A,0x40,0x32,0x40,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_298_153_153[45] U8G_FONT_SECTION("fontpage_298_153_153") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x99,0x99,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x80,0x4F,0xE0,0x72,0x80,0x82,0x80,0xEF, + 0xE0,0x40,0x00,0xF7,0xC0,0x44,0x40,0x47,0xC0,0x54,0x40,0x67,0xC0}; +const u8g_fntpgm_uint8_t fontpage_298_220_220[45] U8G_FONT_SECTION("fontpage_298_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x4F,0xE0,0x72,0x80,0x8F,0xE0,0xF4, + 0x40,0x27,0xC0,0xF4,0x40,0x27,0xC0,0x2A,0x80,0x32,0xA0,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_298_255_255[45] U8G_FONT_SECTION("fontpage_298_255_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x21,0x00,0x22,0x00,0x24,0x00,0x28,0x00,0x30, + 0x00,0xFF,0xC0,0x28,0x00,0x24,0x00,0x22,0x00,0x29,0x00,0x30,0xC0}; +const u8g_fntpgm_uint8_t fontpage_299_237_237[45] U8G_FONT_SECTION("fontpage_299_237_237") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xED,0xED,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xE0,0x20,0x20,0x82,0x20,0x82,0x20,0xBF, + 0xA0,0x86,0x20,0x8A,0x20,0x92,0x20,0xA2,0x20,0x86,0x20,0x80,0xE0}; +const u8g_fntpgm_uint8_t fontpage_299_242_242[45] U8G_FONT_SECTION("fontpage_299_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x20,0x20,0x84,0x20,0x84,0x20,0xBF, + 0xA0,0x84,0x20,0x8E,0x20,0x95,0x20,0xA4,0xA0,0x84,0x20,0x80,0xE0}; +const u8g_fntpgm_uint8_t fontpage_299_244_244[45] U8G_FONT_SECTION("fontpage_299_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x4F,0xC0,0x20,0x40,0x80,0x40,0x9E,0x40,0x92, + 0x40,0x9E,0x40,0x92,0x40,0x92,0x40,0x9E,0x40,0x80,0x40,0x81,0xC0}; +const u8g_fntpgm_uint8_t fontpage_300_136_136[45] U8G_FONT_SECTION("fontpage_300_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xE0,0x11,0x20,0x82,0xA0,0xBF,0xE0,0x82, + 0x20,0xBA,0xA0,0xAA,0xA0,0xB9,0x20,0x81,0x20,0xBA,0xA0,0x84,0x60}; +const u8g_fntpgm_uint8_t fontpage_300_205_205[45] U8G_FONT_SECTION("fontpage_300_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF2,0x00,0x93,0xE0,0xA6,0x40,0xC1,0x80,0xA6, + 0x60,0x91,0x00,0x97,0xE0,0xD5,0x00,0xAF,0xE0,0x81,0x00,0x81,0x00}; +const u8g_fntpgm_uint8_t fontpage_300_208_208[45] U8G_FONT_SECTION("fontpage_300_208_208") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF7,0xC0,0x94,0x40,0xA7,0xC0,0xC4,0x40,0xA7, + 0xC0,0x95,0x00,0x95,0x20,0xD5,0x40,0xA4,0x80,0x85,0x40,0x86,0x20}; +const u8g_fntpgm_uint8_t fontpage_300_228_228[45] U8G_FONT_SECTION("fontpage_300_228_228") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE4,0xE4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF1,0x00,0x92,0x80,0xA4,0x40,0xCB,0xA0,0xA1, + 0x00,0x9F,0xE0,0x91,0x00,0xE5,0x40,0x89,0x20,0x91,0x20,0x83,0x00}; +const u8g_fntpgm_uint8_t fontpage_300_233_233[45] U8G_FONT_SECTION("fontpage_300_233_233") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE9,0xE9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF1,0x00,0x92,0x80,0xA4,0x40,0xC8,0x20,0xA7, + 0xC0,0x90,0x00,0x9A,0x40,0xD5,0x40,0xA5,0x40,0x80,0x80,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_301_246_246[45] U8G_FONT_SECTION("fontpage_301_246_246") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF6,0xF6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0x95,0x20,0x0E, + 0x00,0x31,0x80,0xC4,0x60,0x3F,0x80,0x01,0x00,0x0E,0x00,0x03,0x00}; +const u8g_fntpgm_uint8_t fontpage_302_128_128[45] U8G_FONT_SECTION("fontpage_302_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0xB5,0xA0,0x04, + 0x00,0xFF,0xE0,0x08,0x00,0x7F,0xC0,0x4A,0x40,0x4A,0x40,0x4A,0xC0}; +const u8g_fntpgm_uint8_t fontpage_302_210_210[45] U8G_FONT_SECTION("fontpage_302_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x04,0x00,0x3F,0x80,0x04, + 0x00,0xFF,0xE0,0x10,0x80,0x1F,0x80,0x10,0x80,0x1F,0x80,0x10,0x80}; +const u8g_fntpgm_uint8_t fontpage_302_222_222[45] U8G_FONT_SECTION("fontpage_302_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0A,0x00,0x0A,0x00,0xFB,0xE0,0x0A,0x00,0x0A, + 0x00,0x7B,0xC0,0x0A,0x00,0x0A,0x00,0xFB,0xE0,0x0A,0x00,0x0A,0x00}; +const u8g_fntpgm_uint8_t fontpage_302_224_224[45] U8G_FONT_SECTION("fontpage_302_224_224") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x00,0x3F,0xC0,0x44,0x00,0xFF,0xE0,0x20, + 0x80,0x3F,0x80,0x0A,0x00,0xFB,0xE0,0x0A,0x00,0xFB,0xE0,0x0A,0x00}; +const u8g_fntpgm_uint8_t fontpage_302_226_226[45] U8G_FONT_SECTION("fontpage_302_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x08,0x00,0x10,0x00,0xFF,0xC0,0x92, + 0x40,0x9E,0x40,0x92,0x40,0x9E,0x40,0x92,0x40,0xFF,0xC0,0x80,0x40}; +const u8g_fntpgm_uint8_t fontpage_304_245_245[45] U8G_FONT_SECTION("fontpage_304_245_245") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF5,0xF5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x04,0x00,0x3F,0x80,0x20,0x80,0x24, + 0x80,0x24,0x80,0x24,0x80,0x26,0x80,0x09,0x00,0x10,0xC0,0x60,0x40}; +const u8g_fntpgm_uint8_t fontpage_304_249_249[45] U8G_FONT_SECTION("fontpage_304_249_249") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF9,0xF9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x07,0xE0,0xF9,0x00,0x27,0xE0,0x24,0x20,0x25, + 0x20,0x25,0x20,0x25,0x20,0x3D,0x20,0xC1,0x80,0x02,0x40,0x0C,0x20}; +const u8g_fntpgm_uint8_t fontpage_305_132_132[45] U8G_FONT_SECTION("fontpage_305_132_132") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFB,0xE0,0x10,0x80,0x63,0xE0,0x22,0x20,0xFA, + 0xA0,0x2A,0xA0,0x22,0xA0,0x22,0xA0,0x22,0xA0,0x21,0x40,0x66,0x20}; +const u8g_fntpgm_uint8_t fontpage_305_145_145[45] U8G_FONT_SECTION("fontpage_305_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x13,0xE0,0x50,0x80,0x5F,0xE0,0x52,0x20,0xFE, + 0xA0,0x12,0xA0,0x56,0xA0,0x5A,0xA0,0x92,0xA0,0x21,0x40,0xC6,0x20}; +const u8g_fntpgm_uint8_t fontpage_305_157_157[45] U8G_FONT_SECTION("fontpage_305_157_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9D,0x9D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x23,0xE0,0xFC,0x80,0x87,0xE0,0x7A,0x20,0xCA, + 0xA0,0x32,0xA0,0x4A,0xA0,0xFE,0xA0,0x4A,0xA0,0x79,0x40,0x4E,0x20}; +const u8g_fntpgm_uint8_t fontpage_305_206_206[45] U8G_FONT_SECTION("fontpage_305_206_206") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCE,0xCE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0x80,0x40,0x80,0x42,0x80,0x52,0x80,0x4C, + 0x80,0x44,0x80,0x4C,0x80,0x52,0x80,0x62,0xA0,0x80,0x60,0x80,0x20}; +const u8g_fntpgm_uint8_t fontpage_306_241_241[45] U8G_FONT_SECTION("fontpage_306_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x00,0x47,0xC0,0x7C,0x40,0x97,0x40,0xAD, + 0x40,0x25,0x40,0x27,0x40,0x24,0xC0,0x2C,0x20,0x34,0x20,0x23,0xE0}; +const u8g_fntpgm_uint8_t fontpage_308_236_236[45] U8G_FONT_SECTION("fontpage_308_236_236") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEC,0xEC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0x80,0x00,0x80,0x10,0x80,0x11,0x00,0x21, + 0x00,0x3F,0xE0,0x00,0x20,0x00,0x20,0xFF,0x20,0x00,0x20,0x00,0xC0}; +const u8g_fntpgm_uint8_t fontpage_308_241_241[45] U8G_FONT_SECTION("fontpage_308_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF3,0xE0,0x12,0x00,0x52,0x20,0x53,0x20,0x52, + 0xA0,0x7A,0x40,0x0A,0x40,0xEA,0xA0,0x0B,0x20,0x0A,0x00,0x33,0xE0}; +const u8g_fntpgm_uint8_t fontpage_309_216_216[45] U8G_FONT_SECTION("fontpage_309_216_216") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x00,0x00,0x1F,0x00,0x11, + 0x00,0x7F,0xC0,0x40,0x40,0x5F,0x40,0x51,0x40,0x5F,0x40,0x40,0xC0}; +const u8g_fntpgm_uint8_t fontpage_317_196_196[45] U8G_FONT_SECTION("fontpage_317_196_196") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC4,0xC4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x7F,0xC0,0x11,0x00,0xFF,0xE0,0x04, + 0x00,0x3F,0x80,0x24,0x80,0x3F,0x80,0x24,0x80,0x3F,0x80,0x60,0xC0}; +const u8g_fntpgm_uint8_t fontpage_317_222_222[45] U8G_FONT_SECTION("fontpage_317_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF8,0x80,0xA8,0x80,0xF8,0xE0,0xA8,0x80,0xF8, + 0x80,0x23,0xE0,0xFA,0x20,0x22,0x20,0xFA,0x20,0x52,0x20,0xAB,0xE0}; +const u8g_fntpgm_uint8_t fontpage_318_208_208[45] U8G_FONT_SECTION("fontpage_318_208_208") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x10,0x80,0x09,0x00,0x06, + 0x00,0x19,0x80,0xE0,0x60,0x09,0x00,0x09,0x00,0x11,0x00,0x61,0x00}; +const u8g_fntpgm_uint8_t fontpage_510_154_154[30] U8G_FONT_SECTION("fontpage_510_154_154") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9A,0x00,0x08,0x00,0x00, + 0x00,0x02,0x07,0x07,0x0C,0x06,0x01,0xC0,0xC0,0x00,0x00,0x00,0xC0,0xC0}; + +static const uxg_fontinfo_t g_fontinfo_zh_CN[] PROGMEM = { + FONTDATA_ITEM(64, 157, 157, fontpage_64_157_157), // '”' -- '”' + FONTDATA_ITEM(69, 191, 191, fontpage_69_191_191), // '⊿' -- '⊿' + FONTDATA_ITEM(156, 128, 128, fontpage_156_128_128), // '一' -- '一' + FONTDATA_ITEM(156, 137, 139, fontpage_156_137_139), // '三' -- '下' + FONTDATA_ITEM(156, 141, 141, fontpage_156_141_141), // '不' -- '不' + FONTDATA_ITEM(156, 147, 147, fontpage_156_147_147), // '专' -- '专' + FONTDATA_ITEM(156, 157, 157, fontpage_156_157_157), // '丝' -- '丝' + FONTDATA_ITEM(156, 170, 170, fontpage_156_170_170), // '个' -- '个' + FONTDATA_ITEM(156, 173, 173, fontpage_156_173_173), // '中' -- '中' + FONTDATA_ITEM(156, 186, 187, fontpage_156_186_187), // '为' -- '主' + FONTDATA_ITEM(156, 201, 201, fontpage_156_201_201), // '义' -- '义' + FONTDATA_ITEM(156, 203, 203, fontpage_156_203_203), // '之' -- '之' + FONTDATA_ITEM(157, 134, 134, fontpage_157_134_134), // '了' -- '了' + FONTDATA_ITEM(157, 140, 140, fontpage_157_140_140), // '二' -- '二' + FONTDATA_ITEM(157, 142, 142, fontpage_157_142_142), // '于' -- '于' + FONTDATA_ITEM(157, 164, 164, fontpage_157_164_164), // '交' -- '交' + FONTDATA_ITEM(157, 174, 174, fontpage_157_174_174), // '亮' -- '亮' + FONTDATA_ITEM(157, 206, 206, fontpage_157_206_206), // '从' -- '从' + FONTDATA_ITEM(157, 228, 229, fontpage_157_228_229), // '令' -- '以' + FONTDATA_ITEM(157, 246, 246, fontpage_157_246_246), // '件' -- '件' + FONTDATA_ITEM(157, 253, 253, fontpage_157_253_253), // '份' -- '份' + FONTDATA_ITEM(158, 145, 145, fontpage_158_145_145), // '休' -- '休' + FONTDATA_ITEM(158, 160, 160, fontpage_158_160_160), // '传' -- '传' + FONTDATA_ITEM(158, 205, 206, fontpage_158_205_206), // '位' -- '低' + FONTDATA_ITEM(158, 211, 211, fontpage_158_211_211), // '体' -- '体' + FONTDATA_ITEM(158, 217, 217, fontpage_158_217_217), // '余' -- '余' + FONTDATA_ITEM(158, 220, 220, fontpage_158_220_220), // '作' -- '作' + FONTDATA_ITEM(158, 255, 255, fontpage_158_255_255), // '使' -- '使' + FONTDATA_ITEM(159, 155, 155, fontpage_159_155_155), // '供' -- '供' + FONTDATA_ITEM(159, 181, 181, fontpage_159_181_181), // '侵' -- '侵' + FONTDATA_ITEM(159, 221, 221, fontpage_159_221_221), // '保' -- '保' + FONTDATA_ITEM(159, 225, 225, fontpage_159_225_225), // '信' -- '信' + FONTDATA_ITEM(160, 188, 188, fontpage_160_188_188), // '值' -- '值' + FONTDATA_ITEM(160, 190, 190, fontpage_160_190_190), // '倾' -- '倾' + FONTDATA_ITEM(160, 207, 207, fontpage_160_207_207), // '偏' -- '偏' + FONTDATA_ITEM(160, 220, 220, fontpage_160_220_220), // '停' -- '停' + FONTDATA_ITEM(161, 168, 168, fontpage_161_168_168), // '储' -- '储' + FONTDATA_ITEM(161, 207, 207, fontpage_161_207_207), // '像' -- '像' + FONTDATA_ITEM(162, 197, 197, fontpage_162_197_197), // '充' -- '充' + FONTDATA_ITEM(162, 200, 201, fontpage_162_200_201), // '先' -- '光' + FONTDATA_ITEM(162, 229, 229, fontpage_162_229_229), // '入' -- '入' + FONTDATA_ITEM(162, 232, 232, fontpage_162_232_232), // '全' -- '全' + FONTDATA_ITEM(162, 241, 241, fontpage_162_241_241), // '共' -- '共' + FONTDATA_ITEM(162, 243, 243, fontpage_162_243_243), // '关' -- '关' + FONTDATA_ITEM(162, 247, 247, fontpage_162_247_247), // '具' -- '具' + FONTDATA_ITEM(163, 151, 151, fontpage_163_151_151), // '冗' -- '冗' + FONTDATA_ITEM(163, 183, 183, fontpage_163_183_183), // '冷' -- '冷' + FONTDATA_ITEM(163, 198, 198, fontpage_163_198_198), // '准' -- '准' + FONTDATA_ITEM(163, 250, 251, fontpage_163_250_251), // '出' -- '击' + FONTDATA_ITEM(164, 134, 135, fontpage_164_134_135), // '分' -- '切' + FONTDATA_ITEM(164, 155, 155, fontpage_164_155_155), // '创' -- '创' + FONTDATA_ITEM(164, 157, 157, fontpage_164_157_157), // '初' -- '初' + FONTDATA_ITEM(164, 171, 171, fontpage_164_171_171), // '别' -- '别' + FONTDATA_ITEM(164, 176, 176, fontpage_164_176_176), // '到' -- '到' + FONTDATA_ITEM(164, 182, 183, fontpage_164_182_183), // '制' -- '刷' + FONTDATA_ITEM(164, 242, 242, fontpage_164_242_242), // '割' -- '割' + FONTDATA_ITEM(165, 155, 155, fontpage_165_155_155), // '力' -- '力' + FONTDATA_ITEM(165, 159, 160, fontpage_165_159_160), // '功' -- '加' + FONTDATA_ITEM(165, 168, 168, fontpage_165_168_168), // '动' -- '动' + FONTDATA_ITEM(166, 150, 150, fontpage_166_150_150), // '化' -- '化' + FONTDATA_ITEM(166, 199, 199, fontpage_166_199_199), // '升' -- '升' + FONTDATA_ITEM(166, 202, 202, fontpage_166_202_202), // '半' -- '半' + FONTDATA_ITEM(166, 207, 207, fontpage_166_207_207), // '协' -- '协' + FONTDATA_ITEM(166, 213, 213, fontpage_166_213_213), // '单' -- '单' + FONTDATA_ITEM(166, 225, 225, fontpage_166_225_225), // '卡' -- '卡' + FONTDATA_ITEM(166, 240, 241, fontpage_166_240_241), // '印' -- '危' + FONTDATA_ITEM(166, 244, 244, fontpage_166_244_244), // '却' -- '却' + FONTDATA_ITEM(166, 248, 248, fontpage_166_248_248), // '卸' -- '卸' + FONTDATA_ITEM(167, 139, 139, fontpage_167_139_139), // '压' -- '压' + FONTDATA_ITEM(167, 159, 159, fontpage_167_159_159), // '原' -- '原' + FONTDATA_ITEM(167, 204, 205, fontpage_167_204_205), // '双' -- '反' + FONTDATA_ITEM(167, 214, 214, fontpage_167_214_214), // '取' -- '取' + FONTDATA_ITEM(167, 216, 216, fontpage_167_216_216), // '变' -- '变' + FONTDATA_ITEM(167, 240, 240, fontpage_167_240_240), // '台' -- '台' + FONTDATA_ITEM(168, 131, 131, fontpage_168_131_131), // '吃' -- '吃' + FONTDATA_ITEM(168, 136, 136, fontpage_168_136_136), // '合' -- '合' + FONTDATA_ITEM(168, 141, 142, fontpage_168_141_142), // '名' -- '后' + FONTDATA_ITEM(168, 145, 145, fontpage_168_145_145), // '向' -- '向' + FONTDATA_ITEM(168, 166, 166, fontpage_168_166_166), // '否' -- '否' + FONTDATA_ITEM(168, 175, 175, fontpage_168_175_175), // '启' -- '启' + FONTDATA_ITEM(168, 202, 202, fontpage_168_202_202), // '告' -- '告' + FONTDATA_ITEM(168, 232, 232, fontpage_168_232_232), // '周' -- '周' + FONTDATA_ITEM(168, 253, 253, fontpage_168_253_253), // '命' -- '命' + FONTDATA_ITEM(169, 140, 140, fontpage_169_140_140), // '和' -- '和' + FONTDATA_ITEM(169, 205, 205, fontpage_169_205_205), // '响' -- '响' + FONTDATA_ITEM(171, 183, 183, fontpage_171_183_183), // '喷' -- '喷' + FONTDATA_ITEM(172, 180, 180, fontpage_172_180_180), // '嘴' -- '嘴' + FONTDATA_ITEM(172, 232, 232, fontpage_172_232_232), // '器' -- '器' + FONTDATA_ITEM(172, 244, 244, fontpage_172_244_244), // '噴' -- '噴' + FONTDATA_ITEM(173, 222, 222, fontpage_173_222_222), // '回' -- '回' + FONTDATA_ITEM(173, 224, 224, fontpage_173_224_224), // '因' -- '因' + FONTDATA_ITEM(173, 250, 250, fontpage_173_250_250), // '固' -- '固' + FONTDATA_ITEM(173, 254, 254, fontpage_173_254_254), // '图' -- '图' + FONTDATA_ITEM(174, 168, 168, fontpage_174_168_168), // '在' -- '在' + FONTDATA_ITEM(174, 207, 207, fontpage_174_207_207), // '坏' -- '坏' + FONTDATA_ITEM(174, 215, 215, fontpage_174_215_215), // '块' -- '块' + FONTDATA_ITEM(175, 139, 139, fontpage_175_139_139), // '型' -- '型' + FONTDATA_ITEM(175, 171, 171, fontpage_175_171_171), // '垫' -- '垫' + FONTDATA_ITEM(176, 235, 235, fontpage_176_235_235), // '填' -- '填' + FONTDATA_ITEM(177, 243, 243, fontpage_177_243_243), // '壳' -- '壳' + FONTDATA_ITEM(178, 135, 135, fontpage_178_135_135), // '备' -- '备' + FONTDATA_ITEM(178, 141, 141, fontpage_178_141_141), // '复' -- '复' + FONTDATA_ITEM(178, 150, 150, fontpage_178_150_150), // '外' -- '外' + FONTDATA_ITEM(178, 154, 154, fontpage_178_154_154), // '多' -- '多' + FONTDATA_ITEM(178, 167, 167, fontpage_178_167_167), // '大' -- '大' + FONTDATA_ITEM(178, 169, 170, fontpage_178_169_170), // '天' -- '太' + FONTDATA_ITEM(178, 177, 177, fontpage_178_177_177), // '失' -- '失' + FONTDATA_ITEM(178, 180, 180, fontpage_178_180_180), // '头' -- '头' + FONTDATA_ITEM(178, 253, 253, fontpage_178_253_253), // '好' -- '好' + FONTDATA_ITEM(179, 203, 203, fontpage_179_203_203), // '始' -- '始' + FONTDATA_ITEM(182, 208, 208, fontpage_182_208_208), // '子' -- '子' + FONTDATA_ITEM(182, 216, 216, fontpage_182_216_216), // '存' -- '存' + FONTDATA_ITEM(183, 137, 137, fontpage_183_137_137), // '安' -- '安' + FONTDATA_ITEM(183, 140, 140, fontpage_183_140_140), // '完' -- '完' + FONTDATA_ITEM(183, 154, 154, fontpage_183_154_154), // '定' -- '定' + FONTDATA_ITEM(183, 162, 162, fontpage_183_162_162), // '客' -- '客' + FONTDATA_ITEM(183, 171, 171, fontpage_183_171_171), // '宫' -- '宫' + FONTDATA_ITEM(183, 249, 249, fontpage_183_249_249), // '对' -- '对' + FONTDATA_ITEM(184, 134, 134, fontpage_184_134_134), // '将' -- '将' + FONTDATA_ITEM(184, 143, 143, fontpage_184_143_143), // '小' -- '小' + FONTDATA_ITEM(184, 177, 177, fontpage_184_177_177), // '就' -- '就' + FONTDATA_ITEM(184, 207, 207, fontpage_184_207_207), // '屏' -- '屏' + FONTDATA_ITEM(187, 229, 229, fontpage_187_229_229), // '工' -- '工' + FONTDATA_ITEM(187, 238, 238, fontpage_187_238_238), // '差' -- '差' + FONTDATA_ITEM(187, 242, 242, fontpage_187_242_242), // '已' -- '已' + FONTDATA_ITEM(188, 243, 243, fontpage_188_243_243), // '平' -- '平' + FONTDATA_ITEM(188, 246, 246, fontpage_188_246_246), // '并' -- '并' + FONTDATA_ITEM(189, 138, 138, fontpage_189_138_138), // '床' -- '床' + FONTDATA_ITEM(189, 148, 148, fontpage_189_148_148), // '应' -- '应' + FONTDATA_ITEM(189, 159, 159, fontpage_189_159_159), // '废' -- '废' + FONTDATA_ITEM(189, 166, 166, fontpage_189_166_166), // '度' -- '度' + FONTDATA_ITEM(190, 128, 128, fontpage_190_128_128), // '开' -- '开' + FONTDATA_ITEM(190, 131, 131, fontpage_190_131_131), // '弃' -- '弃' + FONTDATA_ITEM(190, 143, 143, fontpage_190_143_143), // '式' -- '式' + FONTDATA_ITEM(190, 149, 149, fontpage_190_149_149), // '引' -- '引' + FONTDATA_ITEM(190, 185, 185, fontpage_190_185_185), // '弹' -- '弹' + FONTDATA_ITEM(190, 210, 210, fontpage_190_210_210), // '归' -- '归' + FONTDATA_ITEM(191, 132, 133, fontpage_191_132_133), // '径' -- '待' + FONTDATA_ITEM(191, 170, 170, fontpage_191_170_170), // '循' -- '循' + FONTDATA_ITEM(191, 174, 174, fontpage_191_174_174), // '微' -- '微' + FONTDATA_ITEM(191, 195, 195, fontpage_191_195_195), // '心' -- '心' + FONTDATA_ITEM(191, 253, 253, fontpage_191_253_253), // '忽' -- '忽' + FONTDATA_ITEM(192, 167, 167, fontpage_192_167_167), // '性' -- '性' + FONTDATA_ITEM(192, 187, 187, fontpage_192_187_187), // '总' -- '总' + FONTDATA_ITEM(192, 226, 226, fontpage_192_226_226), // '恢' -- '恢' + FONTDATA_ITEM(192, 239, 239, fontpage_192_239_239), // '息' -- '息' + FONTDATA_ITEM(194, 159, 159, fontpage_194_159_159), // '感' -- '感' + FONTDATA_ITEM(196, 143, 144, fontpage_196_143_144), // '戏' -- '成' + FONTDATA_ITEM(196, 183, 183, fontpage_196_183_183), // '户' -- '户' + FONTDATA_ITEM(196, 192, 192, fontpage_196_192_192), // '所' -- '所' + FONTDATA_ITEM(196, 199, 199, fontpage_196_199_199), // '扇' -- '扇' + FONTDATA_ITEM(196, 203, 203, fontpage_196_203_203), // '手' -- '手' + FONTDATA_ITEM(196, 211, 211, fontpage_196_211_211), // '打' -- '打' + FONTDATA_ITEM(196, 231, 231, fontpage_196_231_231), // '执' -- '执' + FONTDATA_ITEM(196, 249, 249, fontpage_196_249_249), // '批' -- '批' + FONTDATA_ITEM(197, 150, 150, fontpage_197_150_150), // '抖' -- '抖' + FONTDATA_ITEM(197, 165, 165, fontpage_197_165_165), // '报' -- '报' + FONTDATA_ITEM(197, 172, 172, fontpage_197_172_172), // '抬' -- '抬' + FONTDATA_ITEM(197, 189, 189, fontpage_197_189_189), // '抽' -- '抽' + FONTDATA_ITEM(197, 212, 212, fontpage_197_212_212), // '拔' -- '拔' + FONTDATA_ITEM(197, 233, 233, fontpage_197_233_233), // '择' -- '择' + FONTDATA_ITEM(198, 137, 137, fontpage_198_137_137), // '按' -- '按' + FONTDATA_ITEM(198, 161, 161, fontpage_198_161_161), // '挡' -- '挡' + FONTDATA_ITEM(198, 164, 164, fontpage_198_164_164), // '挤' -- '挤' + FONTDATA_ITEM(198, 223, 223, fontpage_198_223_223), // '损' -- '损' + FONTDATA_ITEM(198, 226, 226, fontpage_198_226_226), // '换' -- '换' + FONTDATA_ITEM(199, 137, 137, fontpage_199_137_137), // '掉' -- '掉' + FONTDATA_ITEM(199, 162, 162, fontpage_199_162_162), // '探' -- '探' + FONTDATA_ITEM(199, 165, 165, fontpage_199_165_165), // '接' -- '接' + FONTDATA_ITEM(199, 167, 167, fontpage_199_167_167), // '控' -- '控' + FONTDATA_ITEM(199, 208, 208, fontpage_199_208_208), // '提' -- '提' + FONTDATA_ITEM(199, 210, 210, fontpage_199_210_210), // '插' -- '插' + FONTDATA_ITEM(202, 182, 182, fontpage_202_182_182), // '收' -- '收' + FONTDATA_ITEM(202, 190, 190, fontpage_202_190_190), // '放' -- '放' + FONTDATA_ITEM(202, 240, 240, fontpage_202_240_240), // '数' -- '数' + FONTDATA_ITEM(202, 242, 242, fontpage_202_242_242), // '敲' -- '敲' + FONTDATA_ITEM(202, 244, 244, fontpage_202_244_244), // '整' -- '整' + FONTDATA_ITEM(203, 135, 135, fontpage_203_135_135), // '文' -- '文' + FONTDATA_ITEM(203, 153, 153, fontpage_203_153_153), // '料' -- '料' + FONTDATA_ITEM(203, 156, 156, fontpage_203_156_156), // '斜' -- '斜' + FONTDATA_ITEM(203, 173, 173, fontpage_203_173_173), // '断' -- '断' + FONTDATA_ITEM(203, 176, 176, fontpage_203_176_176), // '新' -- '新' + FONTDATA_ITEM(203, 185, 185, fontpage_203_185_185), // '方' -- '方' + FONTDATA_ITEM(203, 224, 224, fontpage_203_224_224), // '无' -- '无' + FONTDATA_ITEM(203, 246, 246, fontpage_203_246_246), // '时' -- '时' + FONTDATA_ITEM(204, 142, 142, fontpage_204_142_142), // '明' -- '明' + FONTDATA_ITEM(204, 175, 175, fontpage_204_175_175), // '是' -- '是' + FONTDATA_ITEM(205, 130, 130, fontpage_205_130_130), // '暂' -- '暂' + FONTDATA_ITEM(205, 171, 171, fontpage_205_171_171), // '暫' -- '暫' + FONTDATA_ITEM(205, 244, 244, fontpage_205_244_244), // '更' -- '更' + FONTDATA_ITEM(206, 128, 128, fontpage_206_128_128), // '最' -- '最' + FONTDATA_ITEM(206, 137, 137, fontpage_206_137_137), // '有' -- '有' + FONTDATA_ITEM(206, 159, 159, fontpage_206_159_159), // '期' -- '期' + FONTDATA_ITEM(206, 186, 186, fontpage_206_186_186), // '机' -- '机' + FONTDATA_ITEM(206, 192, 192, fontpage_206_192_192), // '杀' -- '杀' + FONTDATA_ITEM(206, 223, 223, fontpage_206_223_223), // '束' -- '束' + FONTDATA_ITEM(206, 225, 225, fontpage_206_225_225), // '条' -- '条' + FONTDATA_ITEM(206, 229, 229, fontpage_206_229_229), // '来' -- '来' + FONTDATA_ITEM(206, 255, 255, fontpage_206_255_255), // '板' -- '板' + FONTDATA_ITEM(207, 151, 151, fontpage_207_151_151), // '林' -- '林' + FONTDATA_ITEM(207, 241, 241, fontpage_207_241_241), // '柱' -- '柱' + FONTDATA_ITEM(208, 161, 161, fontpage_208_161_161), // '校' -- '校' + FONTDATA_ITEM(208, 188, 188, fontpage_208_188_188), // '格' -- '格' + FONTDATA_ITEM(209, 175, 175, fontpage_209_175_175), // '梯' -- '梯' + FONTDATA_ITEM(209, 192, 192, fontpage_209_192_192), // '检' -- '检' + FONTDATA_ITEM(211, 253, 253, fontpage_211_253_253), // '槽' -- '槽' + FONTDATA_ITEM(212, 161, 161, fontpage_212_161_161), // '模' -- '模' + FONTDATA_ITEM(212, 217, 217, fontpage_212_217_217), // '橙' -- '橙' + FONTDATA_ITEM(214, 226, 227, fontpage_214_226_227), // '止' -- '正' + FONTDATA_ITEM(214, 229, 229, fontpage_214_229_229), // '步' -- '步' + FONTDATA_ITEM(215, 212, 212, fontpage_215_212_212), // '比' -- '比' + FONTDATA_ITEM(217, 161, 161, fontpage_217_161_161), // '没' -- '没' + FONTDATA_ITEM(217, 226, 226, fontpage_217_226_226), // '波' -- '波' + FONTDATA_ITEM(217, 232, 232, fontpage_217_232_232), // '注' -- '注' + FONTDATA_ITEM(218, 151, 151, fontpage_218_151_151), // '洗' -- '洗' + FONTDATA_ITEM(218, 187, 187, fontpage_218_187_187), // '活' -- '活' + FONTDATA_ITEM(218, 193, 193, fontpage_218_193_193), // '流' -- '流' + FONTDATA_ITEM(218, 203, 203, fontpage_218_203_203), // '测' -- '测' + FONTDATA_ITEM(219, 136, 136, fontpage_219_136_136), // '消' -- '消' + FONTDATA_ITEM(219, 225, 225, fontpage_219_225_225), // '淡' -- '淡' + FONTDATA_ITEM(219, 247, 247, fontpage_219_247_247), // '混' -- '混' + FONTDATA_ITEM(220, 133, 133, fontpage_220_133_133), // '清' -- '清' + FONTDATA_ITEM(220, 169, 169, fontpage_220_169_169), // '温' -- '温' + FONTDATA_ITEM(220, 184, 184, fontpage_220_184_184), // '游' -- '游' + FONTDATA_ITEM(221, 144, 144, fontpage_221_144_144), // '源' -- '源' + FONTDATA_ITEM(221, 162, 162, fontpage_221_162_162), // '溢' -- '溢' + FONTDATA_ITEM(221, 209, 209, fontpage_221_209_209), // '滑' -- '滑' + FONTDATA_ITEM(222, 143, 143, fontpage_222_143_143), // '漏' -- '漏' + FONTDATA_ITEM(223, 192, 192, fontpage_223_192_192), // '激' -- '激' + FONTDATA_ITEM(224, 239, 239, fontpage_224_239_239), // '灯' -- '灯' + FONTDATA_ITEM(225, 185, 185, fontpage_225_185_185), // '点' -- '点' + FONTDATA_ITEM(225, 237, 237, fontpage_225_237_237), // '热' -- '热' + FONTDATA_ITEM(228, 199, 199, fontpage_228_199_199), // '片' -- '片' + FONTDATA_ITEM(228, 233, 233, fontpage_228_233_233), // '物' -- '物' + FONTDATA_ITEM(228, 249, 249, fontpage_228_249_249), // '特' -- '特' + FONTDATA_ITEM(231, 135, 135, fontpage_231_135_135), // '率' -- '率' + FONTDATA_ITEM(231, 175, 175, fontpage_231_175_175), // '环' -- '环' + FONTDATA_ITEM(234, 168, 168, fontpage_234_168_168), // '用' -- '用' + FONTDATA_ITEM(234, 181, 181, fontpage_234_181_181), // '电' -- '电' + FONTDATA_ITEM(234, 229, 229, fontpage_234_229_229), // '略' -- '略' + FONTDATA_ITEM(236, 253, 253, fontpage_236_253_253), // '白' -- '白' + FONTDATA_ITEM(237, 132, 132, fontpage_237_132_132), // '的' -- '的' + FONTDATA_ITEM(237, 209, 209, fontpage_237_209_209), // '监' -- '监' + FONTDATA_ITEM(237, 244, 244, fontpage_237_244_244), // '直' -- '直' + FONTDATA_ITEM(238, 129, 129, fontpage_238_129_129), // '省' -- '省' + FONTDATA_ITEM(238, 160, 160, fontpage_238_160_160), // '眠' -- '眠' + FONTDATA_ITEM(240, 238, 238, fontpage_240_238_238), // '确' -- '确' + FONTDATA_ITEM(243, 187, 187, fontpage_243_187_187), // '离' -- '离' + FONTDATA_ITEM(243, 251, 251, fontpage_243_251_251), // '移' -- '移' + FONTDATA_ITEM(244, 250, 250, fontpage_244_250_250), // '空' -- '空' + FONTDATA_ITEM(245, 239, 239, fontpage_245_239_239), // '端' -- '端' + FONTDATA_ITEM(246, 172, 172, fontpage_246_172_172), // '第' -- '第' + FONTDATA_ITEM(246, 201, 201, fontpage_246_201_201), // '等' -- '等' + FONTDATA_ITEM(247, 128, 128, fontpage_247_128_128), // '简' -- '简' + FONTDATA_ITEM(247, 177, 177, fontpage_247_177_177), // '箱' -- '箱' + FONTDATA_ITEM(248, 251, 251, fontpage_248_251_251), // '类' -- '类' + FONTDATA_ITEM(250, 162, 162, fontpage_250_162_162), // '索' -- '索' + FONTDATA_ITEM(250, 171, 171, fontpage_250_171_171), // '紫' -- '紫' + FONTDATA_ITEM(253, 162, 162, fontpage_253_162_162), // '红' -- '红' + FONTDATA_ITEM(253, 167, 167, fontpage_253_167_167), // '级' -- '级' + FONTDATA_ITEM(253, 191, 191, fontpage_253_191_191), // '线' -- '线' + FONTDATA_ITEM(253, 198, 198, fontpage_253_198_198), // '细' -- '细' + FONTDATA_ITEM(253, 200, 200, fontpage_253_200_200), // '终' -- '终' + FONTDATA_ITEM(253, 211, 211, fontpage_253_211_211), // '结' -- '结' + FONTDATA_ITEM(253, 217, 217, fontpage_253_217_217), // '给' -- '给' + FONTDATA_ITEM(253, 223, 223, fontpage_253_223_223), // '统' -- '统' + FONTDATA_ITEM(253, 231, 231, fontpage_253_231_231), // '继' -- '继' + FONTDATA_ITEM(253, 234, 234, fontpage_253_234_234), // '绪' -- '绪' + FONTDATA_ITEM(253, 237, 237, fontpage_253_237_237), // '续' -- '续' + FONTDATA_ITEM(253, 255, 255, fontpage_253_255_255), // '绿' -- '绿' + FONTDATA_ITEM(254, 150, 150, fontpage_254_150_150), // '编' -- '编' + FONTDATA_ITEM(254, 186, 186, fontpage_254_186_186), // '缺' -- '缺' + FONTDATA_ITEM(254, 209, 209, fontpage_254_209_209), // '网' -- '网' + FONTDATA_ITEM(254, 238, 238, fontpage_254_238_238), // '置' -- '置' + FONTDATA_ITEM(254, 242, 242, fontpage_254_242_242), // '署' -- '署' + FONTDATA_ITEM(256, 133, 133, fontpage_256_133_133), // '者' -- '者' + FONTDATA_ITEM(256, 234, 234, fontpage_256_234_234), // '聪' -- '聪' + FONTDATA_ITEM(257, 253, 253, fontpage_257_253_253), // '能' -- '能' + FONTDATA_ITEM(259, 234, 234, fontpage_259_234_234), // '自' -- '自' + FONTDATA_ITEM(259, 243, 243, fontpage_259_243_243), // '至' -- '至' + FONTDATA_ITEM(263, 220, 220, fontpage_263_220_220), // '菜' -- '菜' + FONTDATA_ITEM(265, 221, 221, fontpage_265_221_221), // '蓝' -- '蓝' + FONTDATA_ITEM(269, 199, 199, fontpage_269_199_199), // '蛇' -- '蛇' + FONTDATA_ITEM(272, 204, 204, fontpage_272_204_204), // '行' -- '行' + FONTDATA_ITEM(273, 171, 171, fontpage_273_171_171), // '被' -- '被' + FONTDATA_ITEM(273, 197, 197, fontpage_273_197_197), // '装' -- '装' + FONTDATA_ITEM(275, 129, 129, fontpage_275_129_129), // '要' -- '要' + FONTDATA_ITEM(275, 210, 210, fontpage_275_210_210), // '角' -- '角' + FONTDATA_ITEM(279, 161, 161, fontpage_279_161_161), // '计' -- '计' + FONTDATA_ITEM(279, 174, 174, fontpage_279_174_174), // '议' -- '议' + FONTDATA_ITEM(279, 190, 190, fontpage_279_190_190), // '设' -- '设' + FONTDATA_ITEM(279, 213, 213, fontpage_279_213_213), // '试' -- '试' + FONTDATA_ITEM(279, 239, 239, fontpage_279_239_239), // '误' -- '误' + FONTDATA_ITEM(279, 247, 247, fontpage_279_247_247), // '请' -- '请' + FONTDATA_ITEM(279, 251, 251, fontpage_279_251_251), // '读' -- '读' + FONTDATA_ITEM(280, 131, 131, fontpage_280_131_131), // '调' -- '调' + FONTDATA_ITEM(282, 165, 165, fontpage_282_165_165), // '败' -- '败' + FONTDATA_ITEM(282, 170, 170, fontpage_282_170_170), // '贪' -- '贪' + FONTDATA_ITEM(282, 247, 247, fontpage_282_247_247), // '起' -- '起' + FONTDATA_ITEM(283, 133, 133, fontpage_283_133_133), // '超' -- '超' + FONTDATA_ITEM(283, 221, 221, fontpage_283_221_221), // '距' -- '距' + FONTDATA_ITEM(286, 236, 236, fontpage_286_236_236), // '转' -- '转' + FONTDATA_ITEM(286, 239, 239, fontpage_286_239_239), // '软' -- '软' + FONTDATA_ITEM(286, 244, 244, fontpage_286_244_244), // '轴' -- '轴' + FONTDATA_ITEM(286, 253, 253, fontpage_286_253_253), // '载' -- '载' + FONTDATA_ITEM(287, 145, 145, fontpage_287_145_145), // '辑' -- '辑' + FONTDATA_ITEM(287, 147, 147, fontpage_287_147_147), // '输' -- '输' + FONTDATA_ITEM(287, 185, 185, fontpage_287_185_185), // '边' -- '边' + FONTDATA_ITEM(287, 193, 193, fontpage_287_193_193), // '迁' -- '迁' + FONTDATA_ITEM(287, 208, 209, fontpage_287_208_209), // '运' -- '近' + FONTDATA_ITEM(287, 212, 212, fontpage_287_212_212), // '返' -- '返' + FONTDATA_ITEM(287, 216, 216, fontpage_287_216_216), // '还' -- '还' + FONTDATA_ITEM(287, 219, 219, fontpage_287_219_219), // '进' -- '进' + FONTDATA_ITEM(287, 222, 222, fontpage_287_222_222), // '连' -- '连' + FONTDATA_ITEM(287, 247, 247, fontpage_287_247_247), // '迷' -- '迷' + FONTDATA_ITEM(288, 128, 128, fontpage_288_128_128), // '退' -- '退' + FONTDATA_ITEM(288, 137, 137, fontpage_288_137_137), // '选' -- '选' + FONTDATA_ITEM(288, 159, 159, fontpage_288_159_159), // '速' -- '速' + FONTDATA_ITEM(289, 232, 232, fontpage_289_232_232), // '部' -- '部' + FONTDATA_ITEM(290, 205, 205, fontpage_290_205_205), // '配' -- '配' + FONTDATA_ITEM(291, 202, 202, fontpage_291_202_202), // '释' -- '释' + FONTDATA_ITEM(291, 205, 205, fontpage_291_205_205), // '重' -- '重' + FONTDATA_ITEM(291, 207, 207, fontpage_291_207_207), // '量' -- '量' + FONTDATA_ITEM(297, 136, 136, fontpage_297_136_136), // '针' -- '针' + FONTDATA_ITEM(297, 174, 174, fontpage_297_174_174), // '钮' -- '钮' + FONTDATA_ITEM(298, 153, 153, fontpage_298_153_153), // '错' -- '错' + FONTDATA_ITEM(298, 220, 220, fontpage_298_220_220), // '镜' -- '镜' + FONTDATA_ITEM(298, 255, 255, fontpage_298_255_255), // '长' -- '长' + FONTDATA_ITEM(299, 237, 237, fontpage_299_237_237), // '闭' -- '闭' + FONTDATA_ITEM(299, 242, 242, fontpage_299_242_242), // '闲' -- '闲' + FONTDATA_ITEM(299, 244, 244, fontpage_299_244_244), // '间' -- '间' + FONTDATA_ITEM(300, 136, 136, fontpage_300_136_136), // '阈' -- '阈' + FONTDATA_ITEM(300, 205, 205, fontpage_300_205_205), // '降' -- '降' + FONTDATA_ITEM(300, 208, 208, fontpage_300_208_208), // '限' -- '限' + FONTDATA_ITEM(300, 228, 228, fontpage_300_228_228), // '除' -- '除' + FONTDATA_ITEM(300, 233, 233, fontpage_300_233_233), // '险' -- '险' + FONTDATA_ITEM(301, 246, 246, fontpage_301_246_246), // '零' -- '零' + FONTDATA_ITEM(302, 128, 128, fontpage_302_128_128), // '需' -- '需' + FONTDATA_ITEM(302, 210, 210, fontpage_302_210_210), // '青' -- '青' + FONTDATA_ITEM(302, 222, 222, fontpage_302_222_222), // '非' -- '非' + FONTDATA_ITEM(302, 224, 224, fontpage_302_224_224), // '靠' -- '靠' + FONTDATA_ITEM(302, 226, 226, fontpage_302_226_226), // '面' -- '面' + FONTDATA_ITEM(304, 245, 245, fontpage_304_245_245), // '页' -- '页' + FONTDATA_ITEM(304, 249, 249, fontpage_304_249_249), // '项' -- '项' + FONTDATA_ITEM(305, 132, 132, fontpage_305_132_132), // '预' -- '预' + FONTDATA_ITEM(305, 145, 145, fontpage_305_145_145), // '频' -- '频' + FONTDATA_ITEM(305, 157, 157, fontpage_305_157_157), // '额' -- '额' + FONTDATA_ITEM(305, 206, 206, fontpage_305_206_206), // '风' -- '风' + FONTDATA_ITEM(306, 241, 241, fontpage_306_241_241), // '饱' -- '饱' + FONTDATA_ITEM(308, 236, 236, fontpage_308_236_236), // '马' -- '马' + FONTDATA_ITEM(308, 241, 241, fontpage_308_241_241), // '驱' -- '驱' + FONTDATA_ITEM(309, 216, 216, fontpage_309_216_216), // '高' -- '高' + FONTDATA_ITEM(317, 196, 196, fontpage_317_196_196), // '黄' -- '黄' + FONTDATA_ITEM(317, 222, 222, fontpage_317_222_222), // '點' -- '點' + FONTDATA_ITEM(318, 208, 208, fontpage_318_208_208), // '齐' -- '齐' + FONTDATA_ITEM(510, 154, 154, fontpage_510_154_154), // ':' -- ':' +}; diff --git a/src/lcd/dogm/fontdata/langdata_zh_TW.h b/src/lcd/dogm/fontdata/langdata_zh_TW.h new file mode 100644 index 0000000..093629c --- /dev/null +++ b/src/lcd/dogm/fontdata/langdata_zh_TW.h @@ -0,0 +1,1522 @@ +/** + * Generated automatically by buildroot/share/fonts/uxggenpages.sh + * Contents will be REPLACED by future processing! + * Use genallfont.sh to generate font data for updated languages. + */ +#pragma once + +#include "langdata.h" + +const u8g_fntpgm_uint8_t fontpage_69_191_191[28] U8G_FONT_SECTION("fontpage_69_191_191") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x00,0x05,0x00,0x00, + 0x00,0x05,0x05,0x05,0x06,0x00,0x00,0x08,0x18,0x28,0x48,0xF8}; +const u8g_fntpgm_uint8_t fontpage_156_128_128[27] U8G_FONT_SECTION("fontpage_156_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x06,0x00,0x00, + 0x00,0x0B,0x02,0x04,0x0C,0x00,0x04,0x00,0x40,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_156_137_139[97] U8G_FONT_SECTION("fontpage_156_137_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x3F, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xE0,0x0B,0x0B,0x16,0x0C,0x00, + 0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x07,0xC0,0x04,0x00,0x04,0x00,0x04, + 0x00,0x04,0x00,0x04,0x00,0xFF,0xE0,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0xFF,0xE0,0x04, + 0x00,0x04,0x00,0x06,0x00,0x05,0x00,0x04,0x80,0x04,0x80,0x04,0x00,0x04,0x00,0x04, + 0x00}; +const u8g_fntpgm_uint8_t fontpage_156_141_141[45] U8G_FONT_SECTION("fontpage_156_141_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x02,0x00,0x02,0x00,0x04,0x00,0x0D, + 0x00,0x14,0x80,0x24,0x40,0x44,0x20,0x84,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_156_166_166[45] U8G_FONT_SECTION("fontpage_156_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x11,0x00,0xFF,0xE0,0x0A,0x00,0x4A, + 0x40,0x4A,0x40,0x2A,0x40,0x2A,0x80,0x0A,0x00,0x0A,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_156_173_173[45] U8G_FONT_SECTION("fontpage_156_173_173") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAD,0xAD,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0xFF,0x80,0x88,0x80,0x88, + 0x80,0x88,0x80,0xFF,0x80,0x88,0x80,0x08,0x00,0x08,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_156_187_187[45] U8G_FONT_SECTION("fontpage_156_187_187") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBB,0xBB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04, + 0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_156_203_203[45] U8G_FONT_SECTION("fontpage_156_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x04,0x00,0x7F,0xC0,0x00,0x80,0x01, + 0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x30,0x00,0x48,0x00,0x87,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_164_164[45] U8G_FONT_SECTION("fontpage_157_164_164") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x00,0x00,0x11,0x00,0x20, + 0x80,0x51,0x40,0x11,0x00,0x0A,0x00,0x04,0x00,0x1B,0x00,0x60,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_174_174[45] U8G_FONT_SECTION("fontpage_157_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x11,0x00,0x1F,0x00,0x00, + 0x00,0xFF,0xE0,0x80,0x20,0x1F,0x00,0x11,0x00,0x21,0x20,0xC0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_157_228_228[45] U8G_FONT_SECTION("fontpage_157_228_228") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE4,0xE4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x24, + 0x80,0xC2,0x60,0x3F,0x80,0x01,0x00,0x0A,0x00,0x04,0x00,0x02,0x00}; +const u8g_fntpgm_uint8_t fontpage_157_246_246[45] U8G_FONT_SECTION("fontpage_157_246_246") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF6,0xF6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x15,0x00,0x25,0x00,0x2F,0xC0,0x71, + 0x00,0xA1,0x00,0x2F,0xE0,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_157_253_253[45] U8G_FONT_SECTION("fontpage_157_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x80,0x12,0x80,0x22,0x40,0x24,0x40,0x68, + 0x20,0xA7,0xC0,0x22,0x40,0x22,0x40,0x22,0x40,0x24,0x40,0x28,0xC0}; +const u8g_fntpgm_uint8_t fontpage_158_145_145[45] U8G_FONT_SECTION("fontpage_158_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x21,0x00,0x3F,0xE0,0x61, + 0x00,0xA3,0x80,0x23,0x80,0x25,0x40,0x29,0x20,0x31,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_158_205_206[73] U8G_FONT_SECTION("fontpage_158_205_206") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x11,0x00,0x20,0x00,0x2F,0xE0,0x60, + 0x00,0xA4,0x40,0x22,0x40,0x22,0x80,0x20,0x80,0x21,0x00,0x2F,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x10,0xC0,0x1F,0x00,0x29,0x00,0x29,0x00,0x69,0x00,0xAF,0xE0,0x29, + 0x00,0x29,0x20,0x2A,0xA0,0x2D,0x60,0x28,0xA0}; +const u8g_fntpgm_uint8_t fontpage_158_220_220[45] U8G_FONT_SECTION("fontpage_158_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x14,0x00,0x14,0x00,0x27,0xE0,0x2A,0x00,0x72, + 0x00,0xA3,0xC0,0x22,0x00,0x22,0x00,0x23,0xE0,0x22,0x00,0x22,0x00}; +const u8g_fntpgm_uint8_t fontpage_159_155_155[45] U8G_FONT_SECTION("fontpage_159_155_155") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9B,0x9B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x14,0x80,0x14,0x80,0x24,0x80,0x2F,0xE0,0x64, + 0x80,0xA4,0x80,0x3F,0xE0,0x20,0x00,0x24,0x80,0x28,0x40,0x30,0x20}; +const u8g_fntpgm_uint8_t fontpage_159_221_221[45] U8G_FONT_SECTION("fontpage_159_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x17,0xC0,0x14,0x40,0x24,0x40,0x27,0xC0,0x61, + 0x00,0xAF,0xE0,0x21,0x00,0x23,0x80,0x25,0x40,0x29,0x20,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_159_225_225[45] U8G_FONT_SECTION("fontpage_159_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x11,0x00,0x2F,0xE0,0x20,0x00,0x67, + 0xC0,0xA0,0x00,0x27,0xC0,0x20,0x00,0x27,0xC0,0x24,0x40,0x27,0xC0}; +const u8g_fntpgm_uint8_t fontpage_160_139_139[45] U8G_FONT_SECTION("fontpage_160_139_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8B,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xE0,0x29,0x20,0x29,0x20,0x2F,0xE0,0x69, + 0x20,0xAB,0xA0,0x2A,0xA0,0x2B,0xA0,0x28,0x20,0x2F,0xE0,0x28,0x20}; +const u8g_fntpgm_uint8_t fontpage_160_188_188[45] U8G_FONT_SECTION("fontpage_160_188_188") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x1F,0xE0,0x22,0x00,0x27,0xC0,0x64, + 0x40,0xA7,0xC0,0x24,0x40,0x27,0x40,0x25,0xC0,0x24,0x40,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_160_207_207[45] U8G_FONT_SECTION("fontpage_160_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x28,0x20,0x2F,0xE0,0x68, + 0x00,0xAF,0xE0,0x2A,0xA0,0x2F,0xE0,0x2A,0xA0,0x3A,0xA0,0x28,0x60}; +const u8g_fntpgm_uint8_t fontpage_160_220_220[45] U8G_FONT_SECTION("fontpage_160_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x3F,0xE0,0x20,0x00,0x4F,0xC0,0x48, + 0x40,0xDF,0xE0,0x50,0x20,0x4F,0xC0,0x41,0x00,0x41,0x00,0x47,0x00}; +const u8g_fntpgm_uint8_t fontpage_160_245_245[45] U8G_FONT_SECTION("fontpage_160_245_245") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF5,0xF5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xE0,0x22,0x00,0x2F,0xC0,0x68, + 0x40,0xAF,0xC0,0x28,0x40,0x2F,0xC0,0x28,0x40,0x2F,0xC0,0x38,0x60}; +const u8g_fntpgm_uint8_t fontpage_161_153_153[45] U8G_FONT_SECTION("fontpage_161_153_153") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x99,0x99,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x80,0x2F,0xC0,0x24,0x80,0x3F,0xE0,0x64, + 0x00,0xAF,0xE0,0x29,0x20,0x3F,0xE0,0x29,0x20,0x2F,0xE0,0x29,0x20}; +const u8g_fntpgm_uint8_t fontpage_161_179_179[45] U8G_FONT_SECTION("fontpage_161_179_179") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB3,0xB3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x3F,0xE0,0x2A,0x40,0x2F,0xC0,0x6A, + 0x40,0xBF,0xC0,0x22,0x80,0x3F,0xE0,0x28,0x80,0x24,0x80,0x21,0x80}; +const u8g_fntpgm_uint8_t fontpage_161_190_190[45] U8G_FONT_SECTION("fontpage_161_190_190") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBE,0xBE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x13,0xE0,0x10,0x80,0x2B,0xE0,0x2A,0x20,0x6F, + 0xE0,0xAA,0x20,0x2B,0xE0,0x2E,0x20,0x2B,0xE0,0x31,0x40,0x26,0x20}; +const u8g_fntpgm_uint8_t fontpage_162_178_178[45] U8G_FONT_SECTION("fontpage_162_178_178") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB2,0xB2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x28,0x80,0x3D,0xE0,0x40,0xA0,0x5D,0xE0,0xC0, + 0x80,0x5D,0xE0,0x43,0x20,0x5D,0xE0,0x55,0x20,0x5D,0xE0,0x55,0x20}; +const u8g_fntpgm_uint8_t fontpage_162_197_197[45] U8G_FONT_SECTION("fontpage_162_197_197") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC5,0xC5,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x04,0x00,0xFF,0xC0,0x08,0x00,0x11,0x00,0x7F, + 0x80,0x12,0x80,0x12,0x00,0x12,0x00,0x22,0x40,0x22,0x40,0xC1,0xC0}; +const u8g_fntpgm_uint8_t fontpage_162_200_201[73] U8G_FONT_SECTION("fontpage_162_200_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC8,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x24,0x00,0x3F,0xC0,0x44,0x00,0x84, + 0x00,0xFF,0xE0,0x12,0x00,0x12,0x00,0x12,0x20,0x22,0x20,0xC1,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x04,0x00,0x44,0x40,0x24,0x80,0x04,0x00,0xFF,0xE0,0x12,0x00,0x12, + 0x00,0x12,0x20,0x12,0x20,0x22,0x20,0xC1,0xE0}; +const u8g_fntpgm_uint8_t fontpage_162_229_229[45] U8G_FONT_SECTION("fontpage_162_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x18,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0A, + 0x00,0x0A,0x00,0x11,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x80,0x20}; +const u8g_fntpgm_uint8_t fontpage_162_232_232[45] U8G_FONT_SECTION("fontpage_162_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xDF, + 0x60,0x04,0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_162_241_241[45] U8G_FONT_SECTION("fontpage_162_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x7F,0xC0,0x11,0x00,0x11, + 0x00,0x11,0x00,0xFF,0xE0,0x00,0x00,0x11,0x00,0x20,0x80,0x40,0x40}; +const u8g_fntpgm_uint8_t fontpage_162_247_247[45] U8G_FONT_SECTION("fontpage_162_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x3F, + 0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF,0xE0,0x11,0x00,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_163_151_151[43] U8G_FONT_SECTION("fontpage_163_151_151") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x97,0x97,0x00,0x09,0xFF,0x00, + 0x00,0x0B,0x0A,0x14,0x0C,0x00,0xFF,0x7F,0xE0,0x40,0x20,0x9F,0x40,0x11,0x00,0x11, + 0x00,0x11,0x00,0x11,0x00,0x21,0x20,0x41,0x20,0x80,0xE0}; +const u8g_fntpgm_uint8_t fontpage_163_183_183[45] U8G_FONT_SECTION("fontpage_163_183_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x82,0x00,0x42,0x00,0x05,0x00,0x28,0x80,0x32, + 0x60,0x41,0x00,0x4F,0xC0,0x80,0x80,0x87,0x00,0x81,0x00,0x00,0x80}; +const u8g_fntpgm_uint8_t fontpage_163_198_198[45] U8G_FONT_SECTION("fontpage_163_198_198") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0A,0x00,0x89,0x00,0x4F,0xE0,0x59,0x00,0x09, + 0x00,0x2F,0xC0,0x29,0x00,0xCF,0xC0,0x49,0x00,0x49,0x00,0x4F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_163_250_250[45] U8G_FONT_SECTION("fontpage_163_250_250") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFA,0xFA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x44,0x40,0x44,0x40,0x44,0x40,0x7F, + 0xC0,0x04,0x00,0x84,0x20,0x84,0x20,0x84,0x20,0x84,0x20,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_134_134[45] U8G_FONT_SECTION("fontpage_164_134_134") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x86,0x86,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x11,0x00,0x20,0x80,0x20,0x80,0x40, + 0x40,0xBF,0xA0,0x08,0x80,0x08,0x80,0x10,0x80,0x20,0x80,0xC3,0x00}; +const u8g_fntpgm_uint8_t fontpage_164_151_151[45] U8G_FONT_SECTION("fontpage_164_151_151") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x97,0x97,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7E,0x20,0x10,0x20,0x11,0x20,0x3D,0x20,0x25, + 0x20,0x65,0x20,0x99,0x20,0x09,0x20,0x10,0x20,0x20,0x20,0xC0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_157_157[45] U8G_FONT_SECTION("fontpage_164_157_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9D,0x9D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0x27,0xE0,0xF9,0x20,0x11,0x20,0x21, + 0x20,0x69,0x20,0xB1,0x20,0x29,0x20,0x22,0x20,0x24,0x20,0x28,0xC0}; +const u8g_fntpgm_uint8_t fontpage_164_176_176[45] U8G_FONT_SECTION("fontpage_164_176_176") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFE,0x20,0x10,0x20,0x20,0xA0,0x44,0xA0,0xFE, + 0xA0,0x10,0xA0,0x7C,0xA0,0x10,0xA0,0x10,0x20,0x1E,0x20,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_182_183[73] U8G_FONT_SECTION("fontpage_164_182_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB6,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x20,0x50,0xA0,0x7E,0xA0,0x90,0xA0,0xFE, + 0xA0,0x10,0xA0,0x7E,0xA0,0x52,0xA0,0x52,0x20,0x56,0x20,0x10,0xE0,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x7E,0x20,0x42,0x20,0x7E,0xA0,0x48,0xA0,0x48,0xA0,0x7E,0xA0,0x6A, + 0xA0,0xAA,0xA0,0xAA,0xA0,0x2E,0x20,0x08,0xE0}; +const u8g_fntpgm_uint8_t fontpage_164_245_245[45] U8G_FONT_SECTION("fontpage_164_245_245") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF5,0xF5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x20,0x28,0x20,0x54,0xA0,0xFE,0xA0,0x44, + 0xA0,0x7C,0xA0,0x44,0xA0,0x7C,0xA0,0xC4,0x20,0x44,0x20,0x7C,0xE0}; +const u8g_fntpgm_uint8_t fontpage_165_155_155[45] U8G_FONT_SECTION("fontpage_165_155_155") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9B,0x9B,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0x80,0x08, + 0x80,0x08,0x80,0x10,0x80,0x10,0x80,0x20,0x80,0x40,0x80,0x87,0x00}; +const u8g_fntpgm_uint8_t fontpage_165_160_160[45] U8G_FONT_SECTION("fontpage_165_160_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x20,0x00,0xFD,0xE0,0x25,0x20,0x25, + 0x20,0x25,0x20,0x25,0x20,0x25,0x20,0x45,0x20,0x55,0xE0,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_165_213_213[45] U8G_FONT_SECTION("fontpage_165_213_213") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD5,0xD5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x78,0x80,0x10,0x80,0xFE,0x80,0x55,0xE0,0x7C, + 0xA0,0x54,0xA0,0x7C,0xA0,0x10,0xA0,0x7D,0x20,0x11,0x20,0xFE,0x60}; +const u8g_fntpgm_uint8_t fontpage_166_150_150[45] U8G_FONT_SECTION("fontpage_166_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x12,0x00,0x22,0x40,0x22,0x80,0x63, + 0x00,0xA2,0x00,0x26,0x00,0x2A,0x00,0x22,0x20,0x22,0x20,0x21,0xE0}; +const u8g_fntpgm_uint8_t fontpage_166_202_202[45] U8G_FONT_SECTION("fontpage_166_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x44,0x40,0x24,0x80,0x15,0x00,0x7F, + 0xC0,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_212_212[45] U8G_FONT_SECTION("fontpage_166_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x27,0xC0,0x22,0x40,0xFA,0x40,0x24, + 0x80,0x24,0x80,0x3F,0xE0,0x2A,0xA0,0x2A,0xA0,0x33,0x20,0x24,0x40}; +const u8g_fntpgm_uint8_t fontpage_166_225_225[45] U8G_FONT_SECTION("fontpage_166_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x0F,0x80,0x08,0x00,0x08,0x00,0xFF, + 0xE0,0x08,0x00,0x0A,0x00,0x09,0x00,0x08,0x80,0x08,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_240_240[45] U8G_FONT_SECTION("fontpage_166_240_240") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x10,0x00,0xE7,0xC0,0x84,0x40,0x84,0x40,0xF4, + 0x40,0x84,0x40,0x84,0x40,0x94,0x40,0xE5,0x80,0x84,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_248_248[45] U8G_FONT_SECTION("fontpage_166_248_248") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0x7D,0xE0,0x91,0x20,0x11,0x20,0xFF, + 0x20,0x11,0x20,0x5D,0x20,0x51,0x20,0x51,0xA0,0x5D,0x40,0xE1,0x00}; +const u8g_fntpgm_uint8_t fontpage_166_251_251[45] U8G_FONT_SECTION("fontpage_166_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x28,0x00,0x25,0xE0,0x53,0x20,0x99,0x20,0x25, + 0x20,0x43,0x20,0xBD,0x20,0x25,0xA0,0x25,0x40,0x3D,0x00,0x25,0x00}; +const u8g_fntpgm_uint8_t fontpage_167_159_159[45] U8G_FONT_SECTION("fontpage_167_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xE0,0x22,0x00,0x2F,0xC0,0x28,0x40,0x2F, + 0xC0,0x28,0x40,0x2F,0xC0,0x22,0x00,0x2A,0x80,0x52,0x60,0xA6,0x20}; +const u8g_fntpgm_uint8_t fontpage_167_205_205[45] U8G_FONT_SECTION("fontpage_167_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0xC0,0x3E,0x00,0x20,0x00,0x20,0x00,0x3F, + 0xC0,0x28,0x80,0x25,0x00,0x22,0x00,0x45,0x00,0x48,0x80,0xB0,0x60}; +const u8g_fntpgm_uint8_t fontpage_167_214_214[45] U8G_FONT_SECTION("fontpage_167_214_214") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD6,0xD6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFC,0x00,0x4B,0xE0,0x4A,0x20,0x7A,0x20,0x49, + 0x40,0x79,0x40,0x48,0x80,0x4C,0x80,0xF9,0x40,0x0A,0x40,0x0C,0x20}; +const u8g_fntpgm_uint8_t fontpage_167_240_240[45] U8G_FONT_SECTION("fontpage_167_240_240") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x10,0x00,0x22,0x00,0x41,0x00,0xFF, + 0x80,0x00,0x80,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00}; +const u8g_fntpgm_uint8_t fontpage_168_136_136[45] U8G_FONT_SECTION("fontpage_168_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xDF, + 0x60,0x00,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x3F,0x80,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_168_166_166[45] U8G_FONT_SECTION("fontpage_168_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x04,0x00,0x0D,0x80,0x34,0x40,0xC4, + 0x20,0x04,0x00,0x3F,0xC0,0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40}; +const u8g_fntpgm_uint8_t fontpage_168_202_202[45] U8G_FONT_SECTION("fontpage_168_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x00,0x24,0x00,0x3F,0xC0,0x44,0x00,0x04, + 0x00,0xFF,0xE0,0x00,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x3F,0x80}; +const u8g_fntpgm_uint8_t fontpage_168_253_253[45] U8G_FONT_SECTION("fontpage_168_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x0A,0x00,0x11,0x00,0xEE,0xE0,0x00, + 0x00,0x7B,0xC0,0x4A,0x40,0x4A,0x40,0x7A,0x40,0x4A,0xC0,0x02,0x00}; +const u8g_fntpgm_uint8_t fontpage_169_140_140[45] U8G_FONT_SECTION("fontpage_169_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0C,0x00,0x70,0x00,0x11,0xE0,0xFD,0x20,0x11, + 0x20,0x39,0x20,0x35,0x20,0x55,0x20,0x91,0x20,0x11,0xE0,0x10,0x00}; +const u8g_fntpgm_uint8_t fontpage_170_223_223[45] U8G_FONT_SECTION("fontpage_170_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x7D,0x00,0x45,0xE0,0x7D,0x40,0x43, + 0x40,0x5D,0x40,0x55,0x40,0x54,0x80,0x94,0x80,0x9D,0x40,0x82,0x20}; +const u8g_fntpgm_uint8_t fontpage_171_174_174[45] U8G_FONT_SECTION("fontpage_171_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xF3,0xC0,0x92,0x40,0x92,0x40,0xFF,0xC0,0x44, + 0x80,0x7F,0x80,0x44,0x80,0x7F,0x80,0x04,0x00,0xFF,0xC0,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_172_180_180[45] U8G_FONT_SECTION("fontpage_172_180_180") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB4,0xB4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0xA0,0xEB,0xC0,0xAA,0xA0,0xBF,0xE0,0xA4, + 0x80,0xAF,0xE0,0xF9,0x20,0x0F,0xE0,0x09,0x20,0x0F,0xE0,0x11,0x20}; +const u8g_fntpgm_uint8_t fontpage_172_232_232[45] U8G_FONT_SECTION("fontpage_172_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7B,0xC0,0x4A,0x40,0x4A,0x40,0x7B,0xC0,0x04, + 0x80,0xFF,0xE0,0x11,0x00,0xFB,0xE0,0x4A,0x40,0x4A,0x40,0x7B,0xC0}; +const u8g_fntpgm_uint8_t fontpage_172_244_244[45] U8G_FONT_SECTION("fontpage_172_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0xEF,0xE0,0xA5,0x40,0xAF,0xE0,0xA4, + 0x40,0xA7,0xC0,0xE4,0x40,0x07,0xC0,0x04,0x40,0x07,0xC0,0x0C,0x60}; +const u8g_fntpgm_uint8_t fontpage_173_222_222[45] U8G_FONT_SECTION("fontpage_173_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x80,0x40,0x80,0x40,0x9E,0x40,0x92, + 0x40,0x92,0x40,0x9E,0x40,0x92,0x40,0x80,0x40,0xFF,0xC0,0x80,0x40}; +const u8g_fntpgm_uint8_t fontpage_173_224_224[45] U8G_FONT_SECTION("fontpage_173_224_224") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x84,0x20,0x84,0x20,0xBF,0xA0,0x84, + 0x20,0x84,0x20,0x8A,0x20,0x91,0x20,0xA0,0xA0,0x80,0x20,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_173_250_250[45] U8G_FONT_SECTION("fontpage_173_250_250") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFA,0xFA,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x88,0x40,0x88,0x40,0xFF,0x40,0x88, + 0x40,0xBE,0x40,0xA2,0x40,0xA2,0x40,0xBE,0x40,0x80,0x40,0xFF,0xC0}; +const u8g_fntpgm_uint8_t fontpage_174_150_150[45] U8G_FONT_SECTION("fontpage_174_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x91,0x20,0x9F,0x20,0x84,0x20,0xFF, + 0xE0,0xAA,0xA0,0xAE,0xA0,0xA0,0xA0,0xBF,0xA0,0x80,0x20,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_174_168_168[45] U8G_FONT_SECTION("fontpage_174_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x08,0x00,0xFF,0xC0,0x10,0x00,0x22, + 0x00,0x62,0x00,0xAF,0x80,0x22,0x00,0x22,0x00,0x22,0x00,0x3F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_175_139_139[45] U8G_FONT_SECTION("fontpage_175_139_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8B,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7E,0x40,0x29,0x40,0x29,0x40,0xFF,0x40,0x29, + 0x40,0x28,0x40,0x4C,0xC0,0x04,0x00,0x3F,0x80,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_175_247_247[45] U8G_FONT_SECTION("fontpage_175_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0xF9,0x00,0x27,0xC0,0xF9,0x40,0x55, + 0x40,0xFB,0x40,0x21,0x40,0xF9,0xC0,0x22,0x40,0x24,0x20,0x28,0x20}; +const u8g_fntpgm_uint8_t fontpage_176_202_202[45] U8G_FONT_SECTION("fontpage_176_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x2F,0xE0,0x29,0x20,0xFF,0xE0,0x29, + 0x20,0x2F,0xE0,0x21,0x40,0x33,0xA0,0xE5,0xE0,0x09,0x20,0x10,0xE0}; +const u8g_fntpgm_uint8_t fontpage_176_235_235[45] U8G_FONT_SECTION("fontpage_176_235_235") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEB,0xEB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x21,0x00,0xF7,0xC0,0x24, + 0x40,0x27,0x40,0x25,0xC0,0x34,0x40,0xEF,0xE0,0x02,0x80,0x0C,0x60}; +const u8g_fntpgm_uint8_t fontpage_177_138_138[45] U8G_FONT_SECTION("fontpage_177_138_138") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8A,0x8A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF9,0x00,0x23,0xC0,0xF9,0x40,0x51,0x40,0xFB, + 0x40,0x22,0xC0,0xFC,0x20,0x24,0x20,0x7F,0xC0,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_178_150_150[45] U8G_FONT_SECTION("fontpage_178_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x3D,0x00,0x25,0x00,0x45, + 0x80,0xA5,0x40,0x19,0x20,0x09,0x00,0x11,0x00,0x21,0x00,0x41,0x00}; +const u8g_fntpgm_uint8_t fontpage_178_154_154[45] U8G_FONT_SECTION("fontpage_178_154_154") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9A,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0x1F,0x00,0x21,0x00,0x52,0x00,0x0C, + 0x00,0x34,0x00,0xCF,0x80,0x10,0x80,0x69,0x00,0x06,0x00,0xF8,0x00}; +const u8g_fntpgm_uint8_t fontpage_178_160_160[45] U8G_FONT_SECTION("fontpage_178_160_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x79,0xE0,0x8A,0x20,0x50,0x20,0x23, + 0xA0,0xFA,0xA0,0x2A,0xA0,0xCB,0xA0,0x28,0x20,0x11,0x20,0xE0,0xC0}; +const u8g_fntpgm_uint8_t fontpage_178_167_167[45] U8G_FONT_SECTION("fontpage_178_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04, + 0x00,0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_178_169_170[73] U8G_FONT_SECTION("fontpage_178_169_170") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA9,0xAA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0xFF, + 0xE0,0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x0A,0x00,0x0A, + 0x00,0x11,0x00,0x19,0x00,0x24,0x80,0xC4,0x60}; +const u8g_fntpgm_uint8_t fontpage_178_177_177[45] U8G_FONT_SECTION("fontpage_178_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x00,0x24,0x00,0x3F,0xC0,0x44,0x00,0x04, + 0x00,0xFF,0xE0,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_179_203_203[45] U8G_FONT_SECTION("fontpage_179_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0xFA,0x40,0x2A,0x20,0x2F, + 0xE0,0x48,0x00,0x53,0xE0,0x32,0x20,0x2A,0x20,0x4B,0xE0,0x82,0x20}; +const u8g_fntpgm_uint8_t fontpage_181_146_146[45] U8G_FONT_SECTION("fontpage_181_146_146") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x92,0x92,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x40,0x2F,0xE0,0x24,0x40,0xF7,0xC0,0x54, + 0x40,0x57,0xC0,0x51,0x00,0x2F,0xE0,0x33,0x80,0x4D,0x40,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_182_208_208[45] U8G_FONT_SECTION("fontpage_182_208_208") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x04, + 0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x14,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_182_216_216[45] U8G_FONT_SECTION("fontpage_182_216_216") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0xFF,0xE0,0x10,0x00,0x2F,0xC0,0x20, + 0x80,0x61,0x00,0xBF,0xE0,0x21,0x00,0x21,0x00,0x21,0x00,0x27,0x00}; +const u8g_fntpgm_uint8_t fontpage_183_137_137[45] U8G_FONT_SECTION("fontpage_183_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x88,0x40,0x08, + 0x00,0xFF,0xE0,0x11,0x00,0x31,0x00,0x0E,0x00,0x09,0x80,0x70,0x60}; +const u8g_fntpgm_uint8_t fontpage_183_140_140[45] U8G_FONT_SECTION("fontpage_183_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x9F,0x40,0x00, + 0x00,0x7F,0xE0,0x0A,0x00,0x12,0x00,0x12,0x20,0x22,0x20,0x41,0xE0}; +const u8g_fntpgm_uint8_t fontpage_183_154_154[45] U8G_FONT_SECTION("fontpage_183_154_154") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x80,0x40,0x3F, + 0xC0,0x04,0x00,0x24,0x00,0x27,0x80,0x24,0x00,0x54,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_183_162_162[45] U8G_FONT_SECTION("fontpage_183_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x08,0x00,0xFF,0xC0,0x90,0x40,0x3F,0x00,0x52, + 0x00,0x8C,0x00,0x33,0x00,0xFF,0xC0,0x21,0x00,0x21,0x00,0x3F,0x00}; +const u8g_fntpgm_uint8_t fontpage_183_185_185[45] U8G_FONT_SECTION("fontpage_183_185_185") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB9,0xB9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x91,0x20,0x24,0x80,0x4A, + 0x40,0x11,0x00,0x20,0x80,0xDF,0x60,0x11,0x00,0x11,0x00,0x1F,0x00}; +const u8g_fntpgm_uint8_t fontpage_184_141_141[45] U8G_FONT_SECTION("fontpage_184_141_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x28,0x40,0xAA,0x40,0x6C,0x40,0xFF,0xE0,0x28, + 0x40,0x7D,0x40,0x10,0xC0,0x7C,0x40,0x10,0x40,0x1D,0x40,0xE0,0x80}; +const u8g_fntpgm_uint8_t fontpage_184_143_143[45] U8G_FONT_SECTION("fontpage_184_143_143") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8F,0x8F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0x24,0x80,0x24, + 0x40,0x44,0x40,0x44,0x20,0x84,0x20,0x04,0x00,0x14,0x00,0x08,0x00}; +const u8g_fntpgm_uint8_t fontpage_184_177_177[45] U8G_FONT_SECTION("fontpage_184_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFD,0x40,0x01,0x20,0x7F,0xE0,0x4A, + 0x80,0x7A,0x80,0x12,0x80,0x5A,0xA0,0x56,0xA0,0x92,0xA0,0x34,0x60}; +const u8g_fntpgm_uint8_t fontpage_187_229_229[41] U8G_FONT_SECTION("fontpage_187_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x09,0x00,0x00, + 0x00,0x0B,0x09,0x12,0x0C,0x00,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04, + 0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_187_238_238[45] U8G_FONT_SECTION("fontpage_187_238_238") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x80,0x09,0x00,0xFF,0xE0,0x04,0x00,0x7F, + 0xC0,0x08,0x00,0xFF,0xE0,0x10,0x00,0x2F,0x80,0x42,0x00,0xBF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_187_242_242[43] U8G_FONT_SECTION("fontpage_187_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x09,0xFF,0x00, + 0x00,0x0A,0x0A,0x14,0x0C,0x01,0xFF,0xFF,0x00,0x01,0x00,0x01,0x00,0x81,0x00,0xFF, + 0x00,0x80,0x00,0x80,0x40,0x80,0x40,0x80,0x40,0x7F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_188_243_243[45] U8G_FONT_SECTION("fontpage_188_243_243") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF3,0xF3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0x24,0x80,0x15,0x00,0x04, + 0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_189_138_138[45] U8G_FONT_SECTION("fontpage_189_138_138") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8A,0x8A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0x7F,0xE0,0x42,0x00,0x42,0x00,0x7F, + 0xE0,0x42,0x00,0x47,0x00,0x4A,0x80,0x52,0x40,0xA2,0x20,0x82,0x00}; +const u8g_fntpgm_uint8_t fontpage_189_166_166[45] U8G_FONT_SECTION("fontpage_189_166_166") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA6,0xA6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x49,0x00,0x7F,0xC0,0x49, + 0x00,0x4F,0x00,0x40,0x00,0x5F,0x80,0x49,0x00,0x86,0x00,0xB9,0xC0}; +const u8g_fntpgm_uint8_t fontpage_189_226_226[45] U8G_FONT_SECTION("fontpage_189_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x55,0x40,0x48,0xA0,0x7D, + 0xC0,0x45,0x20,0x5E,0x00,0x51,0xC0,0x5D,0x40,0x84,0x80,0x9B,0x60}; +const u8g_fntpgm_uint8_t fontpage_189_250_250[45] U8G_FONT_SECTION("fontpage_189_250_250") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFA,0xFA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0xEF,0xC0,0x22,0x40,0x5F,0xE0,0xE2, + 0x40,0x2F,0xC0,0xA2,0x00,0x6F,0xE0,0x22,0x00,0x52,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_190_149_149[45] U8G_FONT_SECTION("fontpage_190_149_149") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x95,0x95,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFC,0x40,0x04,0x40,0x04,0x40,0x7C,0x40,0x40, + 0x40,0xFC,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x28,0x40,0x10,0x40}; +const u8g_fntpgm_uint8_t fontpage_191_133_133[45] U8G_FONT_SECTION("fontpage_191_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x21,0x00,0x47,0xC0,0x91,0x00,0x1F, + 0xE0,0x20,0x80,0x6F,0xE0,0xA4,0x80,0x22,0x80,0x20,0x80,0x21,0x80}; +const u8g_fntpgm_uint8_t fontpage_191_140_140[45] U8G_FONT_SECTION("fontpage_191_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x24,0x80,0x47,0x00,0x92,0x40,0x2F, + 0xE0,0x64,0x20,0xA7,0xC0,0x2C,0x40,0x32,0x80,0x23,0x80,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_191_145_145[45] U8G_FONT_SECTION("fontpage_191_145_145") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x91,0x91,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x1F,0xE0,0x25,0x40,0x45,0x40,0x9A,0x80,0x25, + 0x40,0x65,0x40,0xA0,0x00,0x27,0xC0,0x21,0x00,0x21,0x00,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_191_158_158[45] U8G_FONT_SECTION("fontpage_191_158_158") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9E,0x9E,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x40,0x22,0x40,0x45,0xA0,0x99,0x20,0x20, + 0x00,0x65,0x00,0xA5,0x00,0x25,0xE0,0x25,0x00,0x2B,0x00,0x31,0xE0}; +const u8g_fntpgm_uint8_t fontpage_191_169_169[45] U8G_FONT_SECTION("fontpage_191_169_169") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA9,0xA9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x14,0x00,0x27,0xE0,0x4C,0x40,0x97,0xC0,0x24, + 0x40,0x67,0xC0,0xA4,0x00,0x27,0xC0,0x2C,0x80,0x33,0x00,0x2C,0xE0}; +const u8g_fntpgm_uint8_t fontpage_191_174_174[45] U8G_FONT_SECTION("fontpage_191_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2A,0x80,0x6A,0x80,0xBE,0x80,0x01,0xE0,0x5D, + 0x40,0xC3,0x40,0x5D,0x40,0x54,0x80,0x56,0x80,0x55,0x40,0x62,0x20}; +const u8g_fntpgm_uint8_t fontpage_191_195_195[45] U8G_FONT_SECTION("fontpage_191_195_195") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC3,0xC3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x02,0x00,0x12,0x00,0x12,0x00,0x10, + 0x40,0x50,0x20,0x50,0x20,0x50,0xA0,0x90,0x80,0x10,0x80,0x0F,0x80}; +const u8g_fntpgm_uint8_t fontpage_192_167_167[45] U8G_FONT_SECTION("fontpage_192_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x25,0x00,0xB5,0x00,0xAF,0xE0,0xA9, + 0x00,0xB1,0x00,0x27,0xC0,0x21,0x00,0x21,0x00,0x21,0x00,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_192_226_226[45] U8G_FONT_SECTION("fontpage_192_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x2F,0xE0,0xB2,0x00,0xAA,0x80,0xA4, + 0x80,0xA5,0xA0,0x2A,0xC0,0x30,0x80,0x21,0x40,0x22,0x40,0x24,0x20}; +const u8g_fntpgm_uint8_t fontpage_192_239_239[45] U8G_FONT_SECTION("fontpage_192_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20, + 0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x54,0x40,0x52,0xA0,0x8F,0x80}; +const u8g_fntpgm_uint8_t fontpage_195_182_182[45] U8G_FONT_SECTION("fontpage_195_182_182") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB6,0xB6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xE0,0xB2,0x80,0xAF,0xE0,0xA4, + 0x40,0x27,0xC0,0x24,0x40,0x27,0xC0,0x25,0x40,0x2C,0xA0,0x33,0xA0}; +const u8g_fntpgm_uint8_t fontpage_195_201_201[45] U8G_FONT_SECTION("fontpage_195_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0x7F,0xE0,0x4A,0x80,0x57,0xE0,0x7C, + 0x80,0x57,0xC0,0x54,0x80,0x57,0xE0,0x4A,0x40,0xA8,0xA0,0x4F,0xA0}; +const u8g_fntpgm_uint8_t fontpage_196_144_144[45] U8G_FONT_SECTION("fontpage_196_144_144") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0x90,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x80,0x02,0x40,0x7F,0xE0,0x42,0x00,0x42, + 0x00,0x7A,0x40,0x4A,0x40,0x4A,0x80,0x49,0x20,0x52,0xA0,0x84,0x60}; +const u8g_fntpgm_uint8_t fontpage_196_182_182[45] U8G_FONT_SECTION("fontpage_196_182_182") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB6,0xB6,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x01,0xC0,0x3E,0x00,0x20,0x00,0x3F,0xC0,0x20, + 0x40,0x20,0x40,0x3F,0xC0,0x20,0x00,0x20,0x00,0x40,0x00,0x80,0x00}; +const u8g_fntpgm_uint8_t fontpage_196_192_192[45] U8G_FONT_SECTION("fontpage_196_192_192") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x18,0x60,0x63,0x80,0x42,0x00,0x7A,0x00,0x4B, + 0xE0,0x4A,0x40,0x7A,0x40,0x42,0x40,0x42,0x40,0x44,0x40,0x88,0x40}; +const u8g_fntpgm_uint8_t fontpage_196_199_199[45] U8G_FONT_SECTION("fontpage_196_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xE0,0x40,0x20,0x7F,0xE0,0x40, + 0x00,0x7D,0xE0,0x44,0x20,0x54,0xA0,0x4C,0x60,0x54,0xA0,0xA9,0x60}; +const u8g_fntpgm_uint8_t fontpage_196_203_203[45] U8G_FONT_SECTION("fontpage_196_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x03,0xC0,0x7C,0x00,0x04,0x00,0x7F,0xC0,0x04, + 0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00}; +const u8g_fntpgm_uint8_t fontpage_196_211_211[45] U8G_FONT_SECTION("fontpage_196_211_211") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD3,0xD3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xE0,0xF8,0x80,0x20,0x80,0x28, + 0x80,0x30,0x80,0x60,0x80,0xA0,0x80,0x20,0x80,0x20,0x80,0xE3,0x80}; +const u8g_fntpgm_uint8_t fontpage_196_249_249[45] U8G_FONT_SECTION("fontpage_196_249_249") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF9,0xF9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x80,0x24,0x80,0xFC,0x80,0x24,0xA0,0x2F, + 0xC0,0x34,0x80,0x64,0x80,0xA4,0x80,0x25,0xA0,0x26,0xA0,0xE4,0x60}; +const u8g_fntpgm_uint8_t fontpage_197_150_150[45] U8G_FONT_SECTION("fontpage_197_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x40,0x22,0x40,0xF9,0x40,0x20,0x40,0x2A, + 0x40,0x31,0x40,0x60,0xE0,0xAF,0x40,0x20,0x40,0x20,0x40,0xE0,0x40}; +const u8g_fntpgm_uint8_t fontpage_197_189_189[45] U8G_FONT_SECTION("fontpage_197_189_189") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBD,0xBD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x20,0x80,0xF8,0x80,0x27,0xE0,0x2C, + 0xA0,0x34,0xA0,0x67,0xE0,0xA4,0xA0,0x24,0xA0,0x27,0xE0,0xE4,0x20}; +const u8g_fntpgm_uint8_t fontpage_197_212_212[45] U8G_FONT_SECTION("fontpage_197_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x80,0x22,0x40,0xFF,0xE0,0x22,0x00,0x2B, + 0xC0,0x32,0x40,0x65,0x40,0xA4,0x80,0x28,0x80,0x29,0x40,0xE6,0x20}; +const u8g_fntpgm_uint8_t fontpage_198_137_137[45] U8G_FONT_SECTION("fontpage_198_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x20,0x80,0xFF,0xE0,0x25,0x20,0x29, + 0x00,0x37,0xE0,0x62,0x40,0xA6,0x40,0x21,0x80,0x22,0x80,0xEC,0x60}; +const u8g_fntpgm_uint8_t fontpage_199_137_137[45] U8G_FONT_SECTION("fontpage_199_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0xE0,0xF9,0x00,0x27,0xC0,0x2C, + 0x40,0x37,0xC0,0x64,0x40,0xA7,0xC0,0x21,0x00,0x2F,0xE0,0xE1,0x00}; +const u8g_fntpgm_uint8_t fontpage_199_162_162[45] U8G_FONT_SECTION("fontpage_199_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xE0,0x28,0x20,0xF2,0x80,0x24,0x40,0x29, + 0x20,0x31,0x00,0x6F,0xE0,0xA1,0x00,0x25,0x80,0x29,0x40,0xF1,0x20}; +const u8g_fntpgm_uint8_t fontpage_199_165_165[45] U8G_FONT_SECTION("fontpage_199_165_165") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0xF4,0x40,0x22,0x80,0x2F, + 0xE0,0x31,0x00,0x6F,0xE0,0xA2,0x40,0x26,0x80,0x21,0x40,0xEE,0x20}; +const u8g_fntpgm_uint8_t fontpage_199_167_167[45] U8G_FONT_SECTION("fontpage_199_167_167") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA7,0xA7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0xF8,0x20,0x22,0x80,0x24, + 0x40,0x38,0x20,0x67,0xC0,0xA1,0x00,0x21,0x00,0x21,0x00,0xEF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_199_208_208[45] U8G_FONT_SECTION("fontpage_199_208_208") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD0,0xD0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x24,0x40,0xFF,0xC0,0x24,0x40,0x27, + 0xC0,0x30,0x00,0x6F,0xE0,0xA5,0x00,0x25,0xE0,0x2B,0x00,0xF1,0xE0}; +const u8g_fntpgm_uint8_t fontpage_199_210_210[45] U8G_FONT_SECTION("fontpage_199_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0xC0,0x27,0x00,0xF1,0x00,0x2F,0xE0,0x21, + 0x00,0x35,0x60,0x69,0x20,0xAD,0x60,0x29,0x20,0x29,0x20,0xEF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_199_219_219[45] U8G_FONT_SECTION("fontpage_199_219_219") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDB,0xDB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xC0,0xF4,0x80,0x2F,0xE0,0x2A, + 0xA0,0x3A,0xA0,0x6C,0x60,0xA1,0x00,0x2F,0xE0,0x22,0x80,0xEC,0x60}; +const u8g_fntpgm_uint8_t fontpage_201_199_199[45] U8G_FONT_SECTION("fontpage_201_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xE0,0x2A,0xA0,0xFF,0xE0,0x21,0x00,0x2F, + 0xE0,0x32,0x80,0xE7,0xC0,0x21,0x00,0x2F,0xE0,0xA1,0x00,0x61,0x00}; +const u8g_fntpgm_uint8_t fontpage_201_202_203[73] U8G_FONT_SECTION("fontpage_201_202_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFD,0xC0,0xA9,0x40,0xF9,0x60,0xAB,0xC0,0xFD, + 0x40,0xA9,0x80,0xAB,0x60,0xFE,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x29,0x20,0x25,0x40,0xFF,0xE0,0x2A,0xA0,0x2B,0x80,0x30,0x00,0xEF, + 0xE0,0x29,0x20,0x2F,0xE0,0xA9,0x20,0x6F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_201_224_224[45] U8G_FONT_SECTION("fontpage_201_224_224") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0xFA,0xA0,0x25,0x40,0x2D, + 0x60,0x35,0x40,0xE4,0x40,0x27,0xC0,0x24,0x40,0xA7,0xC0,0x68,0x40}; +const u8g_fntpgm_uint8_t fontpage_202_182_182[45] U8G_FONT_SECTION("fontpage_202_182_182") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB6,0xB6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x12,0x00,0x12,0x00,0x93,0xE0,0x94,0x40,0x9A, + 0x40,0x92,0x40,0xB2,0x80,0xD1,0x00,0x91,0x80,0x12,0x40,0x14,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_190_190[45] U8G_FONT_SECTION("fontpage_202_190_190") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBE,0xBE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x11,0x00,0xFD,0xE0,0x22,0x40,0x25, + 0x40,0x39,0x40,0x29,0x40,0x28,0x80,0x49,0x80,0x4A,0x40,0x94,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_215_215[45] U8G_FONT_SECTION("fontpage_202_215_215") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD7,0xD7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7D,0x00,0x45,0x00,0x7D,0xE0,0x47,0x40,0x7D, + 0x40,0x45,0x40,0x7D,0x40,0x45,0x40,0x28,0x80,0x45,0x40,0x86,0x20}; +const u8g_fntpgm_uint8_t fontpage_202_244_244[45] U8G_FONT_SECTION("fontpage_202_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFF,0xE0,0x55,0x40,0x7C,0x80,0x39, + 0x40,0x56,0x20,0x7F,0xC0,0x04,0x00,0x27,0x80,0x24,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_202_248_248[45] U8G_FONT_SECTION("fontpage_202_248_248") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x7D,0x00,0x55,0xE0,0xFF,0x40,0x55, + 0x40,0xFD,0x40,0x95,0x40,0xFF,0x40,0x28,0x80,0x19,0x40,0xE6,0x20}; +const u8g_fntpgm_uint8_t fontpage_203_153_153[45] U8G_FONT_SECTION("fontpage_203_153_153") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x99,0x99,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0xAC,0x80,0x72,0x80,0x20,0x80,0xFC, + 0x80,0x22,0x80,0x30,0xE0,0x6F,0x80,0xA0,0x80,0x20,0x80,0x20,0x80}; +const u8g_fntpgm_uint8_t fontpage_203_156_156[45] U8G_FONT_SECTION("fontpage_203_156_156") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9C,0x9C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x40,0x29,0x40,0x44,0xC0,0xB8,0x40,0x12, + 0x40,0x7D,0x40,0x10,0x60,0x55,0xC0,0x52,0x40,0x92,0x40,0x30,0x40}; +const u8g_fntpgm_uint8_t fontpage_203_176_176[45] U8G_FONT_SECTION("fontpage_203_176_176") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x60,0xFD,0x80,0x45,0x00,0x29,0x00,0xFD, + 0xE0,0x11,0x40,0xFD,0x40,0x11,0x40,0x55,0x40,0x92,0x40,0x34,0x40}; +const u8g_fntpgm_uint8_t fontpage_203_183_183[45] U8G_FONT_SECTION("fontpage_203_183_183") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB7,0xB7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xAA,0x40,0xFD,0x80,0x95,0x00,0xAB,0x00,0xFF, + 0xE0,0xA9,0x40,0xAB,0x40,0xFD,0x40,0x95,0x40,0xAB,0x40,0xFE,0x40}; +const u8g_fntpgm_uint8_t fontpage_203_188_188[45] U8G_FONT_SECTION("fontpage_203_188_188") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x10,0x80,0xFD,0x40,0x21,0x40,0x3A, + 0x20,0x2C,0x80,0x28,0x40,0x28,0x40,0x49,0x00,0x48,0x80,0x98,0x40}; +const u8g_fntpgm_uint8_t fontpage_204_135_135[45] U8G_FONT_SECTION("fontpage_204_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xC0,0x20,0x40,0x3F,0xC0,0x20,0x40,0x3F, + 0xC0,0x79,0x00,0x11,0x00,0xFF,0xE0,0x11,0x00,0x21,0x00,0xC1,0x00}; +const u8g_fntpgm_uint8_t fontpage_204_142_142[45] U8G_FONT_SECTION("fontpage_204_142_142") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8E,0x8E,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x03,0xE0,0xF2,0x20,0x92,0x20,0x93,0xE0,0xF2, + 0x20,0x92,0x20,0x93,0xE0,0xF2,0x20,0x04,0x20,0x08,0xA0,0x30,0x40}; +const u8g_fntpgm_uint8_t fontpage_204_175_175[45] U8G_FONT_SECTION("fontpage_204_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x1F,0x80,0x10,0x80,0x1F,0x80,0x10,0x80,0x1F, + 0x80,0x00,0x00,0xFF,0xE0,0x24,0x00,0x27,0x80,0x54,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_204_194_194[45] U8G_FONT_SECTION("fontpage_204_194_194") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC2,0xC2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0xF7,0xC0,0x91,0x00,0x91,0x00,0xFF, + 0xE0,0x90,0x80,0x9F,0xE0,0x94,0x80,0xF2,0x80,0x00,0x80,0x03,0x80}; +const u8g_fntpgm_uint8_t fontpage_205_171_171[45] U8G_FONT_SECTION("fontpage_205_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0xE0,0xFF,0x00,0x55,0xE0,0x7D,0x40,0x55, + 0x40,0xFF,0xC0,0x10,0x40,0x1F,0xC0,0x10,0x40,0x1F,0xC0,0x10,0x40}; +const u8g_fntpgm_uint8_t fontpage_205_244_244[45] U8G_FONT_SECTION("fontpage_205_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xE0,0x02,0x00,0x3F,0xC0,0x22,0x40,0x3F, + 0xC0,0x22,0x40,0x3F,0xC0,0x0A,0x00,0x04,0x00,0x1B,0x00,0xE0,0xE0}; +const u8g_fntpgm_uint8_t fontpage_206_128_128[45] U8G_FONT_SECTION("fontpage_206_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF, + 0xE0,0x48,0x00,0x7F,0xC0,0x4A,0x40,0x79,0x80,0xC9,0x80,0x0E,0x60}; +const u8g_fntpgm_uint8_t fontpage_206_137_137[45] U8G_FONT_SECTION("fontpage_206_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x08,0x00,0xFF,0xE0,0x10,0x00,0x1F,0x80,0x30, + 0x80,0x5F,0x80,0x90,0x80,0x1F,0x80,0x10,0x80,0x10,0x80,0x11,0x80}; +const u8g_fntpgm_uint8_t fontpage_206_255_255[45] U8G_FONT_SECTION("fontpage_206_255_255") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0xC0,0x27,0x00,0xFC,0x00,0x24,0x00,0x27, + 0xC0,0x74,0x40,0x6E,0x40,0xA5,0x80,0x28,0x80,0x29,0x40,0x36,0x20}; +const u8g_fntpgm_uint8_t fontpage_207_241_241[45] U8G_FONT_SECTION("fontpage_207_241_241") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x21,0x00,0xFF,0xE0,0x21,0x00,0x71, + 0x00,0x69,0x00,0xA7,0xC0,0xA1,0x00,0x21,0x00,0x21,0x00,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_208_161_161[45] U8G_FONT_SECTION("fontpage_208_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x21,0x00,0x2F,0xE0,0xF0,0x00,0x22, + 0x80,0x74,0x40,0x6A,0xA0,0xA2,0x80,0x21,0x00,0x22,0x80,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_208_188_188[45] U8G_FONT_SECTION("fontpage_208_188_188") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xC0,0xF4,0x40,0x2A,0x80,0x21, + 0x00,0x72,0x80,0x6C,0x60,0xA7,0xC0,0x24,0x40,0x24,0x40,0x27,0xC0}; +const u8g_fntpgm_uint8_t fontpage_209_157_157[45] U8G_FONT_SECTION("fontpage_209_157_157") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9D,0x9D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x24,0x00,0x27,0xE0,0x5A,0x40,0x51,0x80,0xDE, + 0x60,0x51,0x00,0x5F,0xE0,0x51,0x00,0x45,0x40,0x49,0x20,0x53,0x20}; +const u8g_fntpgm_uint8_t fontpage_209_196_196[45] U8G_FONT_SECTION("fontpage_209_196_196") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC4,0xC4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x20,0x80,0x7F,0xC0,0x24, + 0x80,0xFF,0xE0,0x24,0x80,0xFF,0xE0,0x15,0x00,0x24,0x80,0xC4,0x60}; +const u8g_fntpgm_uint8_t fontpage_211_253_253[45] U8G_FONT_SECTION("fontpage_211_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x80,0x2F,0xE0,0xFA,0xA0,0x2F,0xE0,0x2A, + 0xA0,0x3F,0xE0,0x64,0x40,0xA7,0xC0,0x24,0x40,0x27,0xC0,0x24,0x40}; +const u8g_fntpgm_uint8_t fontpage_212_217_217[45] U8G_FONT_SECTION("fontpage_212_217_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0x40,0x2A,0xA0,0xF4,0x40,0x27,0xC0,0x38, + 0x20,0x27,0xC0,0x64,0x40,0xA7,0xC0,0x24,0x40,0x22,0x80,0x2F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_212_223_223[45] U8G_FONT_SECTION("fontpage_212_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x25,0x40,0x29,0xA0,0xFF,0x40,0x25,0x20,0x6F, + 0xE0,0x75,0x40,0xAF,0xE0,0xA5,0x40,0x26,0xA0,0x29,0x60,0x32,0x20}; +const u8g_fntpgm_uint8_t fontpage_213_162_162[45] U8G_FONT_SECTION("fontpage_213_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x22,0x80,0xF4,0x40,0x2B,0xA0,0x60, + 0x00,0x7E,0xE0,0xAA,0xA0,0xAE,0xE0,0x24,0x40,0x2A,0xC0,0x31,0x20}; +const u8g_fntpgm_uint8_t fontpage_214_226_227[71] U8G_FONT_SECTION("fontpage_214_226_227") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE3,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x04,0x00,0x04,0x00,0x04,0x00,0x24,0x00,0x27, + 0x80,0x24,0x00,0x24,0x00,0x24,0x00,0x24,0x00,0x24,0x00,0xFF,0xC0,0x0B,0x0A,0x14, + 0x0C,0x00,0xFF,0xFF,0xE0,0x04,0x00,0x04,0x00,0x24,0x00,0x27,0xC0,0x24,0x00,0x24, + 0x00,0x24,0x00,0x24,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_214_229_229[45] U8G_FONT_SECTION("fontpage_214_229_229") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE5,0xE5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x27,0xC0,0x24,0x00,0x24,0x00,0xFF, + 0xE0,0x04,0x00,0x14,0x40,0x24,0x80,0x41,0x00,0x06,0x00,0xF8,0x00}; +const u8g_fntpgm_uint8_t fontpage_214_248_248[45] U8G_FONT_SECTION("fontpage_214_248_248") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x43,0xC0,0xF0,0x40,0x93,0xC0,0xF8,0x40,0x8F, + 0xE0,0xFC,0xA0,0x20,0x80,0xBB,0xE0,0xA2,0xA0,0xBA,0xE0,0xE0,0x80}; +const u8g_fntpgm_uint8_t fontpage_215_188_188[45] U8G_FONT_SECTION("fontpage_215_188_188") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBC,0xBC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0xC0,0xFD,0x40,0x11,0x40,0xFF,0x60,0x84, + 0x00,0x7B,0xE0,0x01,0x40,0x79,0x40,0x4A,0x80,0x4D,0x40,0x82,0x20}; +const u8g_fntpgm_uint8_t fontpage_215_212_212[45] U8G_FONT_SECTION("fontpage_215_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x84,0x00,0x84,0x00,0x84,0x80,0x85,0x00,0xF6, + 0x00,0x84,0x00,0x84,0x00,0x84,0x00,0xB4,0x40,0xC4,0x40,0x83,0xC0}; +const u8g_fntpgm_uint8_t fontpage_217_146_146[45] U8G_FONT_SECTION("fontpage_217_146_146") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x92,0x92,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x23,0xC0,0x84,0x40,0x59,0x40,0x10, + 0x80,0x27,0xC0,0x24,0x40,0xC2,0x80,0x41,0x00,0x46,0x80,0x58,0x60}; +const u8g_fntpgm_uint8_t fontpage_219_136_136[45] U8G_FONT_SECTION("fontpage_219_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x49,0x20,0x25,0x40,0x81,0x00,0x57,0xE0,0x14, + 0x20,0x27,0xE0,0x24,0x20,0xC7,0xE0,0x44,0x20,0x44,0x20,0x44,0x60}; +const u8g_fntpgm_uint8_t fontpage_219_225_225[45] U8G_FONT_SECTION("fontpage_219_225_225") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE1,0xE1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x25,0x40,0x09,0x80,0x82,0x80,0x54, + 0x40,0x29,0x20,0x25,0x40,0xC5,0x80,0x49,0x00,0x42,0x80,0x5C,0x60}; +const u8g_fntpgm_uint8_t fontpage_220_133_133[45] U8G_FONT_SECTION("fontpage_220_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x2F,0xE0,0x01,0x00,0x97,0xC0,0x51, + 0x00,0x2F,0xE0,0x24,0x40,0xC7,0x40,0x45,0xC0,0x44,0x40,0x44,0xC0}; +const u8g_fntpgm_uint8_t fontpage_220_172_172[45] U8G_FONT_SECTION("fontpage_220_172_172") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4E,0x20,0x2A,0xA0,0x0A,0xA0,0x8E,0xA0,0x5A, + 0xA0,0x2E,0xA0,0x2A,0xA0,0xCA,0xA0,0x4E,0x20,0x4A,0x20,0x51,0x60}; +const u8g_fntpgm_uint8_t fontpage_221_144_144[45] U8G_FONT_SECTION("fontpage_221_144_144") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0x90,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x28,0x80,0x8B,0xE0,0x4A,0x20,0x1B, + 0xE0,0x2A,0x20,0x2B,0xE0,0xC8,0x80,0x4A,0xC0,0x54,0xA0,0x69,0xA0}; +const u8g_fntpgm_uint8_t fontpage_221_150_150[45] U8G_FONT_SECTION("fontpage_221_150_150") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x96,0x96,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x85,0x00,0x4F,0xE0,0x99,0x00,0x4F,0xC0,0x49, + 0x00,0xCF,0xC0,0x49,0x00,0x4F,0xE0,0x04,0x00,0xFF,0xE0,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_221_171_171[45] U8G_FONT_SECTION("fontpage_221_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xC0,0x25,0x40,0x06,0xC0,0x84,0x40,0x47, + 0xC0,0x20,0x00,0x2F,0xE0,0xCA,0xA0,0x4A,0xA0,0x4A,0xA0,0x5F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_223_192_192[45] U8G_FONT_SECTION("fontpage_223_192_192") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x80,0x3E,0x80,0x12,0xE0,0x9E,0xA0,0x53, + 0xA0,0x3E,0xA0,0x28,0xA0,0xDF,0xA0,0x4A,0x40,0x52,0xA0,0x65,0x20}; +const u8g_fntpgm_uint8_t fontpage_226_161_161[45] U8G_FONT_SECTION("fontpage_226_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0x7F,0xE0,0xAA,0x80,0x2A,0x80,0xFF, + 0xE0,0x2A,0x80,0x2A,0x80,0xFF,0xE0,0x12,0x40,0x49,0x20,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_227_177_177[45] U8G_FONT_SECTION("fontpage_227_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0xF9,0x00,0x23,0xC0,0xFD,0x40,0x53, + 0x40,0xA9,0x40,0xFA,0xE0,0x22,0x20,0xFA,0x40,0x49,0x20,0x89,0x20}; +const u8g_fntpgm_uint8_t fontpage_227_200_200[45] U8G_FONT_SECTION("fontpage_227_200_200") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC8,0xC8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2F,0xA0,0x2B,0x40,0xAC,0x80,0xB7,0xC0,0xA8, + 0x20,0x37,0xC0,0x24,0x40,0x27,0xC0,0x52,0x80,0x49,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_228_199_199[45] U8G_FONT_SECTION("fontpage_228_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x21,0x00,0x3F,0xE0,0x20, + 0x00,0x20,0x00,0x3F,0x80,0x20,0x80,0x20,0x80,0x40,0x80,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_228_233_233[45] U8G_FONT_SECTION("fontpage_228_233_233") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE9,0xE9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0xA2,0x00,0xA7,0xE0,0xFA,0xA0,0xA2, + 0xA0,0x32,0xA0,0x64,0xA0,0xA9,0x20,0x22,0x20,0x25,0x20,0x28,0xC0}; +const u8g_fntpgm_uint8_t fontpage_231_135_135[45] U8G_FONT_SECTION("fontpage_231_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x88,0x40,0x52,0x80,0x0C, + 0x00,0x2A,0x80,0xDF,0x40,0x04,0x00,0xFF,0xE0,0x04,0x00,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_234_168_168[45] U8G_FONT_SECTION("fontpage_234_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x44,0x40,0x44,0x40,0x7F,0xC0,0x44, + 0x40,0x44,0x40,0x7F,0xC0,0x44,0x40,0x44,0x40,0x84,0x40,0x84,0xC0}; +const u8g_fntpgm_uint8_t fontpage_234_204_204[45] U8G_FONT_SECTION("fontpage_234_204_204") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x44,0x40,0x7F,0xC0,0x44,0x40,0x7F, + 0xC0,0x0A,0x00,0x31,0x80,0xD1,0x60,0x11,0x00,0x21,0x00,0x41,0x00}; +const u8g_fntpgm_uint8_t fontpage_236_253_253[34] U8G_FONT_SECTION("fontpage_236_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x08,0x0B,0x0B,0x0C,0x02,0xFF,0x10,0x20,0xFF,0x81,0x81,0xFF,0x81,0x81,0x81, + 0xFF,0x81}; +const u8g_fntpgm_uint8_t fontpage_237_132_132[45] U8G_FONT_SECTION("fontpage_237_132_132") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x22,0x00,0x42,0x00,0xF7,0xC0,0x98,0x40,0x90, + 0x40,0xF4,0x40,0x92,0x40,0x92,0x40,0x90,0x40,0xF0,0x40,0x91,0x80}; +const u8g_fntpgm_uint8_t fontpage_237_227_227[45] U8G_FONT_SECTION("fontpage_237_227_227") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE3,0xE3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF9,0x00,0xA1,0x00,0xF9,0xE0,0x8A,0x00,0xFA, + 0x80,0xA0,0x40,0xFC,0x00,0x00,0x00,0x7F,0xC0,0x4A,0x40,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_237_244_244[45] U8G_FONT_SECTION("fontpage_237_244_244") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF4,0xF4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x04,0x00,0x3F,0x80,0x20, + 0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x20,0x80,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_238_160_160[45] U8G_FONT_SECTION("fontpage_238_160_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x07,0xE0,0xF4,0x20,0x97,0xE0,0xF4,0x80,0x94, + 0x80,0x97,0xE0,0xF4,0x80,0x94,0x80,0xF4,0xA0,0x96,0x60,0x04,0x20}; +const u8g_fntpgm_uint8_t fontpage_240_141_141[45] U8G_FONT_SECTION("fontpage_240_141_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x02,0x00,0xFA,0x00,0x23,0xE0,0x24,0x20,0x79, + 0x40,0xC9,0x00,0x49,0x00,0x49,0x00,0x7A,0x80,0x4C,0x40,0x08,0x20}; +const u8g_fntpgm_uint8_t fontpage_241_186_186[45] U8G_FONT_SECTION("fontpage_241_186_186") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBA,0xBA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x01,0x00,0xFF,0xE0,0x2A,0x20,0x22,0x80,0x77, + 0xE0,0xD4,0x80,0x5F,0xE0,0x54,0x80,0x77,0xE0,0x54,0x80,0x07,0xE0}; +const u8g_fntpgm_uint8_t fontpage_243_251_251[45] U8G_FONT_SECTION("fontpage_243_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xE3,0xE0,0x24,0x20,0xFA,0x40,0x21, + 0x80,0x36,0x80,0x29,0xE0,0x62,0x20,0xA5,0x40,0x20,0x80,0x27,0x00}; +const u8g_fntpgm_uint8_t fontpage_244_205_205[45] U8G_FONT_SECTION("fontpage_244_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xEF,0xE0,0x21,0x00,0xFF,0xC0,0x21, + 0x00,0x2F,0xE0,0x34,0x40,0x6F,0xC0,0xA4,0x40,0x27,0xC0,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_245_239_239[45] U8G_FONT_SECTION("fontpage_245_239_239") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEF,0xEF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x81,0x00,0x45,0x20,0xF7,0xE0,0x00,0x00,0xAF, + 0xE0,0xA1,0x00,0xAF,0xE0,0x4A,0xA0,0x6A,0xA0,0x8A,0xA0,0x08,0x60}; +const u8g_fntpgm_uint8_t fontpage_246_201_201[45] U8G_FONT_SECTION("fontpage_246_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x7B,0xE0,0x94,0x80,0x7F,0xC0,0x04, + 0x00,0xFF,0xE0,0x01,0x00,0x7F,0xC0,0x11,0x00,0x09,0x00,0x03,0x00}; +const u8g_fntpgm_uint8_t fontpage_247_161_161[45] U8G_FONT_SECTION("fontpage_247_161_161") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA1,0xA1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x3D,0xE0,0x52,0x80,0xFF,0xE0,0x80, + 0x20,0x3F,0x80,0x20,0x80,0x3F,0xC0,0x20,0x40,0x20,0x40,0x3F,0xC0}; +const u8g_fntpgm_uint8_t fontpage_247_177_177[45] U8G_FONT_SECTION("fontpage_247_177_177") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB1,0xB1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x3D,0xE0,0x4A,0x80,0x94,0x40,0x7F, + 0xC0,0x12,0x40,0x3B,0xC0,0x56,0x40,0x93,0xC0,0x12,0x40,0x13,0xC0}; +const u8g_fntpgm_uint8_t fontpage_249_251_251[45] U8G_FONT_SECTION("fontpage_249_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x09,0x0B,0x16,0x0C,0x01,0xFF,0x03,0x80,0xFC,0x00,0x11,0x00,0x7E,0x00,0x08, + 0x00,0x11,0x00,0xFF,0x80,0x08,0x80,0x2A,0x00,0x49,0x00,0x98,0x80}; +const u8g_fntpgm_uint8_t fontpage_250_133_133[45] U8G_FONT_SECTION("fontpage_250_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xC0,0x41,0x00,0xF1,0x00,0x21, + 0x00,0x51,0x00,0xE9,0x00,0x01,0x00,0x51,0x00,0xA9,0x00,0xAF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_250_162_162[45] U8G_FONT_SECTION("fontpage_250_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0x91, + 0x20,0x3E,0x00,0x08,0x80,0x7F,0xC0,0x04,0x40,0x24,0x80,0xCC,0x60}; +const u8g_fntpgm_uint8_t fontpage_250_171_171[45] U8G_FONT_SECTION("fontpage_250_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x51,0x40,0x5D,0x80,0x51,0x20,0xFD, + 0xE0,0x08,0x80,0x3F,0x00,0x08,0x80,0x7F,0xC0,0x24,0x80,0xCC,0x60}; +const u8g_fntpgm_uint8_t fontpage_250_176_176[45] U8G_FONT_SECTION("fontpage_250_176_176") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB0,0xB0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xE0,0x55,0x20,0xF5,0x20,0x25, + 0x20,0x57,0xE0,0xED,0x20,0x05,0x20,0x55,0x20,0xAF,0xE0,0xAC,0x20}; +const u8g_fntpgm_uint8_t fontpage_250_194_194[45] U8G_FONT_SECTION("fontpage_250_194_194") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC2,0xC2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x23,0xC0,0x54,0x40,0xF2,0x80,0x21, + 0x00,0x52,0x80,0xEC,0x60,0x01,0x00,0x50,0x80,0xAB,0x00,0x80,0xC0}; +const u8g_fntpgm_uint8_t fontpage_250_241_242[73] U8G_FONT_SECTION("fontpage_250_241_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF1,0xF2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x20,0x80,0x57,0xE0,0xF1,0x00,0x22, + 0x40,0x57,0xA0,0xE8,0x00,0x02,0x80,0x52,0xA0,0xAC,0xA0,0xA8,0x60,0x0B,0x0B,0x16, + 0x0C,0x00,0xFF,0x21,0x00,0x21,0x00,0x52,0x40,0xF7,0x80,0x21,0x40,0x57,0xE0,0xE8, + 0x80,0x02,0xC0,0x54,0xA0,0xA8,0xA0,0xA9,0x80}; +const u8g_fntpgm_uint8_t fontpage_251_160_160[45] U8G_FONT_SECTION("fontpage_251_160_160") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA0,0xA0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x23,0xC0,0x22,0x40,0x57,0x80,0xF0,0x80,0x2F, + 0xE0,0x51,0x20,0xED,0x40,0x03,0x80,0x55,0x40,0xA9,0x20,0xAF,0x20}; +const u8g_fntpgm_uint8_t fontpage_251_178_178[45] U8G_FONT_SECTION("fontpage_251_178_178") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB2,0xB2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xE0,0x24,0x20,0x55,0x60,0xF4,0xA0,0x27, + 0xE0,0x54,0xA0,0xEF,0xE0,0x05,0x20,0x55,0xE0,0xAC,0x20,0xAC,0x60}; +const u8g_fntpgm_uint8_t fontpage_251_210_210[45] U8G_FONT_SECTION("fontpage_251_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x20,0x27,0xA0,0x51,0x40,0xFF,0xE0,0x21, + 0x00,0x53,0xE0,0xEE,0x20,0x03,0xE0,0x52,0x20,0xAB,0xE0,0xAA,0x20}; +const u8g_fntpgm_uint8_t fontpage_251_218_218[45] U8G_FONT_SECTION("fontpage_251_218_218") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDA,0xDA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xC0,0x54,0x40,0xF7,0xC0,0x24, + 0x40,0x57,0xC0,0xE9,0x20,0x07,0x40,0x53,0x80,0xAD,0x40,0xAB,0x20}; +const u8g_fntpgm_uint8_t fontpage_251_232_232[45] U8G_FONT_SECTION("fontpage_251_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x2F,0xE0,0x58,0x20,0xFF,0xE0,0x28, + 0x00,0x5F,0xE0,0xEA,0xA0,0x0F,0xE0,0x5A,0xA0,0xAA,0xA0,0xAA,0x60}; +const u8g_fntpgm_uint8_t fontpage_252_174_174[45] U8G_FONT_SECTION("fontpage_252_174_174") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAE,0xAE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xE0,0x44,0x20,0xFB,0xE0,0x24, + 0x80,0x5D,0xE0,0xF5,0x20,0x05,0xE0,0x55,0x20,0xAD,0xE0,0xA5,0x20}; +const u8g_fntpgm_uint8_t fontpage_252_189_189[45] U8G_FONT_SECTION("fontpage_252_189_189") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBD,0xBD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x27,0xE0,0x55,0x60,0xF6,0xA0,0x25, + 0x20,0x56,0xA0,0xEF,0xE0,0x01,0x40,0x56,0xA0,0xAA,0x60,0xA9,0xC0}; +const u8g_fntpgm_uint8_t fontpage_252_252_252[45] U8G_FONT_SECTION("fontpage_252_252_252") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4A,0x40,0x4D,0xA0,0x8A,0x40,0xFD,0xA0,0x28, + 0x00,0x4F,0xE0,0xFA,0x40,0x0D,0xA0,0x5A,0x40,0xAD,0xA0,0xAF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_253_140_140[45] U8G_FONT_SECTION("fontpage_253_140_140") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x4F,0xE0,0x91,0x00,0xEF,0xE0,0x2A, + 0xA0,0x5F,0xE0,0xF4,0x40,0x07,0xC0,0x54,0x40,0xAF,0xC0,0xAC,0x60}; +const u8g_fntpgm_uint8_t fontpage_253_162_162[45] U8G_FONT_SECTION("fontpage_253_162_162") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA2,0xA2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x00,0x27,0xC0,0x41,0x00,0x51,0x00,0xE1, + 0x00,0x21,0x00,0x41,0x00,0xF1,0x00,0x01,0x00,0x31,0x00,0xCF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_254_238_238[45] U8G_FONT_SECTION("fontpage_254_238_238") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x4A,0x40,0x7F,0xC0,0x04,0x00,0xFF, + 0xE0,0x20,0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_254_242_242[45] U8G_FONT_SECTION("fontpage_254_242_242") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF2,0xF2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xE0,0x49,0x20,0x7F,0xE0,0x04,0x40,0x3F, + 0x80,0x05,0x00,0xFF,0xE0,0x30,0x80,0xDF,0x80,0x10,0x80,0x1F,0x80}; +const u8g_fntpgm_uint8_t fontpage_256_240_240[45] U8G_FONT_SECTION("fontpage_256_240_240") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF9,0x00,0x57,0xE0,0x56,0xA0,0x75,0x20,0x56, + 0xA0,0x77,0xE0,0x51,0x00,0x52,0xC0,0xFE,0x20,0x12,0x60,0x11,0xC0}; +const u8g_fntpgm_uint8_t fontpage_259_234_234[34] U8G_FONT_SECTION("fontpage_259_234_234") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xEA,0xEA,0x00,0x0A,0xFF,0x00, + 0x00,0x07,0x0B,0x0B,0x0C,0x02,0xFF,0x20,0xFE,0x82,0x82,0xFE,0x82,0xFE,0x82,0x82, + 0xFE,0x82}; +const u8g_fntpgm_uint8_t fontpage_267_205_205[45] U8G_FONT_SECTION("fontpage_267_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFF,0xE0,0x91,0x00,0xF9,0xE0,0x8A, + 0x80,0xFC,0x40,0x90,0x00,0xFF,0xC0,0x4A,0x40,0x4A,0x40,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_272_204_204[45] U8G_FONT_SECTION("fontpage_272_204_204") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x40,0x00,0x80,0x00,0x10,0x00,0x2F, + 0xE0,0x60,0x80,0xA0,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x23,0x80}; +const u8g_fntpgm_uint8_t fontpage_272_232_232[45] U8G_FONT_SECTION("fontpage_272_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x04,0x00,0x3F,0x80,0x04, + 0x00,0xFF,0xE0,0x0A,0x40,0x12,0x80,0x31,0x00,0xD4,0x80,0x18,0x60}; +const u8g_fntpgm_uint8_t fontpage_273_171_171[45] U8G_FONT_SECTION("fontpage_273_171_171") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAB,0xAB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x80,0x20,0x80,0xFF,0xE0,0x14,0xA0,0x2C, + 0x80,0x77,0xE0,0xAD,0x40,0x25,0x40,0x24,0x80,0x29,0x40,0x36,0x20}; +const u8g_fntpgm_uint8_t fontpage_273_197_197[45] U8G_FONT_SECTION("fontpage_273_197_197") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC5,0xC5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0x9F,0xE0,0x51,0x00,0x31,0x00,0xD7, + 0xC0,0x12,0x00,0xFF,0xE0,0x0C,0x40,0x32,0x80,0xD1,0x00,0x18,0xE0}; +const u8g_fntpgm_uint8_t fontpage_273_221_221[45] U8G_FONT_SECTION("fontpage_273_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x51,0x00,0x7F,0xE0,0x11,0x00,0xF1,0x00,0x57, + 0xC0,0x84,0x00,0xFF,0xE0,0x14,0x80,0x33,0x00,0xD5,0x80,0x18,0x60}; +const u8g_fntpgm_uint8_t fontpage_274_135_135[45] U8G_FONT_SECTION("fontpage_274_135_135") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x87,0x87,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x00,0x27,0xE0,0xF8,0x00,0x17,0xC0,0x2C, + 0x40,0x77,0xC0,0xAC,0x40,0x27,0xC0,0x2C,0x40,0x33,0x80,0x2C,0x60}; +const u8g_fntpgm_uint8_t fontpage_275_210_210[45] U8G_FONT_SECTION("fontpage_275_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x00,0xFF,0x10,0x00,0x1F,0x00,0x22,0x00,0x7F,0xC0,0xA4, + 0x40,0x3F,0xC0,0x24,0x40,0x3F,0xC0,0x24,0x40,0x45,0x40,0x80,0x80}; +const u8g_fntpgm_uint8_t fontpage_276_136_136[45] U8G_FONT_SECTION("fontpage_276_136_136") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x10,0x80,0xFC,0x80,0x00,0x80,0x7F, + 0xE0,0x00,0x80,0x78,0x80,0x00,0x80,0x78,0x80,0x48,0x80,0x78,0x80}; +const u8g_fntpgm_uint8_t fontpage_276_138_138[45] U8G_FONT_SECTION("fontpage_276_138_138") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8A,0x8A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xC0,0xF2,0x40,0x02,0x40,0xF2,0x40,0x02, + 0x40,0xFF,0xC0,0x02,0x40,0xF2,0x40,0x92,0x60,0xF2,0x60,0x92,0x20}; +const u8g_fntpgm_uint8_t fontpage_276_152_152[45] U8G_FONT_SECTION("fontpage_276_152_152") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x98,0x98,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x00,0xF7,0xC0,0x00,0x40,0xF0,0x40,0x07, + 0xC0,0xF4,0x40,0x04,0x00,0xF4,0x00,0x94,0x20,0xF4,0x20,0x93,0xE0}; +const u8g_fntpgm_uint8_t fontpage_276_173_173[45] U8G_FONT_SECTION("fontpage_276_173_173") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAD,0xAD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0x80,0xF4,0x80,0x04,0x80,0xF4,0xE0,0x08, + 0x00,0xF7,0xC0,0x04,0x40,0xF2,0x80,0x91,0x00,0xF2,0x80,0x9C,0x60}; +const u8g_fntpgm_uint8_t fontpage_276_230_230[45] U8G_FONT_SECTION("fontpage_276_230_230") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE6,0xE6,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0xC0,0xF0,0xA0,0x0F,0xE0,0xF0,0x80,0x07, + 0x80,0xF2,0x80,0x02,0x80,0xF2,0x80,0x93,0xA0,0xFC,0x60,0x90,0x20}; +const u8g_fntpgm_uint8_t fontpage_277_141_141[45] U8G_FONT_SECTION("fontpage_277_141_141") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8D,0x8D,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xE0,0xF9,0x20,0x05,0x20,0xF5,0x20,0x02, + 0xE0,0xF4,0x40,0x03,0x00,0xF2,0xA0,0x96,0x20,0xFA,0x40,0x91,0xC0}; +const u8g_fntpgm_uint8_t fontpage_277_164_164[45] U8G_FONT_SECTION("fontpage_277_164_164") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA4,0xA4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xC0,0xF4,0x40,0x04,0x40,0xF7,0xC0,0x00, + 0x00,0xF7,0xC0,0x01,0x00,0xFF,0xE0,0x92,0x80,0xF4,0x40,0x98,0x20}; +const u8g_fntpgm_uint8_t fontpage_277_191_191[45] U8G_FONT_SECTION("fontpage_277_191_191") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x47,0xE0,0xF4,0x20,0x05,0x20,0xF7,0xA0,0x05, + 0x20,0xF7,0xE0,0x04,0x20,0xF7,0xA0,0x96,0xA0,0xF7,0xA0,0x98,0x60}; +const u8g_fntpgm_uint8_t fontpage_277_203_203[45] U8G_FONT_SECTION("fontpage_277_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0xFF,0xE0,0x01,0x00,0xF7,0xC0,0x01, + 0x00,0xFF,0xE0,0x04,0x40,0xF7,0xC0,0x94,0x40,0xF7,0xC0,0x94,0x40}; +const u8g_fntpgm_uint8_t fontpage_278_240_240[45] U8G_FONT_SECTION("fontpage_278_240_240") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x40,0xFF,0xE0,0x01,0x00,0xF7,0xC0,0x01, + 0x00,0xFF,0xE0,0x04,0xA0,0xFF,0xE0,0x94,0xA0,0xFE,0x40,0x95,0xA0}; +const u8g_fntpgm_uint8_t fontpage_279_128_128[45] U8G_FONT_SECTION("fontpage_279_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0xFF,0xE0,0x01,0x00,0xFF,0xE0,0x0A, + 0xA0,0xFF,0xE0,0x04,0x40,0xF7,0xC0,0x94,0x40,0xF7,0xC0,0x9C,0x60}; +const u8g_fntpgm_uint8_t fontpage_279_138_138[45] U8G_FONT_SECTION("fontpage_279_138_138") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8A,0x8A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x44,0x40,0xAE,0xA0,0x40,0x40,0xAE,0xA0,0xEA, + 0xE0,0x5E,0x40,0xA0,0xA0,0x1F,0xC0,0x69,0x00,0x06,0x00,0x79,0xE0}; +const u8g_fntpgm_uint8_t fontpage_281_199_199[45] U8G_FONT_SECTION("fontpage_281_199_199") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x88,0x00,0x5F,0xC0,0x22,0x40,0xFF,0x00,0x61, + 0xC0,0x3F,0x00,0x21,0x00,0x3F,0x00,0x21,0x00,0x3F,0x00,0xE1,0xC0}; +const u8g_fntpgm_uint8_t fontpage_283_221_221[45] U8G_FONT_SECTION("fontpage_283_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7B,0xE0,0x4A,0x00,0x4A,0x00,0x7B,0xE0,0x12, + 0x20,0x52,0x20,0x5A,0x20,0x53,0xE0,0x52,0x00,0x5E,0x00,0xE3,0xE0}; +const u8g_fntpgm_uint8_t fontpage_285_202_202[45] U8G_FONT_SECTION("fontpage_285_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x04,0x00,0x3F,0x80,0x24, + 0x80,0x3F,0x80,0x24,0x80,0x3F,0x80,0x04,0x00,0xFF,0xE0,0x04,0x00}; +const u8g_fntpgm_uint8_t fontpage_285_223_223[45] U8G_FONT_SECTION("fontpage_285_223_223") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDF,0xDF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0xFA,0x00,0x23,0xE0,0xFD,0x20,0xA9, + 0x40,0xF9,0x00,0xA9,0x00,0xF9,0x80,0x22,0x80,0xFA,0x40,0x24,0x20}; +const u8g_fntpgm_uint8_t fontpage_285_248_248[45] U8G_FONT_SECTION("fontpage_285_248_248") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0xF8,0x80,0x23,0xE0,0xFA,0xA0,0xAA, + 0xA0,0xFA,0xA0,0xAB,0xE0,0xFA,0xA0,0x22,0xA0,0xFB,0xE0,0x22,0x20}; +const u8g_fntpgm_uint8_t fontpage_286_137_137[45] U8G_FONT_SECTION("fontpage_286_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x80,0x7D,0x40,0x11,0x00,0xFF,0xE0,0x11, + 0x00,0xFF,0x20,0x55,0x40,0x7C,0x80,0x54,0xA0,0xFF,0x60,0x12,0x20}; +const u8g_fntpgm_uint8_t fontpage_286_175_175[45] U8G_FONT_SECTION("fontpage_286_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x23,0xC0,0xFA,0x40,0x23,0xC0,0xF8,0x00,0xAF, + 0xE0,0xFA,0x40,0xAB,0xC0,0xFA,0x40,0x22,0xE0,0xFF,0x40,0x20,0x40}; +const u8g_fntpgm_uint8_t fontpage_286_184_184[45] U8G_FONT_SECTION("fontpage_286_184_184") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB8,0xB8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0xFA,0x80,0x24,0x60,0xFB,0x80,0xAE, + 0x20,0xFA,0xA0,0xAE,0xA0,0xFA,0xA0,0x2E,0xA0,0xFA,0x20,0x2A,0x60}; +const u8g_fntpgm_uint8_t fontpage_286_201_201[45] U8G_FONT_SECTION("fontpage_286_201_201") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC9,0xC9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0xFF,0xE0,0x25,0x40,0xFF,0xC0,0xAD, + 0x40,0xFF,0xC0,0xA9,0x60,0xFF,0xE0,0x24,0x40,0xFA,0x40,0x20,0xC0}; +const u8g_fntpgm_uint8_t fontpage_287_209_209[45] U8G_FONT_SECTION("fontpage_287_209_209") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD1,0xD1,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0xC0,0x27,0x00,0x24,0x00,0x07,0xE0,0xE4, + 0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x28,0x80,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_287_212_212[45] U8G_FONT_SECTION("fontpage_287_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x40,0x60,0x27,0x80,0x24,0x00,0x07,0xE0,0xE6, + 0x20,0x25,0x40,0x24,0x80,0x29,0x40,0x26,0x20,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_128_128[45] U8G_FONT_SECTION("fontpage_288_128_128") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x8F,0xC0,0x48,0x40,0x4F,0xC0,0x08,0x40,0xCF, + 0xC0,0x48,0x00,0x4B,0x40,0x48,0x80,0x4E,0x40,0xB0,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_159_159[45] U8G_FONT_SECTION("fontpage_288_159_159") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9F,0x9F,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x3F,0xE0,0x21,0x00,0x0F,0xE0,0xE9, + 0x20,0x2F,0xE0,0x23,0x80,0x25,0x40,0x29,0x20,0x51,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_163_163[45] U8G_FONT_SECTION("fontpage_288_163_163") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA3,0xA3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x2F,0xE0,0x25,0x40,0x07,0xC0,0xE5, + 0x40,0x27,0xC0,0x21,0x00,0x2F,0xE0,0x21,0x00,0x50,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_178_178[45] U8G_FONT_SECTION("fontpage_288_178_178") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xB2,0xB2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x43,0x00,0x24,0x80,0x27,0xE0,0x0C,0x80,0xF7, + 0xE0,0x24,0x80,0x27,0xE0,0x24,0x80,0x27,0xE0,0x54,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_203_203[45] U8G_FONT_SECTION("fontpage_288_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4F,0xE0,0x29,0x20,0x2F,0xE0,0x05,0x40,0xE7, + 0xC0,0x25,0x40,0x27,0xC0,0x21,0x00,0x2F,0xE0,0x51,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_212_212[45] U8G_FONT_SECTION("fontpage_288_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x41,0x00,0x27,0xC0,0x21,0x00,0x0F,0xE0,0xE2, + 0x80,0x2F,0xE0,0x21,0x00,0x2F,0xE0,0x21,0x00,0x51,0x00,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_288_248_248[45] U8G_FONT_SECTION("fontpage_288_248_248") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x4E,0xE0,0x2A,0xA0,0x2E,0xE0,0x08,0x80,0xEA, + 0xA0,0x2F,0xE0,0x22,0x80,0x2F,0xE0,0x22,0x40,0x54,0x20,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_289_132_132[45] U8G_FONT_SECTION("fontpage_289_132_132") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x84,0x84,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x9F,0xC0,0x55,0x40,0x5F,0xC0,0x00,0x00,0xFF, + 0xE0,0x28,0x80,0x2F,0xA0,0x27,0x40,0x2A,0x80,0x52,0x40,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_289_138_138[45] U8G_FONT_SECTION("fontpage_289_138_138") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8A,0x8A,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x42,0x00,0x2F,0xC0,0x28,0x40,0x1F,0xE0,0xF4, + 0xA0,0x29,0x40,0x3F,0xE0,0x22,0x00,0x27,0xC0,0x58,0xC0,0x8F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_289_232_232[45] U8G_FONT_SECTION("fontpage_289_232_232") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE8,0xE8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0xE0,0xFF,0x20,0x45,0x20,0x29,0x40,0xFF, + 0x80,0x01,0x40,0x7D,0x20,0x45,0x20,0x45,0xA0,0x7D,0x40,0x45,0x00}; +const u8g_fntpgm_uint8_t fontpage_291_203_203[45] U8G_FONT_SECTION("fontpage_291_203_203") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCB,0xCB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x2A,0xA0,0xAF,0xE0,0x71,0x00,0xFF, + 0xE0,0x22,0x80,0x77,0xE0,0x69,0x00,0xA7,0xE0,0xA1,0x00,0x21,0x00}; +const u8g_fntpgm_uint8_t fontpage_291_205_205[45] U8G_FONT_SECTION("fontpage_291_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0x24,0x80,0x3F, + 0x80,0x24,0x80,0x3F,0x80,0x04,0x00,0x7F,0xC0,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_291_207_207[45] U8G_FONT_SECTION("fontpage_291_207_207") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCF,0xCF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0xFF, + 0xE0,0x24,0x80,0x3F,0x80,0x24,0x80,0x7F,0xC0,0x04,0x00,0xFF,0xE0}; +const u8g_fntpgm_uint8_t fontpage_291_221_221[45] U8G_FONT_SECTION("fontpage_291_221_221") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDD,0xDD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x20,0x80,0x50,0x80,0x88,0x80,0x78,0x80,0x27, + 0xE0,0xF8,0x80,0x20,0x80,0xA8,0x80,0x70,0x80,0x38,0x80,0xC0,0x80}; +const u8g_fntpgm_uint8_t fontpage_292_149_149[45] U8G_FONT_SECTION("fontpage_292_149_149") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x95,0x95,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x27,0xC0,0x31,0x40,0x49,0x40,0xF9,0x40,0x21, + 0x40,0xFF,0xC0,0x22,0x40,0xAA,0x40,0x72,0x40,0x3A,0x40,0xC7,0xE0}; +const u8g_fntpgm_uint8_t fontpage_294_175_175[45] U8G_FONT_SECTION("fontpage_294_175_175") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAF,0xAF,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x40,0x57,0xE0,0x8A,0x40,0x7A,0x40,0x27, + 0xE0,0xF8,0x00,0x23,0xE0,0xAA,0x20,0x73,0xE0,0x3A,0x20,0xE3,0xE0}; +const u8g_fntpgm_uint8_t fontpage_294_245_245[45] U8G_FONT_SECTION("fontpage_294_245_245") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF5,0xF5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2C,0x80,0x25,0xE0,0x54,0xA0,0xFB,0xE0,0x2C, + 0xA0,0xF7,0xE0,0x24,0x80,0xB7,0xE0,0x6C,0x80,0x34,0x80,0xCB,0xE0}; +const u8g_fntpgm_uint8_t fontpage_298_247_247[45] U8G_FONT_SECTION("fontpage_298_247_247") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xF7,0xF7,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0x3F,0x80,0x20,0x00,0x3F,0x00,0x20,0x00,0x3F, + 0x00,0x20,0x00,0xFF,0xC0,0x24,0x80,0x23,0x00,0x29,0x00,0x30,0xC0}; +const u8g_fntpgm_uint8_t fontpage_299_137_137[45] U8G_FONT_SECTION("fontpage_299_137_137") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x89,0x89,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFB,0xE0,0x8A,0x20,0xFB,0xE0,0x8A,0x20,0xFB, + 0xE0,0x82,0x20,0xBF,0xA0,0x8A,0x20,0x92,0x20,0xA2,0x20,0x86,0xE0}; +const u8g_fntpgm_uint8_t fontpage_299_139_139[45] U8G_FONT_SECTION("fontpage_299_139_139") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8B,0x8B,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFB,0xE0,0x8A,0x20,0xFB,0xE0,0x8A,0x20,0xFB, + 0xE0,0x80,0x20,0x9F,0x20,0x8A,0x20,0xBF,0xA0,0x8A,0x20,0x92,0xE0}; +const u8g_fntpgm_uint8_t fontpage_299_147_147[45] U8G_FONT_SECTION("fontpage_299_147_147") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x93,0x93,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFB,0xE0,0x8A,0x20,0xFB,0xE0,0x8A,0x20,0xFB, + 0xE0,0x9F,0x20,0x91,0x20,0x9F,0x20,0x91,0x20,0x9F,0x20,0x80,0xE0}; +const u8g_fntpgm_uint8_t fontpage_299_220_220[45] U8G_FONT_SECTION("fontpage_299_220_220") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDC,0xDC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFB,0xE0,0x8A,0x20,0xFB,0xE0,0x8A,0x20,0xF5, + 0xE0,0xAA,0xA0,0xBB,0xA0,0xAA,0xA0,0xBB,0xA0,0x8A,0x20,0xB2,0x60}; +const u8g_fntpgm_uint8_t fontpage_300_205_205[45] U8G_FONT_SECTION("fontpage_300_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF2,0x00,0x93,0xE0,0xA6,0x40,0xC1,0x80,0xA6, + 0x60,0x91,0x00,0x97,0xE0,0xD5,0x00,0xAF,0xE0,0x81,0x00,0x81,0x00}; +const u8g_fntpgm_uint8_t fontpage_300_228_228[45] U8G_FONT_SECTION("fontpage_300_228_228") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE4,0xE4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF1,0x00,0x92,0x80,0xA4,0x40,0xCB,0xA0,0xA1, + 0x00,0x9F,0xE0,0x91,0x00,0xE5,0x40,0x89,0x20,0x91,0x20,0x83,0x00}; +const u8g_fntpgm_uint8_t fontpage_301_142_142[45] U8G_FONT_SECTION("fontpage_301_142_142") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x8E,0x8E,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF8,0x80,0x98,0xA0,0xAE,0xC0,0xC8,0xA0,0xAE, + 0xE0,0x92,0x00,0x97,0xC0,0xF4,0x40,0xA7,0xC0,0x84,0x40,0x87,0xC0}; +const u8g_fntpgm_uint8_t fontpage_301_217_217[45] U8G_FONT_SECTION("fontpage_301_217_217") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD9,0xD9,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x2A,0x80,0x3F,0xE0,0x6A,0x80,0xBF,0xC0,0x2A, + 0x80,0x3F,0xE0,0x00,0x00,0x3F,0xC0,0x08,0x80,0x07,0x00,0x78,0xE0}; +const u8g_fntpgm_uint8_t fontpage_301_226_226[45] U8G_FONT_SECTION("fontpage_301_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x80,0xFD,0x40,0x55,0xE0,0x6F,0x40,0x55, + 0xE0,0x7D,0x40,0x21,0x40,0xFD,0xE0,0xAD,0x40,0xB5,0x40,0x8D,0xE0}; +const u8g_fntpgm_uint8_t fontpage_301_251_251[45] U8G_FONT_SECTION("fontpage_301_251_251") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFB,0xFB,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xC0,0x04,0x00,0xFF,0xE0,0xA4,0xA0,0x7F, + 0xC0,0x44,0x40,0x7F,0xC0,0x44,0x40,0x7F,0xC0,0x04,0x20,0x07,0xE0}; +const u8g_fntpgm_uint8_t fontpage_302_210_210[45] U8G_FONT_SECTION("fontpage_302_210_210") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD2,0xD2,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0x7F,0xC0,0x04,0x00,0x3F,0x80,0x04, + 0x00,0xFF,0xE0,0x10,0x80,0x1F,0x80,0x10,0x80,0x1F,0x80,0x10,0x80}; +const u8g_fntpgm_uint8_t fontpage_302_222_222[45] U8G_FONT_SECTION("fontpage_302_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x0A,0x00,0x0A,0x00,0xFB,0xE0,0x0A,0x00,0x0A, + 0x00,0x7B,0xC0,0x0A,0x00,0x0A,0x00,0xFB,0xE0,0x0A,0x00,0x0A,0x00}; +const u8g_fntpgm_uint8_t fontpage_302_226_226[45] U8G_FONT_SECTION("fontpage_302_226_226") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xE2,0xE2,0x00,0x0A,0xFF,0x00, + 0x00,0x0A,0x0B,0x16,0x0C,0x01,0xFF,0xFF,0xC0,0x08,0x00,0x10,0x00,0xFF,0xC0,0x92, + 0x40,0x9E,0x40,0x92,0x40,0x9E,0x40,0x92,0x40,0xFF,0xC0,0x80,0x40}; +const u8g_fntpgm_uint8_t fontpage_304_133_133[45] U8G_FONT_SECTION("fontpage_304_133_133") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x85,0x85,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x07,0xE0,0xF9,0x00,0x27,0xE0,0x24,0x20,0x27, + 0xE0,0x24,0x20,0x3F,0xE0,0xC4,0x20,0x07,0xE0,0x02,0x40,0x0C,0x20}; +const u8g_fntpgm_uint8_t fontpage_304_144_144[45] U8G_FONT_SECTION("fontpage_304_144_144") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x90,0x90,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xFF,0xE0,0x91,0x00,0x67,0xC0,0x24,0x40,0xFF, + 0xC0,0x24,0x40,0x27,0xC0,0x24,0x40,0x27,0xC0,0x22,0x80,0xEC,0x60}; +const u8g_fntpgm_uint8_t fontpage_304_205_205[45] U8G_FONT_SECTION("fontpage_304_205_205") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCD,0xCD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x23,0xE0,0xFC,0x80,0xA7,0xE0,0x3A,0x20,0x4B, + 0xE0,0xB2,0x20,0x4B,0xE0,0xFE,0x20,0x4B,0xE0,0x79,0x40,0x4E,0x20}; +const u8g_fntpgm_uint8_t fontpage_304_222_222[45] U8G_FONT_SECTION("fontpage_304_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xAB,0xE0,0x70,0x80,0x23,0xE0,0xFA,0x20,0x73, + 0xE0,0xAA,0x20,0x23,0xE0,0xFA,0x20,0x23,0xE0,0x51,0x40,0x8E,0x20}; +const u8g_fntpgm_uint8_t fontpage_305_168_168[45] U8G_FONT_SECTION("fontpage_305_168_168") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xC0,0x21,0x40,0x2E,0x40,0x24,0x40,0x3F, + 0x40,0x35,0x40,0x3F,0x40,0x25,0x40,0x27,0x60,0x5C,0xA0,0x88,0x20}; +const u8g_fntpgm_uint8_t fontpage_305_253_253[45] U8G_FONT_SECTION("fontpage_305_253_253") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xFD,0xFD,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x22,0x00,0x52,0x00,0xAB,0xE0,0xFC,0x20,0x8B, + 0xA0,0xFA,0xA0,0x8B,0xA0,0xFA,0x40,0x92,0x20,0xAA,0x20,0xC9,0xE0}; +const u8g_fntpgm_uint8_t fontpage_306_152_152[45] U8G_FONT_SECTION("fontpage_306_152_152") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x98,0x98,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x21,0x00,0x52,0x80,0xAC,0x40,0xF8,0x20,0x8F, + 0xC0,0xF9,0x00,0x8F,0xE0,0xF9,0x00,0x95,0x40,0xB9,0x20,0xCB,0x00}; +const u8g_fntpgm_uint8_t fontpage_307_172_172[45] U8G_FONT_SECTION("fontpage_307_172_172") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xAC,0xAC,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x3F,0xC0,0x24,0x00,0x3F,0x80,0x24,0x00,0x3F, + 0x80,0x24,0x00,0x3F,0xE0,0x00,0x20,0x55,0x20,0x4A,0xA0,0x8A,0xC0}; +const u8g_fntpgm_uint8_t fontpage_308_197_197[45] U8G_FONT_SECTION("fontpage_308_197_197") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC5,0xC5,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x7F,0xE0,0x54,0x00,0x7D,0xC0,0x55,0x40,0x7D, + 0xC0,0x54,0x00,0x7F,0xE0,0x5E,0xA0,0xAF,0xE0,0xAC,0x00,0x17,0xE0}; +const u8g_fntpgm_uint8_t fontpage_309_212_212[45] U8G_FONT_SECTION("fontpage_309_212_212") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD4,0xD4,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x79,0x40,0x6B,0xE0,0x5A,0xA0,0xFF,0xE0,0x86, + 0xA0,0x7F,0xE0,0x4A,0x40,0x7B,0xC0,0x4A,0x40,0x79,0x80,0x4F,0xE0}; +const u8g_fntpgm_uint8_t fontpage_309_216_216[45] U8G_FONT_SECTION("fontpage_309_216_216") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x00,0x00,0x1F,0x00,0x11, + 0x00,0x7F,0xC0,0x40,0x40,0x5F,0x40,0x51,0x40,0x5F,0x40,0x40,0xC0}; +const u8g_fntpgm_uint8_t fontpage_317_195_195[45] U8G_FONT_SECTION("fontpage_317_195_195") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xC3,0xC3,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x11,0x00,0xFF,0xE0,0x11,0x00,0x1F,0x00,0x00, + 0x00,0xFF,0xE0,0x24,0x80,0x3F,0x80,0x24,0x80,0x3F,0x80,0xC0,0x60}; +const u8g_fntpgm_uint8_t fontpage_317_222_222[45] U8G_FONT_SECTION("fontpage_317_222_222") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xDE,0xDE,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0xF8,0x80,0xA8,0x80,0xF8,0xE0,0xA8,0x80,0xF8, + 0x80,0x23,0xE0,0xFA,0x20,0x22,0x20,0xFA,0x20,0x52,0x20,0xAB,0xE0}; +const u8g_fntpgm_uint8_t fontpage_318_202_202[45] U8G_FONT_SECTION("fontpage_318_202_202") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0xCA,0xCA,0x00,0x0A,0xFF,0x00, + 0x00,0x0B,0x0B,0x16,0x0C,0x00,0xFF,0x04,0x00,0xFF,0xE0,0x0A,0x40,0xF5,0x80,0x55, + 0x40,0x95,0xA0,0x20,0x80,0x3F,0x80,0x20,0x80,0x3F,0x80,0xC0,0x80}; +const u8g_fntpgm_uint8_t fontpage_510_154_154[30] U8G_FONT_SECTION("fontpage_510_154_154") = { + 0x00,0x0C,0x0F,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x9A,0x9A,0x00,0x08,0x00,0x00, + 0x00,0x02,0x07,0x07,0x0C,0x06,0x01,0xC0,0xC0,0x00,0x00,0x00,0xC0,0xC0}; + +static const uxg_fontinfo_t g_fontinfo_zh_TW[] PROGMEM = { + FONTDATA_ITEM(69, 191, 191, fontpage_69_191_191), // '⊿' -- '⊿' + FONTDATA_ITEM(156, 128, 128, fontpage_156_128_128), // '一' -- '一' + FONTDATA_ITEM(156, 137, 139, fontpage_156_137_139), // '三' -- '下' + FONTDATA_ITEM(156, 141, 141, fontpage_156_141_141), // '不' -- '不' + FONTDATA_ITEM(156, 166, 166, fontpage_156_166_166), // '並' -- '並' + FONTDATA_ITEM(156, 173, 173, fontpage_156_173_173), // '中' -- '中' + FONTDATA_ITEM(156, 187, 187, fontpage_156_187_187), // '主' -- '主' + FONTDATA_ITEM(156, 203, 203, fontpage_156_203_203), // '之' -- '之' + FONTDATA_ITEM(157, 164, 164, fontpage_157_164_164), // '交' -- '交' + FONTDATA_ITEM(157, 174, 174, fontpage_157_174_174), // '亮' -- '亮' + FONTDATA_ITEM(157, 228, 228, fontpage_157_228_228), // '令' -- '令' + FONTDATA_ITEM(157, 246, 246, fontpage_157_246_246), // '件' -- '件' + FONTDATA_ITEM(157, 253, 253, fontpage_157_253_253), // '份' -- '份' + FONTDATA_ITEM(158, 145, 145, fontpage_158_145_145), // '休' -- '休' + FONTDATA_ITEM(158, 205, 206, fontpage_158_205_206), // '位' -- '低' + FONTDATA_ITEM(158, 220, 220, fontpage_158_220_220), // '作' -- '作' + FONTDATA_ITEM(159, 155, 155, fontpage_159_155_155), // '供' -- '供' + FONTDATA_ITEM(159, 221, 221, fontpage_159_221_221), // '保' -- '保' + FONTDATA_ITEM(159, 225, 225, fontpage_159_225_225), // '信' -- '信' + FONTDATA_ITEM(160, 139, 139, fontpage_160_139_139), // '個' -- '個' + FONTDATA_ITEM(160, 188, 188, fontpage_160_188_188), // '值' -- '值' + FONTDATA_ITEM(160, 207, 207, fontpage_160_207_207), // '偏' -- '偏' + FONTDATA_ITEM(160, 220, 220, fontpage_160_220_220), // '停' -- '停' + FONTDATA_ITEM(160, 245, 245, fontpage_160_245_245), // '偵' -- '偵' + FONTDATA_ITEM(161, 153, 153, fontpage_161_153_153), // '備' -- '備' + FONTDATA_ITEM(161, 179, 179, fontpage_161_179_179), // '傳' -- '傳' + FONTDATA_ITEM(161, 190, 190, fontpage_161_190_190), // '傾' -- '傾' + FONTDATA_ITEM(162, 178, 178, fontpage_162_178_178), // '儲' -- '儲' + FONTDATA_ITEM(162, 197, 197, fontpage_162_197_197), // '充' -- '充' + FONTDATA_ITEM(162, 200, 201, fontpage_162_200_201), // '先' -- '光' + FONTDATA_ITEM(162, 229, 229, fontpage_162_229_229), // '入' -- '入' + FONTDATA_ITEM(162, 232, 232, fontpage_162_232_232), // '全' -- '全' + FONTDATA_ITEM(162, 241, 241, fontpage_162_241_241), // '共' -- '共' + FONTDATA_ITEM(162, 247, 247, fontpage_162_247_247), // '具' -- '具' + FONTDATA_ITEM(163, 151, 151, fontpage_163_151_151), // '冗' -- '冗' + FONTDATA_ITEM(163, 183, 183, fontpage_163_183_183), // '冷' -- '冷' + FONTDATA_ITEM(163, 198, 198, fontpage_163_198_198), // '准' -- '准' + FONTDATA_ITEM(163, 250, 250, fontpage_163_250_250), // '出' -- '出' + FONTDATA_ITEM(164, 134, 134, fontpage_164_134_134), // '分' -- '分' + FONTDATA_ITEM(164, 151, 151, fontpage_164_151_151), // '列' -- '列' + FONTDATA_ITEM(164, 157, 157, fontpage_164_157_157), // '初' -- '初' + FONTDATA_ITEM(164, 176, 176, fontpage_164_176_176), // '到' -- '到' + FONTDATA_ITEM(164, 182, 183, fontpage_164_182_183), // '制' -- '刷' + FONTDATA_ITEM(164, 245, 245, fontpage_164_245_245), // '創' -- '創' + FONTDATA_ITEM(165, 155, 155, fontpage_165_155_155), // '力' -- '力' + FONTDATA_ITEM(165, 160, 160, fontpage_165_160_160), // '加' -- '加' + FONTDATA_ITEM(165, 213, 213, fontpage_165_213_213), // '動' -- '動' + FONTDATA_ITEM(166, 150, 150, fontpage_166_150_150), // '化' -- '化' + FONTDATA_ITEM(166, 202, 202, fontpage_166_202_202), // '半' -- '半' + FONTDATA_ITEM(166, 212, 212, fontpage_166_212_212), // '協' -- '協' + FONTDATA_ITEM(166, 225, 225, fontpage_166_225_225), // '卡' -- '卡' + FONTDATA_ITEM(166, 240, 240, fontpage_166_240_240), // '印' -- '印' + FONTDATA_ITEM(166, 248, 248, fontpage_166_248_248), // '卸' -- '卸' + FONTDATA_ITEM(166, 251, 251, fontpage_166_251_251), // '卻' -- '卻' + FONTDATA_ITEM(167, 159, 159, fontpage_167_159_159), // '原' -- '原' + FONTDATA_ITEM(167, 205, 205, fontpage_167_205_205), // '反' -- '反' + FONTDATA_ITEM(167, 214, 214, fontpage_167_214_214), // '取' -- '取' + FONTDATA_ITEM(167, 240, 240, fontpage_167_240_240), // '台' -- '台' + FONTDATA_ITEM(168, 136, 136, fontpage_168_136_136), // '合' -- '合' + FONTDATA_ITEM(168, 166, 166, fontpage_168_166_166), // '否' -- '否' + FONTDATA_ITEM(168, 202, 202, fontpage_168_202_202), // '告' -- '告' + FONTDATA_ITEM(168, 253, 253, fontpage_168_253_253), // '命' -- '命' + FONTDATA_ITEM(169, 140, 140, fontpage_169_140_140), // '和' -- '和' + FONTDATA_ITEM(170, 223, 223, fontpage_170_223_223), // '啟' -- '啟' + FONTDATA_ITEM(171, 174, 174, fontpage_171_174_174), // '單' -- '單' + FONTDATA_ITEM(172, 180, 180, fontpage_172_180_180), // '嘴' -- '嘴' + FONTDATA_ITEM(172, 232, 232, fontpage_172_232_232), // '器' -- '器' + FONTDATA_ITEM(172, 244, 244, fontpage_172_244_244), // '噴' -- '噴' + FONTDATA_ITEM(173, 222, 222, fontpage_173_222_222), // '回' -- '回' + FONTDATA_ITEM(173, 224, 224, fontpage_173_224_224), // '因' -- '因' + FONTDATA_ITEM(173, 250, 250, fontpage_173_250_250), // '固' -- '固' + FONTDATA_ITEM(174, 150, 150, fontpage_174_150_150), // '圖' -- '圖' + FONTDATA_ITEM(174, 168, 168, fontpage_174_168_168), // '在' -- '在' + FONTDATA_ITEM(175, 139, 139, fontpage_175_139_139), // '型' -- '型' + FONTDATA_ITEM(175, 247, 247, fontpage_175_247_247), // '執' -- '執' + FONTDATA_ITEM(176, 202, 202, fontpage_176_202_202), // '塊' -- '塊' + FONTDATA_ITEM(176, 235, 235, fontpage_176_235_235), // '填' -- '填' + FONTDATA_ITEM(177, 138, 138, fontpage_177_138_138), // '墊' -- '墊' + FONTDATA_ITEM(178, 150, 150, fontpage_178_150_150), // '外' -- '外' + FONTDATA_ITEM(178, 154, 154, fontpage_178_154_154), // '多' -- '多' + FONTDATA_ITEM(178, 160, 160, fontpage_178_160_160), // '夠' -- '夠' + FONTDATA_ITEM(178, 167, 167, fontpage_178_167_167), // '大' -- '大' + FONTDATA_ITEM(178, 169, 170, fontpage_178_169_170), // '天' -- '太' + FONTDATA_ITEM(178, 177, 177, fontpage_178_177_177), // '失' -- '失' + FONTDATA_ITEM(179, 203, 203, fontpage_179_203_203), // '始' -- '始' + FONTDATA_ITEM(181, 146, 146, fontpage_181_146_146), // '媒' -- '媒' + FONTDATA_ITEM(182, 208, 208, fontpage_182_208_208), // '子' -- '子' + FONTDATA_ITEM(182, 216, 216, fontpage_182_216_216), // '存' -- '存' + FONTDATA_ITEM(183, 137, 137, fontpage_183_137_137), // '安' -- '安' + FONTDATA_ITEM(183, 140, 140, fontpage_183_140_140), // '完' -- '完' + FONTDATA_ITEM(183, 154, 154, fontpage_183_154_154), // '定' -- '定' + FONTDATA_ITEM(183, 162, 162, fontpage_183_162_162), // '客' -- '客' + FONTDATA_ITEM(183, 185, 185, fontpage_183_185_185), // '容' -- '容' + FONTDATA_ITEM(184, 141, 141, fontpage_184_141_141), // '對' -- '對' + FONTDATA_ITEM(184, 143, 143, fontpage_184_143_143), // '小' -- '小' + FONTDATA_ITEM(184, 177, 177, fontpage_184_177_177), // '就' -- '就' + FONTDATA_ITEM(187, 229, 229, fontpage_187_229_229), // '工' -- '工' + FONTDATA_ITEM(187, 238, 238, fontpage_187_238_238), // '差' -- '差' + FONTDATA_ITEM(187, 242, 242, fontpage_187_242_242), // '已' -- '已' + FONTDATA_ITEM(188, 243, 243, fontpage_188_243_243), // '平' -- '平' + FONTDATA_ITEM(189, 138, 138, fontpage_189_138_138), // '床' -- '床' + FONTDATA_ITEM(189, 166, 166, fontpage_189_166_166), // '度' -- '度' + FONTDATA_ITEM(189, 226, 226, fontpage_189_226_226), // '廢' -- '廢' + FONTDATA_ITEM(189, 250, 250, fontpage_189_250_250), // '建' -- '建' + FONTDATA_ITEM(190, 149, 149, fontpage_190_149_149), // '引' -- '引' + FONTDATA_ITEM(191, 133, 133, fontpage_191_133_133), // '待' -- '待' + FONTDATA_ITEM(191, 140, 140, fontpage_191_140_140), // '後' -- '後' + FONTDATA_ITEM(191, 145, 145, fontpage_191_145_145), // '徑' -- '徑' + FONTDATA_ITEM(191, 158, 158, fontpage_191_158_158), // '從' -- '從' + FONTDATA_ITEM(191, 169, 169, fontpage_191_169_169), // '復' -- '復' + FONTDATA_ITEM(191, 174, 174, fontpage_191_174_174), // '微' -- '微' + FONTDATA_ITEM(191, 195, 195, fontpage_191_195_195), // '心' -- '心' + FONTDATA_ITEM(192, 167, 167, fontpage_192_167_167), // '性' -- '性' + FONTDATA_ITEM(192, 226, 226, fontpage_192_226_226), // '恢' -- '恢' + FONTDATA_ITEM(192, 239, 239, fontpage_192_239_239), // '息' -- '息' + FONTDATA_ITEM(195, 182, 182, fontpage_195_182_182), // '憶' -- '憶' + FONTDATA_ITEM(195, 201, 201, fontpage_195_201_201), // '應' -- '應' + FONTDATA_ITEM(196, 144, 144, fontpage_196_144_144), // '成' -- '成' + FONTDATA_ITEM(196, 182, 182, fontpage_196_182_182), // '戶' -- '戶' + FONTDATA_ITEM(196, 192, 192, fontpage_196_192_192), // '所' -- '所' + FONTDATA_ITEM(196, 199, 199, fontpage_196_199_199), // '扇' -- '扇' + FONTDATA_ITEM(196, 203, 203, fontpage_196_203_203), // '手' -- '手' + FONTDATA_ITEM(196, 211, 211, fontpage_196_211_211), // '打' -- '打' + FONTDATA_ITEM(196, 249, 249, fontpage_196_249_249), // '批' -- '批' + FONTDATA_ITEM(197, 150, 150, fontpage_197_150_150), // '抖' -- '抖' + FONTDATA_ITEM(197, 189, 189, fontpage_197_189_189), // '抽' -- '抽' + FONTDATA_ITEM(197, 212, 212, fontpage_197_212_212), // '拔' -- '拔' + FONTDATA_ITEM(198, 137, 137, fontpage_198_137_137), // '按' -- '按' + FONTDATA_ITEM(199, 137, 137, fontpage_199_137_137), // '掉' -- '掉' + FONTDATA_ITEM(199, 162, 162, fontpage_199_162_162), // '探' -- '探' + FONTDATA_ITEM(199, 165, 165, fontpage_199_165_165), // '接' -- '接' + FONTDATA_ITEM(199, 167, 167, fontpage_199_167_167), // '控' -- '控' + FONTDATA_ITEM(199, 208, 208, fontpage_199_208_208), // '提' -- '提' + FONTDATA_ITEM(199, 210, 210, fontpage_199_210_210), // '插' -- '插' + FONTDATA_ITEM(199, 219, 219, fontpage_199_219_219), // '換' -- '換' + FONTDATA_ITEM(201, 199, 199, fontpage_201_199_199), // '擇' -- '擇' + FONTDATA_ITEM(201, 202, 203, fontpage_201_202_203), // '擊' -- '擋' + FONTDATA_ITEM(201, 224, 224, fontpage_201_224_224), // '擠' -- '擠' + FONTDATA_ITEM(202, 182, 182, fontpage_202_182_182), // '收' -- '收' + FONTDATA_ITEM(202, 190, 190, fontpage_202_190_190), // '放' -- '放' + FONTDATA_ITEM(202, 215, 215, fontpage_202_215_215), // '敗' -- '敗' + FONTDATA_ITEM(202, 244, 244, fontpage_202_244_244), // '整' -- '整' + FONTDATA_ITEM(202, 248, 248, fontpage_202_248_248), // '數' -- '數' + FONTDATA_ITEM(203, 153, 153, fontpage_203_153_153), // '料' -- '料' + FONTDATA_ITEM(203, 156, 156, fontpage_203_156_156), // '斜' -- '斜' + FONTDATA_ITEM(203, 176, 176, fontpage_203_176_176), // '新' -- '新' + FONTDATA_ITEM(203, 183, 183, fontpage_203_183_183), // '斷' -- '斷' + FONTDATA_ITEM(203, 188, 188, fontpage_203_188_188), // '於' -- '於' + FONTDATA_ITEM(204, 135, 135, fontpage_204_135_135), // '昇' -- '昇' + FONTDATA_ITEM(204, 142, 142, fontpage_204_142_142), // '明' -- '明' + FONTDATA_ITEM(204, 175, 175, fontpage_204_175_175), // '是' -- '是' + FONTDATA_ITEM(204, 194, 194, fontpage_204_194_194), // '時' -- '時' + FONTDATA_ITEM(205, 171, 171, fontpage_205_171_171), // '暫' -- '暫' + FONTDATA_ITEM(205, 244, 244, fontpage_205_244_244), // '更' -- '更' + FONTDATA_ITEM(206, 128, 128, fontpage_206_128_128), // '最' -- '最' + FONTDATA_ITEM(206, 137, 137, fontpage_206_137_137), // '有' -- '有' + FONTDATA_ITEM(206, 255, 255, fontpage_206_255_255), // '板' -- '板' + FONTDATA_ITEM(207, 241, 241, fontpage_207_241_241), // '柱' -- '柱' + FONTDATA_ITEM(208, 161, 161, fontpage_208_161_161), // '校' -- '校' + FONTDATA_ITEM(208, 188, 188, fontpage_208_188_188), // '格' -- '格' + FONTDATA_ITEM(209, 157, 157, fontpage_209_157_157), // '條' -- '條' + FONTDATA_ITEM(209, 196, 196, fontpage_209_196_196), // '棄' -- '棄' + FONTDATA_ITEM(211, 253, 253, fontpage_211_253_253), // '槽' -- '槽' + FONTDATA_ITEM(212, 217, 217, fontpage_212_217_217), // '橙' -- '橙' + FONTDATA_ITEM(212, 223, 223, fontpage_212_223_223), // '機' -- '機' + FONTDATA_ITEM(213, 162, 162, fontpage_213_162_162), // '檢' -- '檢' + FONTDATA_ITEM(214, 226, 227, fontpage_214_226_227), // '止' -- '正' + FONTDATA_ITEM(214, 229, 229, fontpage_214_229_229), // '步' -- '步' + FONTDATA_ITEM(214, 248, 248, fontpage_214_248_248), // '歸' -- '歸' + FONTDATA_ITEM(215, 188, 188, fontpage_215_188_188), // '殼' -- '殼' + FONTDATA_ITEM(215, 212, 212, fontpage_215_212_212), // '比' -- '比' + FONTDATA_ITEM(217, 146, 146, fontpage_217_146_146), // '沒' -- '沒' + FONTDATA_ITEM(219, 136, 136, fontpage_219_136_136), // '消' -- '消' + FONTDATA_ITEM(219, 225, 225, fontpage_219_225_225), // '淡' -- '淡' + FONTDATA_ITEM(220, 133, 133, fontpage_220_133_133), // '清' -- '清' + FONTDATA_ITEM(220, 172, 172, fontpage_220_172_172), // '測' -- '測' + FONTDATA_ITEM(221, 144, 144, fontpage_221_144_144), // '源' -- '源' + FONTDATA_ITEM(221, 150, 150, fontpage_221_150_150), // '準' -- '準' + FONTDATA_ITEM(221, 171, 171, fontpage_221_171_171), // '溫' -- '溫' + FONTDATA_ITEM(223, 192, 192, fontpage_223_192_192), // '激' -- '激' + FONTDATA_ITEM(226, 161, 161, fontpage_226_161_161), // '無' -- '無' + FONTDATA_ITEM(227, 177, 177, fontpage_227_177_177), // '熱' -- '熱' + FONTDATA_ITEM(227, 200, 200, fontpage_227_200_200), // '燈' -- '燈' + FONTDATA_ITEM(228, 199, 199, fontpage_228_199_199), // '片' -- '片' + FONTDATA_ITEM(228, 233, 233, fontpage_228_233_233), // '物' -- '物' + FONTDATA_ITEM(231, 135, 135, fontpage_231_135_135), // '率' -- '率' + FONTDATA_ITEM(234, 168, 168, fontpage_234_168_168), // '用' -- '用' + FONTDATA_ITEM(234, 204, 204, fontpage_234_204_204), // '界' -- '界' + FONTDATA_ITEM(236, 253, 253, fontpage_236_253_253), // '白' -- '白' + FONTDATA_ITEM(237, 132, 132, fontpage_237_132_132), // '的' -- '的' + FONTDATA_ITEM(237, 227, 227, fontpage_237_227_227), // '監' -- '監' + FONTDATA_ITEM(237, 244, 244, fontpage_237_244_244), // '直' -- '直' + FONTDATA_ITEM(238, 160, 160, fontpage_238_160_160), // '眠' -- '眠' + FONTDATA_ITEM(240, 141, 141, fontpage_240_141_141), // '砍' -- '砍' + FONTDATA_ITEM(241, 186, 186, fontpage_241_186_186), // '確' -- '確' + FONTDATA_ITEM(243, 251, 251, fontpage_243_251_251), // '移' -- '移' + FONTDATA_ITEM(244, 205, 205, fontpage_244_205_205), // '積' -- '積' + FONTDATA_ITEM(245, 239, 239, fontpage_245_239_239), // '端' -- '端' + FONTDATA_ITEM(246, 201, 201, fontpage_246_201_201), // '等' -- '等' + FONTDATA_ITEM(247, 161, 161, fontpage_247_161_161), // '管' -- '管' + FONTDATA_ITEM(247, 177, 177, fontpage_247_177_177), // '箱' -- '箱' + FONTDATA_ITEM(249, 251, 251, fontpage_249_251_251), // '系' -- '系' + FONTDATA_ITEM(250, 133, 133, fontpage_250_133_133), // '紅' -- '紅' + FONTDATA_ITEM(250, 162, 162, fontpage_250_162_162), // '索' -- '索' + FONTDATA_ITEM(250, 171, 171, fontpage_250_171_171), // '紫' -- '紫' + FONTDATA_ITEM(250, 176, 176, fontpage_250_176_176), // '細' -- '細' + FONTDATA_ITEM(250, 194, 194, fontpage_250_194_194), // '終' -- '終' + FONTDATA_ITEM(250, 241, 242, fontpage_250_241_242), // '統' -- '絲' + FONTDATA_ITEM(251, 160, 160, fontpage_251_160_160), // '綠' -- '綠' + FONTDATA_ITEM(251, 178, 178, fontpage_251_178_178), // '網' -- '網' + FONTDATA_ITEM(251, 210, 210, fontpage_251_210_210), // '緒' -- '緒' + FONTDATA_ITEM(251, 218, 218, fontpage_251_218_218), // '線' -- '線' + FONTDATA_ITEM(251, 232, 232, fontpage_251_232_232), // '編' -- '編' + FONTDATA_ITEM(252, 174, 174, fontpage_252_174_174), // '縮' -- '縮' + FONTDATA_ITEM(252, 189, 189, fontpage_252_189_189), // '總' -- '總' + FONTDATA_ITEM(252, 252, 252, fontpage_252_252_252), // '繼' -- '繼' + FONTDATA_ITEM(253, 140, 140, fontpage_253_140_140), // '續' -- '續' + FONTDATA_ITEM(253, 162, 162, fontpage_253_162_162), // '红' -- '红' + FONTDATA_ITEM(254, 238, 238, fontpage_254_238_238), // '置' -- '置' + FONTDATA_ITEM(254, 242, 242, fontpage_254_242_242), // '署' -- '署' + FONTDATA_ITEM(256, 240, 240, fontpage_256_240_240), // '聰' -- '聰' + FONTDATA_ITEM(259, 234, 234, fontpage_259_234_234), // '自' -- '自' + FONTDATA_ITEM(267, 205, 205, fontpage_267_205_205), // '藍' -- '藍' + FONTDATA_ITEM(272, 204, 204, fontpage_272_204_204), // '行' -- '行' + FONTDATA_ITEM(272, 232, 232, fontpage_272_232_232), // '表' -- '表' + FONTDATA_ITEM(273, 171, 171, fontpage_273_171_171), // '被' -- '被' + FONTDATA_ITEM(273, 197, 197, fontpage_273_197_197), // '装' -- '装' + FONTDATA_ITEM(273, 221, 221, fontpage_273_221_221), // '裝' -- '裝' + FONTDATA_ITEM(274, 135, 135, fontpage_274_135_135), // '複' -- '複' + FONTDATA_ITEM(275, 210, 210, fontpage_275_210_210), // '角' -- '角' + FONTDATA_ITEM(276, 136, 136, fontpage_276_136_136), // '計' -- '計' + FONTDATA_ITEM(276, 138, 138, fontpage_276_138_138), // '訊' -- '訊' + FONTDATA_ITEM(276, 152, 152, fontpage_276_152_152), // '記' -- '記' + FONTDATA_ITEM(276, 173, 173, fontpage_276_173_173), // '設' -- '設' + FONTDATA_ITEM(276, 230, 230, fontpage_276_230_230), // '試' -- '試' + FONTDATA_ITEM(277, 141, 141, fontpage_277_141_141), // '認' -- '認' + FONTDATA_ITEM(277, 164, 164, fontpage_277_164_164), // '誤' -- '誤' + FONTDATA_ITEM(277, 191, 191, fontpage_277_191_191), // '調' -- '調' + FONTDATA_ITEM(277, 203, 203, fontpage_277_203_203), // '請' -- '請' + FONTDATA_ITEM(278, 240, 240, fontpage_278_240_240), // '議' -- '議' + FONTDATA_ITEM(279, 128, 128, fontpage_279_128_128), // '讀' -- '讀' + FONTDATA_ITEM(279, 138, 138, fontpage_279_138_138), // '變' -- '變' + FONTDATA_ITEM(281, 199, 199, fontpage_281_199_199), // '資' -- '資' + FONTDATA_ITEM(283, 221, 221, fontpage_283_221_221), // '距' -- '距' + FONTDATA_ITEM(285, 202, 202, fontpage_285_202_202), // '車' -- '車' + FONTDATA_ITEM(285, 223, 223, fontpage_285_223_223), // '軟' -- '軟' + FONTDATA_ITEM(285, 248, 248, fontpage_285_248_248), // '軸' -- '軸' + FONTDATA_ITEM(286, 137, 137, fontpage_286_137_137), // '載' -- '載' + FONTDATA_ITEM(286, 175, 175, fontpage_286_175_175), // '輯' -- '輯' + FONTDATA_ITEM(286, 184, 184, fontpage_286_184_184), // '輸' -- '輸' + FONTDATA_ITEM(286, 201, 201, fontpage_286_201_201), // '轉' -- '轉' + FONTDATA_ITEM(287, 209, 209, fontpage_287_209_209), // '近' -- '近' + FONTDATA_ITEM(287, 212, 212, fontpage_287_212_212), // '返' -- '返' + FONTDATA_ITEM(288, 128, 128, fontpage_288_128_128), // '退' -- '退' + FONTDATA_ITEM(288, 159, 159, fontpage_288_159_159), // '速' -- '速' + FONTDATA_ITEM(288, 163, 163, fontpage_288_163_163), // '連' -- '連' + FONTDATA_ITEM(288, 178, 178, fontpage_288_178_178), // '進' -- '進' + FONTDATA_ITEM(288, 203, 203, fontpage_288_203_203), // '運' -- '運' + FONTDATA_ITEM(288, 212, 212, fontpage_288_212_212), // '達' -- '達' + FONTDATA_ITEM(288, 248, 248, fontpage_288_248_248), // '選' -- '選' + FONTDATA_ITEM(289, 132, 132, fontpage_289_132_132), // '還' -- '還' + FONTDATA_ITEM(289, 138, 138, fontpage_289_138_138), // '邊' -- '邊' + FONTDATA_ITEM(289, 232, 232, fontpage_289_232_232), // '部' -- '部' + FONTDATA_ITEM(291, 203, 203, fontpage_291_203_203), // '釋' -- '釋' + FONTDATA_ITEM(291, 205, 205, fontpage_291_205_205), // '重' -- '重' + FONTDATA_ITEM(291, 207, 207, fontpage_291_207_207), // '量' -- '量' + FONTDATA_ITEM(291, 221, 221, fontpage_291_221_221), // '針' -- '針' + FONTDATA_ITEM(292, 149, 149, fontpage_292_149_149), // '鈕' -- '鈕' + FONTDATA_ITEM(294, 175, 175, fontpage_294_175_175), // '錯' -- '錯' + FONTDATA_ITEM(294, 245, 245, fontpage_294_245_245), // '鍵' -- '鍵' + FONTDATA_ITEM(298, 247, 247, fontpage_298_247_247), // '長' -- '長' + FONTDATA_ITEM(299, 137, 137, fontpage_299_137_137), // '閉' -- '閉' + FONTDATA_ITEM(299, 139, 139, fontpage_299_139_139), // '開' -- '開' + FONTDATA_ITEM(299, 147, 147, fontpage_299_147_147), // '間' -- '間' + FONTDATA_ITEM(299, 220, 220, fontpage_299_220_220), // '關' -- '關' + FONTDATA_ITEM(300, 205, 205, fontpage_300_205_205), // '降' -- '降' + FONTDATA_ITEM(300, 228, 228, fontpage_300_228_228), // '除' -- '除' + FONTDATA_ITEM(301, 142, 142, fontpage_301_142_142), // '階' -- '階' + FONTDATA_ITEM(301, 217, 217, fontpage_301_217_217), // '雙' -- '雙' + FONTDATA_ITEM(301, 226, 226, fontpage_301_226_226), // '離' -- '離' + FONTDATA_ITEM(301, 251, 251, fontpage_301_251_251), // '電' -- '電' + FONTDATA_ITEM(302, 210, 210, fontpage_302_210_210), // '青' -- '青' + FONTDATA_ITEM(302, 222, 222, fontpage_302_222_222), // '非' -- '非' + FONTDATA_ITEM(302, 226, 226, fontpage_302_226_226), // '面' -- '面' + FONTDATA_ITEM(304, 133, 133, fontpage_304_133_133), // '項' -- '項' + FONTDATA_ITEM(304, 144, 144, fontpage_304_144_144), // '預' -- '預' + FONTDATA_ITEM(304, 205, 205, fontpage_304_205_205), // '額' -- '額' + FONTDATA_ITEM(304, 222, 222, fontpage_304_222_222), // '類' -- '類' + FONTDATA_ITEM(305, 168, 168, fontpage_305_168_168), // '風' -- '風' + FONTDATA_ITEM(305, 253, 253, fontpage_305_253_253), // '飽' -- '飽' + FONTDATA_ITEM(306, 152, 152, fontpage_306_152_152), // '餘' -- '餘' + FONTDATA_ITEM(307, 172, 172, fontpage_307_172_172), // '馬' -- '馬' + FONTDATA_ITEM(308, 197, 197, fontpage_308_197_197), // '驅' -- '驅' + FONTDATA_ITEM(309, 212, 212, fontpage_309_212_212), // '體' -- '體' + FONTDATA_ITEM(309, 216, 216, fontpage_309_216_216), // '高' -- '高' + FONTDATA_ITEM(317, 195, 195, fontpage_317_195_195), // '黃' -- '黃' + FONTDATA_ITEM(317, 222, 222, fontpage_317_222_222), // '點' -- '點' + FONTDATA_ITEM(318, 202, 202, fontpage_318_202_202), // '齊' -- '齊' + FONTDATA_ITEM(510, 154, 154, fontpage_510_154_154), // ':' -- ':' +}; diff --git a/src/lcd/dogm/lcdprint_u8g.cpp b/src/lcd/dogm/lcdprint_u8g.cpp new file mode 100644 index 0000000..48b2e92 --- /dev/null +++ b/src/lcd/dogm/lcdprint_u8g.cpp @@ -0,0 +1,56 @@ +/** + * @file lcdprint_u8g.cpp + * @brief LCD print api for u8glib + * @author Yunhui Fu (yhfudev@gmail.com) + * @version 1.0 + * @date 2016-08-19 + * @copyright GPL/BSD + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB + +#include "marlinui_DOGM.h" + +#include "../marlinui.h" +#include "../../MarlinCore.h" + +#include "../fontutils.h" +#include "u8g_fontutf8.h" +#include "../lcdprint.h" + +int lcd_glyph_height() { return u8g_GetFontBBXHeight(u8g.getU8g()); } + +void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { u8g.setPrintPos(col, row); } + +void lcd_put_int(const int i) { u8g.print(i); } + +// return < 0 on error +// return the advanced pixels +int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) { + if (c < 256) { + u8g.print((char)c); + return u8g_GetFontBBXWidth(u8g.getU8g()); + } + u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(), + ret = uxg_DrawWchar(u8g.getU8g(), x, y, c, max_length); + u8g.setPrintPos(x + ret, y); + return ret; +} + +int lcd_put_u8str_max(const char * utf8_str, const pixel_len_t max_length) { + u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(), + ret = uxg_DrawUtf8Str(u8g.getU8g(), x, y, utf8_str, max_length); + u8g.setPrintPos(x + ret, y); + return ret; +} + +int lcd_put_u8str_max_P(PGM_P utf8_pstr, const pixel_len_t max_length) { + u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(), + ret = uxg_DrawUtf8StrP(u8g.getU8g(), x, y, utf8_pstr, max_length); + u8g.setPrintPos(x + ret, y); + return ret; +} + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/marlinui_DOGM.cpp b/src/lcd/dogm/marlinui_DOGM.cpp new file mode 100644 index 0000000..e327159 --- /dev/null +++ b/src/lcd/dogm/marlinui_DOGM.cpp @@ -0,0 +1,754 @@ +/** + * 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/dogm/marlinui_DOGM.h + * + * Implementation of the LCD display routines for a DOGM128 graphic display. + * by STB for ErikZalm/Marlin. Common LCD 128x64 pixel graphic displays. + * + * Demonstrator: https://www.reprap.org/wiki/STB_Electronics + * License: https://opensource.org/licenses/BSD-3-Clause + * + * With the use of: + * u8glib by Oliver Kraus + * https://github.com/olikraus/U8glib_Arduino + * License: https://opensource.org/licenses/BSD-3-Clause + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB + +#include "marlinui_DOGM.h" +#include "u8g_fontutf8.h" + +#if ENABLED(SHOW_BOOTSCREEN) + #include "dogm_Bootscreen.h" +#endif + +#include "../lcdprint.h" +#include "../fontutils.h" +#include "../../libs/numtostr.h" +#include "../marlinui.h" + +#include "../../sd/cardreader.h" +#include "../../module/temperature.h" +#include "../../module/printcounter.h" +#include "../../MarlinCore.h" + +#if ENABLED(SDSUPPORT) + #include "../../libs/duration_t.h" +#endif + +#if ENABLED(AUTO_BED_LEVELING_UBL) + #include "../../feature/bedlevel/bedlevel.h" +#endif + +/** + * Include all needed font files + * (See https://marlinfw.org/docs/development/fonts.html) + */ +#include "fontdata/fontdata_ISO10646_1.h" +#if ENABLED(USE_SMALL_INFOFONT) + #include "fontdata/fontdata_6x9_marlin.h" + #define FONT_STATUSMENU_NAME u8g_font_6x9 +#else + #define FONT_STATUSMENU_NAME MENU_FONT_NAME +#endif + +U8G_CLASS u8g; + +#include LANGUAGE_DATA_INCL(LCD_LANGUAGE) +#ifdef LCD_LANGUAGE_2 + #include LANGUAGE_DATA_INCL(LCD_LANGUAGE_2) +#endif +#ifdef LCD_LANGUAGE_3 + #include LANGUAGE_DATA_INCL(LCD_LANGUAGE_3) +#endif +#ifdef LCD_LANGUAGE_4 + #include LANGUAGE_DATA_INCL(LCD_LANGUAGE_4) +#endif +#ifdef LCD_LANGUAGE_5 + #include LANGUAGE_DATA_INCL(LCD_LANGUAGE_5) +#endif + +#if HAS_LCD_CONTRAST + void MarlinUI::_set_contrast() { u8g.setContrast(contrast); } +#endif + +void MarlinUI::set_font(const MarlinFont font_nr) { + static char currentfont = 0; + if (font_nr != currentfont) { + switch ((currentfont = font_nr)) { + case FONT_STATUSMENU : u8g.setFont(FONT_STATUSMENU_NAME); break; + case FONT_EDIT : u8g.setFont(EDIT_FONT_NAME); break; + default: + case FONT_MENU : u8g.setFont(MENU_FONT_NAME); break; + } + } +} + +bool MarlinUI::detected() { return true; } + +#if ENABLED(SHOW_BOOTSCREEN) + + #if ENABLED(SHOW_CUSTOM_BOOTSCREEN) + // Draws a slice of a particular frame of the custom bootscreen, without the u8g loop + void MarlinUI::draw_custom_bootscreen(const uint8_t frame/*=0*/) { + constexpr u8g_uint_t left = u8g_uint_t((LCD_PIXEL_WIDTH - (CUSTOM_BOOTSCREEN_BMPWIDTH)) / 2), + top = u8g_uint_t(CUSTOM_BOOTSCREEN_Y); + #if ENABLED(CUSTOM_BOOTSCREEN_INVERTED) + constexpr u8g_uint_t right = left + CUSTOM_BOOTSCREEN_BMPWIDTH, + bottom = top + CUSTOM_BOOTSCREEN_BMPHEIGHT; + #endif + + #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED) + #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED_FRAME_TIME) + const u8g_pgm_uint8_t * const bmp = (u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[frame].bitmap); + #else + const u8g_pgm_uint8_t * const bmp = (u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[frame]); + #endif + #else + const u8g_pgm_uint8_t * const bmp = custom_start_bmp; + #endif + + UNUSED(frame); + + u8g.drawBitmapP(left, top, CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH, CUSTOM_BOOTSCREEN_BMPHEIGHT, bmp); + + #if ENABLED(CUSTOM_BOOTSCREEN_INVERTED) + if (frame == 0) { + u8g.setColorIndex(1); + if (top) u8g.drawBox(0, 0, LCD_PIXEL_WIDTH, top); + if (left) u8g.drawBox(0, top, left, CUSTOM_BOOTSCREEN_BMPHEIGHT); + if (right < LCD_PIXEL_WIDTH) u8g.drawBox(right, top, LCD_PIXEL_WIDTH - right, CUSTOM_BOOTSCREEN_BMPHEIGHT); + if (bottom < LCD_PIXEL_HEIGHT) u8g.drawBox(0, bottom, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT - bottom); + } + #endif + } + + // Shows the custom bootscreen, with the u8g loop, animations and delays + void MarlinUI::show_custom_bootscreen() { + #if DISABLED(CUSTOM_BOOTSCREEN_ANIMATED) + constexpr millis_t frame_time = 0; + constexpr uint8_t f = 0; + #else + #if DISABLED(CUSTOM_BOOTSCREEN_ANIMATED_FRAME_TIME) + constexpr millis_t frame_time = CUSTOM_BOOTSCREEN_FRAME_TIME; + #endif + LOOP_L_N(f, COUNT(custom_bootscreen_animation)) + #endif + { + #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED_FRAME_TIME) + const uint8_t fr = _MIN(f, COUNT(custom_bootscreen_animation) - 1); + const millis_t frame_time = pgm_read_word(&custom_bootscreen_animation[fr].duration); + #endif + u8g.firstPage(); + do { draw_custom_bootscreen(f); } while (u8g.nextPage()); + if (frame_time) safe_delay(frame_time); + } + + #ifndef CUSTOM_BOOTSCREEN_TIMEOUT + #define CUSTOM_BOOTSCREEN_TIMEOUT 2500 + #endif + #if CUSTOM_BOOTSCREEN_TIMEOUT + safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT); + #endif + } + #endif // SHOW_CUSTOM_BOOTSCREEN + + // Two-part needed to display all info + constexpr bool two_part = ((LCD_PIXEL_HEIGHT) - (START_BMPHEIGHT)) < ((MENU_FONT_ASCENT) * 2); + constexpr uint8_t bootscreen_pages = 1 + two_part; + + // Draw the static Marlin bootscreen from a u8g loop + // or the animated boot screen within its own u8g loop + void MarlinUI::draw_marlin_bootscreen(const bool line2/*=false*/) { + + // Determine text space needed + constexpr u8g_uint_t text_width_1 = u8g_uint_t((sizeof(SHORT_BUILD_VERSION) - 1) * (MENU_FONT_WIDTH)), + text_width_2 = u8g_uint_t((sizeof(MARLIN_WEBSITE_URL) - 1) * (MENU_FONT_WIDTH)), + text_max_width = _MAX(text_width_1, text_width_2), + text_total_height = (MENU_FONT_HEIGHT) * 2, + width = LCD_PIXEL_WIDTH, height = LCD_PIXEL_HEIGHT, + rspace = width - (START_BMPWIDTH); + + u8g_int_t offx, offy, txt_base, txt_offx_1, txt_offx_2; + + // Can the text fit to the right of the bitmap? + if (text_max_width < rspace) { + constexpr int8_t inter = (width - text_max_width - (START_BMPWIDTH)) / 3; // Evenly distribute horizontal space + offx = inter; // First the boot logo... + offy = (height - (START_BMPHEIGHT)) / 2; // ...V-aligned in the full height + txt_offx_1 = txt_offx_2 = inter + (START_BMPWIDTH) + inter; // Text right of the bitmap + txt_base = (height + MENU_FONT_ASCENT + text_total_height - (MENU_FONT_HEIGHT)) / 2; // Text vertical center + } + else { + constexpr int8_t inter = (height - text_total_height - (START_BMPHEIGHT)) / 3; // Evenly distribute vertical space + offx = rspace / 2; // Center the boot logo in the whole space + offy = inter; // V-align boot logo proportionally + txt_offx_1 = (width - text_width_1) / 2; // Text 1 centered + txt_offx_2 = (width - text_width_2) / 2; // Text 2 centered + txt_base = offy + START_BMPHEIGHT + offy + text_total_height - (MENU_FONT_DESCENT); // Even spacing looks best + } + NOLESS(offx, 0); + NOLESS(offy, 0); + + auto _draw_bootscreen_bmp = [&](const uint8_t *bitmap) { + u8g.drawBitmapP(offx, offy, START_BMP_BYTEWIDTH, START_BMPHEIGHT, bitmap); + set_font(FONT_MENU); + if (!two_part || !line2) lcd_put_u8str(txt_offx_1, txt_base - (MENU_FONT_HEIGHT), F(SHORT_BUILD_VERSION)); + if (!two_part || line2) lcd_put_u8str(txt_offx_2, txt_base, F(MARLIN_WEBSITE_URL)); + }; + + auto draw_bootscreen_bmp = [&](const uint8_t *bitmap) { + u8g.firstPage(); do { _draw_bootscreen_bmp(bitmap); } while (u8g.nextPage()); + }; + + #if DISABLED(BOOT_MARLIN_LOGO_ANIMATED) + draw_bootscreen_bmp(start_bmp); + #else + constexpr millis_t frame_time = MARLIN_BOOTSCREEN_FRAME_TIME; + LOOP_L_N(f, COUNT(marlin_bootscreen_animation)) { + draw_bootscreen_bmp((uint8_t*)pgm_read_ptr(&marlin_bootscreen_animation[f])); + if (frame_time) safe_delay(frame_time); + } + #endif + } + + // Show the Marlin bootscreen, with the u8g loop and delays + void MarlinUI::show_marlin_bootscreen() { + for (uint8_t q = bootscreen_pages; q--;) { + draw_marlin_bootscreen(q == 0); + if (q) safe_delay((BOOTSCREEN_TIMEOUT) / bootscreen_pages); + } + } + + void MarlinUI::show_bootscreen() { + TERN_(SHOW_CUSTOM_BOOTSCREEN, show_custom_bootscreen()); + show_marlin_bootscreen(); + } + + void MarlinUI::bootscreen_completion(const millis_t sofar) { + if ((BOOTSCREEN_TIMEOUT) / bootscreen_pages > sofar) safe_delay((BOOTSCREEN_TIMEOUT) / bootscreen_pages - sofar); + } + +#endif // SHOW_BOOTSCREEN + +#if ENABLED(LIGHTWEIGHT_UI) + #include "status_screen_lite_ST7920.h" +#endif + +// Initialize or re-initialize the LCD +void MarlinUI::init_lcd() { + + static bool did_init_u8g = false; + if (!did_init_u8g) { + u8g.init(U8G_PARAM); + did_init_u8g = true; + } + + #if PIN_EXISTS(LCD_BACKLIGHT) + OUT_WRITE(LCD_BACKLIGHT_PIN, DISABLED(DELAYED_BACKLIGHT_INIT)); // Illuminate after reset or right away + #endif + + #if ANY(MKS_12864OLED, MKS_12864OLED_SSD1306, FYSETC_242_OLED_12864, ZONESTAR_12864OLED, K3D_242_OLED_CONTROLLER) + SET_OUTPUT(LCD_PINS_DC); + #ifndef LCD_RESET_PIN + #define LCD_RESET_PIN LCD_PINS_RS + #endif + #endif + + #if PIN_EXISTS(LCD_RESET) + // Perform a clean hardware reset with needed delays + OUT_WRITE(LCD_RESET_PIN, LOW); + hal.delay_ms(5); + WRITE(LCD_RESET_PIN, HIGH); + hal.delay_ms(5); + u8g.begin(); + #endif + + #if PIN_EXISTS(LCD_BACKLIGHT) && ENABLED(DELAYED_BACKLIGHT_INIT) + WRITE(LCD_BACKLIGHT_PIN, HIGH); + #endif + + TERN_(HAS_LCD_CONTRAST, refresh_contrast()); + + #if LCD_SCREEN_ROTATE == 90 + u8g.setRot90(); + #elif LCD_SCREEN_ROTATE == 180 + u8g.setRot180(); + #elif LCD_SCREEN_ROTATE == 270 + u8g.setRot270(); + #endif + + update_language_font(); +} + +void MarlinUI::update_language_font() { + #if HAS_MULTI_LANGUAGE + switch (language) { + default: uxg_SetUtf8Fonts(LANG_FONT_INFO(LCD_LANGUAGE), COUNT(LANG_FONT_INFO(LCD_LANGUAGE))); break; + #ifdef LCD_LANGUAGE_2 + case 1: uxg_SetUtf8Fonts(LANG_FONT_INFO(LCD_LANGUAGE_2), COUNT(LANG_FONT_INFO(LCD_LANGUAGE_2))); break; + #endif + #ifdef LCD_LANGUAGE_3 + case 2: uxg_SetUtf8Fonts(LANG_FONT_INFO(LCD_LANGUAGE_3), COUNT(LANG_FONT_INFO(LCD_LANGUAGE_3))); break; + #endif + #ifdef LCD_LANGUAGE_4 + case 3: uxg_SetUtf8Fonts(LANG_FONT_INFO(LCD_LANGUAGE_4), COUNT(LANG_FONT_INFO(LCD_LANGUAGE_4))); break; + #endif + #ifdef LCD_LANGUAGE_5 + case 4: uxg_SetUtf8Fonts(LANG_FONT_INFO(LCD_LANGUAGE_5), COUNT(LANG_FONT_INFO(LCD_LANGUAGE_5))); break; + #endif + } + #else + uxg_SetUtf8Fonts(LANG_FONT_INFO(LCD_LANGUAGE), COUNT(LANG_FONT_INFO(LCD_LANGUAGE))); + #endif +} + +// The kill screen is displayed for unrecoverable conditions +void MarlinUI::draw_kill_screen() { + TERN_(LIGHTWEIGHT_UI, ST7920_Lite_Status_Screen::clear_text_buffer()); + const u8g_uint_t x = 0, h4 = u8g.getHeight() / 4; + u8g.firstPage(); + do { + set_font(FONT_MENU); + lcd_put_u8str(x, h4 * 1, status_message); + lcd_put_u8str(x, h4 * 2, GET_TEXT_F(MSG_HALTED)); + lcd_put_u8str(x, h4 * 3, GET_TEXT_F(MSG_PLEASE_RESET)); + } while (u8g.nextPage()); +} + +void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop + +#if HAS_DISPLAY_SLEEP + void MarlinUI::sleep_on() { u8g.sleepOn(); } + void MarlinUI::sleep_off() { u8g.sleepOff(); } +#endif + +#if HAS_LCD_BRIGHTNESS + + void MarlinUI::_set_brightness() { + #if PIN_EXISTS(TFT_BACKLIGHT) + if (PWM_PIN(TFT_BACKLIGHT_PIN)) + analogWrite(pin_t(TFT_BACKLIGHT_PIN), backlight ? brightness : 0); + #endif + } + +#endif + +#if HAS_MARLINUI_MENU + + #include "../menu/menu.h" + + u8g_uint_t row_y1, row_y2; + + #if ENABLED(ADVANCED_PAUSE_FEATURE) + + void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) { + u8g_uint_t y1 = row * (MENU_FONT_HEIGHT) + 1, y2 = y1 + MENU_FONT_HEIGHT - 1; + + if (!PAGE_CONTAINS(y1 + 1, y2 + 2)) return; + + lcd_put_lchar(LCD_PIXEL_WIDTH - 11 * (MENU_FONT_WIDTH), y2, 'E'); + lcd_put_lchar((char)('1' + extruder)); + lcd_put_lchar(' '); + lcd_put_u8str(i16tostr3rj(thermalManager.wholeDegHotend(extruder))); + lcd_put_lchar('/'); + + if (get_blink() || !thermalManager.heater_idle[extruder].timed_out) + lcd_put_u8str(i16tostr3rj(thermalManager.degTargetHotend(extruder))); + } + + #endif // ADVANCED_PAUSE_FEATURE + + // Mark a menu item and set font color if selected. + // Return 'false' if the item is not on screen. + static bool mark_as_selected(const uint8_t row, const bool sel) { + row_y1 = row * (MENU_FONT_HEIGHT) + 1; + row_y2 = row_y1 + MENU_FONT_HEIGHT - 1; + + if (!PAGE_CONTAINS(row_y1 + 1, row_y2 + 2)) return false; + + if (sel) { + #if ENABLED(MENU_HOLLOW_FRAME) + u8g.drawHLine(0, row_y1 + 1, LCD_PIXEL_WIDTH); + u8g.drawHLine(0, row_y2 + 2, LCD_PIXEL_WIDTH); + #else + u8g.setColorIndex(1); // solid outline + u8g.drawBox(0, row_y1 + 2, LCD_PIXEL_WIDTH, MENU_FONT_HEIGHT - 1); + u8g.setColorIndex(0); // inverted text + #endif + } + #if DISABLED(MENU_HOLLOW_FRAME) + else u8g.setColorIndex(1); // solid text + #endif + + if (!PAGE_CONTAINS(row_y1, row_y2)) return false; + + lcd_moveto(0, row_y2); + return true; + } + + // Draw a static line of text in the same idiom as a menu item + void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) { + + if (mark_as_selected(row, style & SS_INVERT)) { + pixel_len_t n = LCD_PIXEL_WIDTH; // pixel width of string allowed + + const int plen = ftpl ? calculateWidth(ftpl) : 0, + vlen = vstr ? utf8_strlen(vstr) : 0; + if (style & SS_CENTER) { + int pad = (LCD_PIXEL_WIDTH - plen - vlen * MENU_FONT_WIDTH) / MENU_FONT_WIDTH / 2; + while (--pad >= 0) n -= lcd_put_lchar(' '); + } + + if (plen) n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n / (MENU_FONT_WIDTH)) * (MENU_FONT_WIDTH); + if (vlen) n -= lcd_put_u8str_max(vstr, n); + while (n > MENU_FONT_WIDTH) n -= lcd_put_lchar(' '); + } + } + + // Draw a generic menu item + void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char, const char post_char) { + if (mark_as_selected(row, sel)) { + pixel_len_t n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 1) * (MENU_FONT_WIDTH); + while (n > MENU_FONT_WIDTH) n -= lcd_put_lchar(' '); + lcd_put_lchar(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH), row_y2, post_char); + lcd_put_lchar(' '); + } + } + + // Draw a menu item with an editable value + void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) { + if (mark_as_selected(row, sel)) { + const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(inStr)), + pixelwidth = (pgm ? uxg_GetUtf8StrPixelWidthP(u8g.getU8g(), inStr) : uxg_GetUtf8StrPixelWidth(u8g.getU8g(), inStr)); + const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1; + + pixel_len_t n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 2 - vallen * prop) * (MENU_FONT_WIDTH); + if (vallen) { + lcd_put_lchar(':'); + while (n > MENU_FONT_WIDTH) n -= lcd_put_lchar(' '); + lcd_moveto(LCD_PIXEL_WIDTH - _MAX((MENU_FONT_WIDTH) * vallen, pixelwidth + 2), row_y2); + if (pgm) lcd_put_u8str_P(inStr); else lcd_put_u8str(inStr); + } + } + } + + void MenuEditItemBase::draw_edit_screen(FSTR_P const ftpl, const char * const value/*=nullptr*/) { + ui.encoder_direction_normal(); + + const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1; + const u8g_uint_t labellen = utf8_strlen(ftpl), vallen = utf8_strlen(value); + bool extra_row = labellen * prop > LCD_WIDTH - 2 - vallen * prop; + + #if ENABLED(USE_BIG_EDIT_FONT) + // Use the menu font if the label won't fit on a single line + constexpr u8g_uint_t lcd_edit_width = (LCD_PIXEL_WIDTH) / (EDIT_FONT_WIDTH); + u8g_uint_t lcd_chr_fit, one_chr_width; + if (labellen * prop <= lcd_edit_width - 1) { + if (labellen * prop + vallen * prop + 1 > lcd_edit_width) extra_row = true; + lcd_chr_fit = lcd_edit_width + 1; + one_chr_width = EDIT_FONT_WIDTH; + ui.set_font(FONT_EDIT); + } + else { + lcd_chr_fit = LCD_WIDTH; + one_chr_width = MENU_FONT_WIDTH; + ui.set_font(FONT_MENU); + } + #else + constexpr u8g_uint_t lcd_chr_fit = LCD_WIDTH, + one_chr_width = MENU_FONT_WIDTH; + #endif + + // Center the label and value lines on the middle line + u8g_uint_t baseline = extra_row ? (LCD_PIXEL_HEIGHT) / 2 - 1 + : (LCD_PIXEL_HEIGHT + EDIT_FONT_ASCENT) / 2; + + // Assume the label is alpha-numeric (with a descender) + bool onpage = PAGE_CONTAINS(baseline - (EDIT_FONT_ASCENT - 1), baseline + EDIT_FONT_DESCENT); + if (onpage) lcd_put_u8str(0, baseline, ftpl, itemIndex, itemStringC, itemStringF); + + // If a value is included, print a colon, then print the value right-justified + if (value) { + lcd_put_lchar(':'); + if (extra_row) { + // Assume that value is numeric (with no descender) + baseline += EDIT_FONT_ASCENT + 2; + onpage = PAGE_CONTAINS(baseline - (EDIT_FONT_ASCENT - 1), baseline); + } + if (onpage) { + lcd_put_lchar(((lcd_chr_fit - 1) - (vallen * prop + 1)) * one_chr_width, baseline, ' '); // Right-justified, padded, add a leading space + lcd_put_u8str(value); + } + } + TERN_(USE_BIG_EDIT_FONT, ui.set_font(FONT_MENU)); + } + + inline void draw_boxed_string(const u8g_uint_t x, const u8g_uint_t y, FSTR_P const fstr, const bool inv) { + const u8g_uint_t len = utf8_strlen(fstr), + by = (y + 1) * (MENU_FONT_HEIGHT); + const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1; + const pixel_len_t bw = len * prop * (MENU_FONT_WIDTH), bx = x * prop * (MENU_FONT_WIDTH); + if (inv) { + u8g.setColorIndex(1); + u8g.drawBox(bx / prop - 1, by - (MENU_FONT_ASCENT), bw + 2, MENU_FONT_HEIGHT); + u8g.setColorIndex(0); + } + lcd_put_u8str(bx / prop, by, fstr); + if (inv) u8g.setColorIndex(1); + } + + void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const fpre, const char * const string/*=nullptr*/, FSTR_P const suff/*=nullptr*/) { + ui.draw_select_screen_prompt(fpre, string, suff); + if (no) draw_boxed_string(1, LCD_HEIGHT - 1, no, !yesno); + if (yes) draw_boxed_string(LCD_WIDTH - (utf8_strlen(yes) * (USE_WIDE_GLYPH ? 2 : 1) + 1), LCD_HEIGHT - 1, yes, yesno); + } + + #if ENABLED(SDSUPPORT) + + void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) { + if (mark_as_selected(row, sel)) { + const uint8_t maxlen = LCD_WIDTH - isDir; + if (isDir) lcd_put_lchar(LCD_STR_FOLDER[0]); + const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH); + pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw); + while (n > MENU_FONT_WIDTH) n -= lcd_put_lchar(' '); + } + } + + #endif // SDSUPPORT + + #if ENABLED(AUTO_BED_LEVELING_UBL) + + /** + * UBL LCD "radar" map data + */ + #define MAP_UPPER_LEFT_CORNER_X 35 // These probably should be moved to the .h file But for now, + #define MAP_UPPER_LEFT_CORNER_Y 8 // it is easier to play with things having them here + #define MAP_MAX_PIXELS_X 53 + #define MAP_MAX_PIXELS_Y 49 + + void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) { + // Scale the box pixels appropriately + u8g_uint_t x_map_pixels = ((MAP_MAX_PIXELS_X - 4) / (GRID_MAX_POINTS_X)) * (GRID_MAX_POINTS_X), + y_map_pixels = ((MAP_MAX_PIXELS_Y - 4) / (GRID_MAX_POINTS_Y)) * (GRID_MAX_POINTS_Y), + + pixels_per_x_mesh_pnt = x_map_pixels / (GRID_MAX_POINTS_X), + pixels_per_y_mesh_pnt = y_map_pixels / (GRID_MAX_POINTS_Y), + + x_offset = MAP_UPPER_LEFT_CORNER_X + 1 + (MAP_MAX_PIXELS_X - x_map_pixels - 2) / 2, + y_offset = MAP_UPPER_LEFT_CORNER_Y + 1 + (MAP_MAX_PIXELS_Y - y_map_pixels - 2) / 2; + + // Clear the Mesh Map + + if (PAGE_CONTAINS(y_offset - 2, y_offset + y_map_pixels + 4)) { + u8g.setColorIndex(1); // First draw the bigger box in White so we have a border around the mesh map box + u8g.drawBox(x_offset - 2, y_offset - 2, x_map_pixels + 4, y_map_pixels + 4); + if (PAGE_CONTAINS(y_offset, y_offset + y_map_pixels)) { + u8g.setColorIndex(0); // Now actually clear the mesh map box + u8g.drawBox(x_offset, y_offset, x_map_pixels, y_map_pixels); + } + } + + // Display Mesh Point Locations + + u8g.setColorIndex(1); + const u8g_uint_t sx = x_offset + pixels_per_x_mesh_pnt / 2; + u8g_uint_t y = y_offset + pixels_per_y_mesh_pnt / 2; + for (uint8_t j = 0; j < (GRID_MAX_POINTS_Y); j++, y += pixels_per_y_mesh_pnt) + if (PAGE_CONTAINS(y, y)) + for (uint8_t i = 0, x = sx; i < (GRID_MAX_POINTS_X); i++, x += pixels_per_x_mesh_pnt) + u8g.drawBox(x, y, 1, 1); + + // Fill in the Specified Mesh Point + + const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y) - 1 - y_plot; // The origin is typically in the lower right corner. We need to + // invert the Y to get it to plot in the right location. + + const u8g_uint_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt; + if (PAGE_CONTAINS(by, by + pixels_per_y_mesh_pnt)) + u8g.drawBox( + x_offset + x_plot * pixels_per_x_mesh_pnt, by, + pixels_per_x_mesh_pnt, pixels_per_y_mesh_pnt + ); + + // Put Relevant Text on Display + + // Show X and Y positions at top of screen + u8g.setColorIndex(1); + if (PAGE_UNDER(7)) { + const xy_pos_t pos = { bedlevel.get_mesh_x(x_plot), bedlevel.get_mesh_y(y_plot) }, + lpos = pos.asLogical(); + lcd_put_u8str_P(5, 7, X_LBL); + lcd_put_u8str(ftostr52(lpos.x)); + lcd_put_u8str_P(74, 7, Y_LBL); + lcd_put_u8str(ftostr52(lpos.y)); + } + + // Print plot position + if (PAGE_CONTAINS(LCD_PIXEL_HEIGHT - (INFO_FONT_HEIGHT - 1), LCD_PIXEL_HEIGHT)) { + lcd_put_lchar(5, LCD_PIXEL_HEIGHT, '('); + u8g.print(x_plot); + lcd_put_lchar(','); + u8g.print(y_plot); + lcd_put_lchar(')'); + + // Show the location value + lcd_put_u8str_P(74, LCD_PIXEL_HEIGHT, Z_LBL); + if (!isnan(bedlevel.z_values[x_plot][y_plot])) + lcd_put_u8str(ftostr43sign(bedlevel.z_values[x_plot][y_plot])); + else + lcd_put_u8str(F(" -----")); + } + + } + + #endif // AUTO_BED_LEVELING_UBL + + #if EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY) + + // + // Draw knob rotation => Z motion key for: + // - menu.cpp:lcd_babystep_zoffset + // - menu_ubl.cpp:_lcd_mesh_fine_tune + // + + const unsigned char cw_bmp[] PROGMEM = { + B00000000,B11111110,B00000000, + B00000011,B11111111,B10000000, + B00000111,B11000111,B11000000, + B00000111,B00000001,B11100000, + B00000000,B00000000,B11100000, + B00000000,B00000000,B11110000, + B00000000,B00000000,B01110000, + B00000100,B00000000,B01110000, + B00001110,B00000000,B01110000, + B00011111,B00000000,B01110000, + B00111111,B10000000,B11110000, + B00001110,B00000000,B11100000, + B00001111,B00000001,B11100000, + B00000111,B11000111,B11000000, + B00000011,B11111111,B10000000, + B00000000,B11111110,B00000000 + }; + + const unsigned char ccw_bmp[] PROGMEM = { + B00000000,B11111110,B00000000, + B00000011,B11111111,B10000000, + B00000111,B11000111,B11000000, + B00001111,B00000001,B11100000, + B00001110,B00000000,B11100000, + B00111111,B10000000,B11110000, + B00011111,B00000000,B01110000, + B00001110,B00000000,B01110000, + B00000100,B00000000,B01110000, + B00000000,B00000000,B01110000, + B00000000,B00000000,B11110000, + B00000000,B00000000,B11100000, + B00000111,B00000001,B11100000, + B00000111,B11000111,B11000000, + B00000011,B11111111,B10000000, + B00000000,B11111110,B00000000 + }; + + const unsigned char up_arrow_bmp[] PROGMEM = { + B00000100,B00000000, + B00001110,B00000000, + B00011111,B00000000, + B00111111,B10000000, + B01111111,B11000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000 + }; + + const unsigned char down_arrow_bmp[] PROGMEM = { + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B00001110,B00000000, + B01111111,B11000000, + B00111111,B10000000, + B00011111,B00000000, + B00001110,B00000000, + B00000100,B00000000 + }; + + const unsigned char offset_bedline_bmp[] PROGMEM = { + B11111111,B11111111,B11111111 + }; + + const unsigned char nozzle_bmp[] PROGMEM = { + B01111111,B10000000, + B11111111,B11000000, + B11111111,B11000000, + B11111111,B11000000, + B01111111,B10000000, + B01111111,B10000000, + B11111111,B11000000, + B11111111,B11000000, + B11111111,B11000000, + B00111111,B00000000, + B00011110,B00000000, + B00001100,B00000000 + }; + + void MarlinUI::zoffset_overlay(const int8_t dir) { + const unsigned char *rot_up = TERN(OVERLAY_GFX_REVERSE, ccw_bmp, cw_bmp), + *rot_down = TERN(OVERLAY_GFX_REVERSE, cw_bmp, ccw_bmp); + + const int left = TERN(USE_BIG_EDIT_FONT, 0, 5), + right = TERN(USE_BIG_EDIT_FONT, 45, 90), + nozzle = TERN(USE_BIG_EDIT_FONT, 95, 60); + + // Draw nozzle lowered or raised according to direction moved + if (PAGE_CONTAINS( 3, 16)) u8g.drawBitmapP(nozzle + 6, 4 - dir, 2, 12, nozzle_bmp); + if (PAGE_CONTAINS(20, 20)) u8g.drawBitmapP(nozzle + 0, 20 , 3, 1, offset_bedline_bmp); + + // Draw cw/ccw indicator and up/down arrows. + if (PAGE_CONTAINS(47, 62)) { + u8g.drawBitmapP(right + 0, 48 - dir, 2, 13, up_arrow_bmp); + u8g.drawBitmapP(left + 0, 49 - dir, 2, 13, down_arrow_bmp); + u8g.drawBitmapP(left + 13, 47 , 3, 16, rot_down); + u8g.drawBitmapP(right + 13, 47 , 3, 16, rot_up); + } + } + + #endif // BABYSTEP_ZPROBE_GFX_OVERLAY || MESH_EDIT_GFX_OVERLAY + +#endif // HAS_MARLINUI_MENU + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/marlinui_DOGM.h b/src/lcd/dogm/marlinui_DOGM.h new file mode 100644 index 0000000..050f147 --- /dev/null +++ b/src/lcd/dogm/marlinui_DOGM.h @@ -0,0 +1,234 @@ +/** + * 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/dogm/marlinui_DOGM.h + */ + +#include "../../inc/MarlinConfigPre.h" + +#include +#include "HAL_LCD_class_defines.h" + +//#define ALTERNATIVE_LCD + +#if ENABLED(REPRAPWORLD_GRAPHICAL_LCD) + + // RepRapWorld Graphical LCD + + #define U8G_CLASS U8GLIB_ST7920_128X64_4X + #if DISABLED(SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN) && (LCD_PINS_ENABLE == SD_MOSI_PIN) + #define U8G_PARAM LCD_PINS_RS + #else + #define U8G_PARAM LCD_PINS_D4, LCD_PINS_ENABLE, LCD_PINS_RS + #endif + +#elif IS_U8GLIB_ST7920 + + // RepRap Discount Full Graphics Smart Controller + // and other variant LCDs using ST7920 + + #if DISABLED(SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN) && (LCD_PINS_ENABLE == SD_MOSI_PIN) + #define U8G_CLASS U8GLIB_ST7920_128X64_4X_HAL // 2 stripes, HW SPI (Shared with SD card. Non-standard LCD adapter on AVR.) + #define U8G_PARAM LCD_PINS_RS + #else + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_ST7920_128X64_4X // 2 stripes, SW SPI (Original u8glib device) + #else + #define U8G_CLASS U8GLIB_ST7920_128X64_RRD // Adjust stripes with PAGE_HEIGHT in ultralcd_st7920_u8glib_rrd.h + #endif + #define U8G_PARAM LCD_PINS_D4, LCD_PINS_ENABLE, LCD_PINS_RS // AVR version ignores these pin settings + // HAL version uses these pin settings + #endif + +#elif ENABLED(CARTESIO_UI) + + // CartesioUI LCD + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_DOGM128_2X // 4 stripes + #define FORCE_SOFT_SPI // SW-SPI + #else + #define U8G_CLASS U8GLIB_DOGM128_2X // 4 stripes (HW-SPI) + #endif + +#elif IS_U8GLIB_LM6059_AF + + // Based on the Adafruit ST7565 (https://www.adafruit.com/products/250) + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_LM6059 // 8 stripes (HW-SPI) + #else + #define U8G_CLASS U8GLIB_LM6059_2X // 4 stripes (HW-SPI) + #endif + +#elif IS_U8GLIB_ST7565_64128N + + // MaKrPanel, Mini Viki, Viki 2.0, AZSMZ 12864 ST7565 controller + + #define SMART_RAMPS MB(RAMPS_SMART_EFB, RAMPS_SMART_EEB, RAMPS_SMART_EFF, RAMPS_SMART_EEF, RAMPS_SMART_SF) + #define U8G_CLASS U8GLIB_64128N_2X_HAL // 4 stripes (HW-SPI) + + #if (SMART_RAMPS && defined(__SAM3X8E__)) || DOGLCD_SCK != SD_SCK_PIN || DOGLCD_MOSI != SD_MOSI_PIN + #define FORCE_SOFT_SPI // SW-SPI + #endif + +#elif ANY(FYSETC_MINI_12864, MKS_MINI_12864, ENDER2_STOCKDISPLAY) + + // The FYSETC Mini 12864 display // "4 stripes" + + // The MKS_MINI_12864 V1/V2 aren't exact copies of the MiniPanel. + // Panel management is in u8g_dev_uc1701_mini12864_HAL.cpp with + // extra delays added to remove glitches seen with fast MCUs. + + #define U8G_CLASS U8GLIB_MINI12864_2X_HAL // 8 stripes (HW-SPI) + +#elif ENABLED(MINIPANEL) + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_MINI12864 + #else + #define U8G_CLASS U8GLIB_MINI12864_2X // 8 stripes (HW-SPI) + #endif + +#elif ENABLED(MKS_12864OLED_SSD1306) + + // MKS 128x64 (SSD1306) OLED I2C LCD + + #define FORCE_SOFT_SPI // SW-SPI + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_SSD1306_128X64_2X // 4 stripes + #else + #define U8G_CLASS U8GLIB_SSD1306_128X64 // 8 stripes + #endif + +#elif EITHER(FYSETC_242_OLED_12864, K3D_242_OLED_CONTROLLER) + + // FYSETC OLED 2.42" 128 × 64 Full Graphics Controller + // or K3D OLED 2.42" 128 × 64 Full Graphics Controller + + #define FORCE_SOFT_SPI // SW-SPI + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_SSD1306_128X64_2X // 4 stripes + #else + #define U8G_CLASS U8GLIB_SSD1309_128X64_HAL + #endif + +#elif ENABLED(ZONESTAR_12864OLED_SSD1306) + + // Zonestar SSD1306 OLED SPI LCD + + #define FORCE_SOFT_SPI // SW-SPI + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_SH1306_128X64_2X // 4 stripes + #else + #define U8G_CLASS U8GLIB_SH1306_128X64 // 8 stripes + #endif + +#elif EITHER(MKS_12864OLED, ZONESTAR_12864OLED) + + // MKS 128x64 (SH1106) OLED I2C LCD + // - or - + // Zonestar SH1106 OLED SPI LCD + + #define FORCE_SOFT_SPI // SW-SPI + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_SH1106_128X64_2X // 4 stripes + #else + #define U8G_CLASS U8GLIB_SH1106_128X64 // 8 stripes + #endif + +#elif ENABLED(U8GLIB_SH1106_EINSTART) + + // Connected via motherboard header + + #define U8G_CLASS U8GLIB_SH1106_128X64 + #define U8G_PARAM DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, LCD_PINS_DC, LCD_PINS_RS + +#elif ENABLED(U8GLIB_SH1106) + + // Generic SH1106 OLED I2C LCD + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_SH1106_128X64_2X_I2C_2_WIRE // 4 stripes + #else + #define U8G_CLASS U8GLIB_SH1106_128X64_2X // 4 stripes + #endif + #define U8G_PARAM (U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST) // I2C + +#elif ENABLED(U8GLIB_SSD1309) + + // Generic support for SSD1309 OLED I2C LCDs + + #define U8G_CLASS U8GLIB_SSD1309_128X64 + #define U8G_PARAM (U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST) // I2C + +#elif ENABLED(U8GLIB_SSD1306) + + // Generic SSD1306 OLED I2C LCD + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_SSD1306_128X64_2X_I2C_2_WIRE // 4 stripes + #else + #define U8G_CLASS U8GLIB_SSD1306_128X64_2X // 4 stripes + #endif + #define U8G_PARAM (U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST) + +#elif TFT_SCALED_DOGLCD + + // Unspecified 320x240 TFT pre-initialized by built-in bootloader + + #define U8G_CLASS U8GLIB_TFT_320X240_UPSCALE_FROM_128X64 + #if HAS_FSMC_GRAPHICAL_TFT + #define U8G_PARAM FSMC_CS_PIN, FSMC_RS_PIN + #else + #define U8G_PARAM -1, -1 + #endif + +#else + + #if ENABLED(ALTERNATIVE_LCD) + #define U8G_CLASS U8GLIB_DOGM128 // 8 stripes (HW-SPI) + #else + #define U8G_CLASS U8GLIB_DOGM128_2X // 4 stripes (HW-SPI) + #endif + +#endif + +// Use HW-SPI if no other option is specified +#ifndef U8G_PARAM + #if ENABLED(FORCE_SOFT_SPI) + #define U8G_PARAM DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, DOGLCD_A0 // SW-SPI + #else + #define U8G_PARAM DOGLCD_CS, DOGLCD_A0 // HW-SPI + #endif +#endif + +// For selective rendering within a Y range +#define PAGE_OVER(ya) ((ya) <= u8g.getU8g()->current_page.y1) // Does the current page follow a region top? +#define PAGE_UNDER(yb) ((yb) >= u8g.getU8g()->current_page.y0) // Does the current page precede a region bottom? +#define PAGE_CONTAINS(ya, yb) ((yb) >= u8g.getU8g()->current_page.y0 && (ya) <= u8g.getU8g()->current_page.y1) // Do two vertical regions overlap? + +extern U8G_CLASS u8g; diff --git a/src/lcd/dogm/status/ammeter.h b/src/lcd/dogm/status/ammeter.h new file mode 100644 index 0000000..d99ea69 --- /dev/null +++ b/src/lcd/dogm/status/ammeter.h @@ -0,0 +1,68 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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/dogm/status/ammeter.h - Status Screen Laser Ammeter bitmaps +// + +#define STATUS_AMMETER_WIDTH 20 + +const unsigned char status_ammeter_bmp_mA[] PROGMEM = { + B00000000,B11111100,B00000000, + B00000011,B00000011,B00000000, + B00000100,B00000000,B10000000, + B00001000,B00000000,B01000000, + B00010000,B00000110,B00100000, + B00010000,B00001001,B00100000, + B00100000,B00001001,B00010000, + B00100011,B01001111,B00010000, + B11100010,B10101001,B00011100, + B00100010,B10101001,B00010000, + B00100010,B10101001,B00010000, + B00010000,B00000000,B00100000, + B00010000,B00000000,B00100000, + B00001000,B00000000,B01000000, + B00000100,B00000000,B10000000, + B00000011,B00000011,B00000000, + B00000000,B11111100,B00000000 +}; + +const unsigned char status_ammeter_bmp_A[] PROGMEM = { + B00000000,B11111100,B00000000, + B00000011,B00000011,B00000000, + B00000100,B00000000,B10000000, + B00001000,B00000000,B01000000, + B00010000,B00000000,B00100000, + B00010000,B00110000,B00100000, + B00100000,B01001000,B00010000, + B00100000,B01001000,B00010000, + B11100000,B01111000,B00011100, + B00100000,B01001000,B00010000, + B00100000,B01001000,B00010000, + B00010000,B01001000,B00100000, + B00010000,B00000000,B00100000, + B00001000,B00000000,B01000000, + B00000100,B00000000,B10000000, + B00000011,B00000011,B00000000, + B00000000,B11111100,B00000000, +}; diff --git a/src/lcd/dogm/status/bed.h b/src/lcd/dogm/status/bed.h new file mode 100644 index 0000000..27f5617 --- /dev/null +++ b/src/lcd/dogm/status/bed.h @@ -0,0 +1,138 @@ +/** + * 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/dogm/status/bed.h - Status Screen Bed bitmaps +// + +#if ENABLED(STATUS_ALT_BED_BITMAP) + + #define STATUS_BED_ANIM + #define STATUS_BED_WIDTH 24 + + #define STATUS_BED_TEXT_X (STATUS_BED_X + 11) + + const unsigned char status_bed_bmp[] PROGMEM = { + B11111111,B11111111,B11000000, + B01000000,B00000000,B00100000, + B00100000,B00000000,B00010000, + B00010000,B00000000,B00001000, + B00001000,B00000000,B00000100, + B00000100,B00000000,B00000010, + B00000011,B11111111,B11111111 + }; + + #if HAS_LEVELING + const unsigned char status_bed_leveled_bmp[] PROGMEM = { + B11111111,B11111111,B11001110, + B01000000,B00100000,B00100100, + B00100000,B00010000,B00010000, + B00011111,B11111111,B11111000, + B00001000,B00000100,B00000100, + B00100100,B00000010,B00000010, + B01110011,B11111111,B11111111 + }; + #endif + + const unsigned char status_bed_on_bmp[] PROGMEM = { + B00000010,B00100010,B00000000, + B00000100,B01000100,B00000000, + B00000100,B01000100,B00000000, + B00000010,B00100010,B00000000, + B00000001,B00010001,B00000000, + B11111111,B11111111,B11000000, + B01000000,B10001000,B10100000, + B00100001,B00010001,B00010000, + B00010010,B00100010,B00001000, + B00001000,B00000000,B00000100, + B00000100,B00000000,B00000010, + B00000011,B11111111,B11111111 + }; + + #if HAS_LEVELING + const unsigned char status_bed_leveled_on_bmp[] PROGMEM = { + B00000010,B00100010,B00000000, + B00000100,B01000100,B00000000, + B00000100,B01000100,B00000000, + B00000010,B00100010,B00000000, + B00000001,B00010001,B00000000, + B11111111,B11111111,B11001110, + B01000000,B10101000,B10100100, + B00100001,B00010001,B00010000, + B00011111,B11111111,B11111000, + B00001000,B00000100,B00000100, + B00100100,B00000010,B00000010, + B01110011,B11111111,B11111111 + }; + #endif + +#else + + #define STATUS_BED_WIDTH 21 + + #ifdef STATUS_BED_ANIM + + const unsigned char status_bed_bmp[] PROGMEM = { + B00011111,B11111111,B11111000, + B00011111,B11111111,B11111000 + }; + + const unsigned char status_bed_on_bmp[] PROGMEM = { + B00000100,B00010000,B01000000, + B00000010,B00001000,B00100000, + B00000010,B00001000,B00100000, + B00000100,B00010000,B01000000, + B00001000,B00100000,B10000000, + B00010000,B01000001,B00000000, + B00010000,B01000001,B00000000, + B00001000,B00100000,B10000000, + B00000100,B00010000,B01000000, + B00000000,B00000000,B00000000, + B00011111,B11111111,B11111000, + B00011111,B11111111,B11111000 + }; + + #else + + const unsigned char status_bed_bmp[] PROGMEM = { + B00000100,B00010000,B01000000, + B00000010,B00001000,B00100000, + B00000010,B00001000,B00100000, + B00000100,B00010000,B01000000, + B00001000,B00100000,B10000000, + B00010000,B01000001,B00000000, + B00010000,B01000001,B00000000, + B00001000,B00100000,B10000000, + B00000100,B00010000,B01000000, + B00000000,B00000000,B00000000, + B00011111,B11111111,B11111000, + B00011111,B11111111,B11111000 + }; + + #endif + +#endif + +#ifndef STATUS_BED_X + #define STATUS_BED_X (LCD_PIXEL_WIDTH - (STATUS_BED_BYTEWIDTH + STATUS_CHAMBER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8 - TERN0(STATUS_HEAT_PERCENT, 4)) +#endif diff --git a/src/lcd/dogm/status/chamber.h b/src/lcd/dogm/status/chamber.h new file mode 100644 index 0000000..787a908 --- /dev/null +++ b/src/lcd/dogm/status/chamber.h @@ -0,0 +1,89 @@ +/** + * 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/dogm/status/chamber.h - Status Screen Chamber bitmaps +// + +#define STATUS_CHAMBER_WIDTH 21 +#if STATUS_HEATERS_WIDTH + #if ENABLED(STATUS_COMBINE_HEATERS) + #define STATUS_CHAMBER_X (LCD_PIXEL_WIDTH - 2 - (STATUS_CHAMBER_BYTEWIDTH) * 8) + #elif HAS_FAN0 && HAS_HEATED_BED && HOTENDS <= 2 + #define STATUS_CHAMBER_X (LCD_PIXEL_WIDTH - 2 - (STATUS_HEATERS_BYTEWIDTH - STATUS_CHAMBER_BYTEWIDTH) * 8) + #elif HAS_FAN0 && !HAS_HEATED_BED + #define STATUS_CHAMBER_X (LCD_PIXEL_WIDTH - (STATUS_CHAMBER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) + #else + #define STATUS_CHAMBER_X (LCD_PIXEL_WIDTH - (STATUS_CHAMBER_BYTEWIDTH) * 8) + #endif +#endif + +#ifdef STATUS_CHAMBER_ANIM + + const unsigned char status_chamber_bmp[] PROGMEM = { + B00011111,B11111111,B11111000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00010000,B00000000,B00001000, + B00011111,B11111111,B11111000, + B00011111,B11111111,B11111000 + }; + const unsigned char status_chamber_on_bmp[] PROGMEM = { + B00011111,B11111111,B11111000, + B00010000,B00000000,B00001000, + B00010000,B10000100,B00001000, + B00010000,B01000010,B00001000, + B00010000,B01000010,B00001000, + B00010000,B10000100,B00001000, + B00010001,B00001000,B00001000, + B00010001,B00001000,B00001000, + B00010000,B10000100,B00001000, + B00010000,B00000000,B00001000, + B00011111,B11111111,B11111000, + B00011111,B11111111,B11111000 + }; + +#else + + const unsigned char status_chamber_bmp[] PROGMEM = { + B00011111,B11111111,B11111000, + B00010000,B00000000,B00001000, + B00010000,B10000100,B00001000, + B00010000,B01000010,B00001000, + B00010000,B01000010,B00001000, + B00010000,B10000100,B00001000, + B00010001,B00001000,B00001000, + B00010001,B00001000,B00001000, + B00010000,B10000100,B00001000, + B00010000,B00000000,B00001000, + B00011111,B11111111,B11111000, + B00011111,B11111111,B11111000 + }; + +#endif diff --git a/src/lcd/dogm/status/combined.h b/src/lcd/dogm/status/combined.h new file mode 100644 index 0000000..070fe6b --- /dev/null +++ b/src/lcd/dogm/status/combined.h @@ -0,0 +1,315 @@ +/** + * 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/dogm/status/combined.h - Status Screen Combined Heater bitmaps +// + +#undef STATUS_HOTEND_ANIM +#undef STATUS_BED_ANIM +#define STATUS_HEATERS_XSPACE 24 + +// +// Status Screen Combined Heater bitmaps +// +#if HAS_HEATED_BED && HOTENDS <= 4 + + #if HOTENDS == 0 + + #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000 + }; + + #elif HOTENDS == 1 + + #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000, + B00000011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000 + }; + + #elif HOTENDS == 2 + + #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00111011,B01110000,B00000000,B00111100,B11110000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00111011,B01110000,B00000000,B00111010,B11110000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00111011,B01110000,B00000000,B00111110,B11110000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, + B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, + B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, + B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000, + B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000 + }; + + #elif HOTENDS == 3 + + #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00000010,B00001000,B00100000, + B00111011,B01110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00000010,B00001000,B00100000, + B00111011,B01110000,B00000000,B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00000100,B00010000,B01000000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00001000,B00100000,B10000000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00010000,B01000001,B00000000, + B00111011,B01110000,B00000000,B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00010000,B01000001,B00000000, + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00001000,B00100000,B10000000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000,B00000000,B00000010,B00001000,B00100000, + B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00000010,B00001000,B00100000, + B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000,B00000000,B00000100,B00010000,B01000000, + B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000,B00000000,B00001000,B00100000,B10000000, + B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000,B00000000,B00010000,B01000001,B00000000, + B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000,B00000000,B00010000,B01000001,B00000000, + B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000,B00000000,B00001000,B00100000,B10000000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00000100,B00010000,B01000000, + B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000, + B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00011111,B11111111,B11111000, + B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00011111,B11111111,B11111000 + }; + + #else // HOTENDS > 3 + + #define STATUS_HEATERS_WIDTH 120 + #define STATUS_BED_X 98 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000,B00000000,B00000010,B00001000,B00100000, + B00111011,B01110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00000010,B00001000,B00100000, + B00111011,B01110000,B00000000,B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000,B00000000,B00000100,B00010000,B01000000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000,B00000000,B00001000,B00100000,B10000000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000,B00000000,B00010000,B01000001,B00000000, + B00111011,B01110000,B00000000,B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000,B00000000,B00010000,B01000001,B00000000, + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000,B00000000,B00001000,B00100000,B10000000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00000010,B00001000,B00100000, + B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00000010,B00001000,B00100000, + B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000,B00000000,B00111011,B01110000,B00000000,B00000100,B00010000,B01000000, + B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000,B00000000,B00011011,B01100000,B00000000,B00001000,B00100000,B10000000, + B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000,B00000000,B00011000,B00100000,B00000000,B00010000,B01000001,B00000000, + B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000,B00000000,B00111111,B01110000,B00000000,B00010000,B01000001,B00000000, + B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000,B00000000,B00111111,B01110000,B00000000,B00001000,B00100000,B10000000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00000100,B00010000,B01000000, + B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000, + B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00011111,B11111111,B11111000, + B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00011111,B11111111,B11111000 + }; + + #endif // HOTENDS + + #define STATUS_BED_WIDTH 20 + #define STATUS_BED_TEXT_X (STATUS_BED_X + STATUS_BED_WIDTH / 2) + +#else // !HAS_HEATED_BED || HOTENDS > 3 + + #if HOTENDS == 0 + + #define STATUS_HEATERS_WIDTH 0 + + #elif HOTENDS == 1 + + #define STATUS_HEATERS_WIDTH 12 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + B00111111,B11110000, + B00111111,B11110000, + B00011111,B11100000, + B00011111,B11100000, + B00111111,B11110000, + B00111111,B11110000, + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #elif HOTENDS == 2 + + #define STATUS_HEATERS_WIDTH 36 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000, + B00111011,B01110000,B00000000,B00111100,B11110000, + B00111011,B01110000,B00000000,B00111010,B11110000, + B00011011,B01100000,B00000000,B00011110,B11100000, + B00011011,B01100000,B00000000,B00011110,B11100000, + B00111011,B01110000,B00000000,B00111110,B11110000, + B00111100,B11110000,B00000000,B00111110,B11110000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000, + B00111100,B11110000,B00000000,B00111011,B01110000, + B00111010,B11110000,B00000000,B00111111,B01110000, + B00011110,B11100000,B00000000,B00011110,B11100000, + B00011110,B11100000,B00000000,B00011101,B11100000, + B00111110,B11110000,B00000000,B00111011,B11110000, + B00111110,B11110000,B00000000,B00111000,B01110000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000, + B00001111,B11000000,B00000000,B00001111,B11000000, + B00000111,B10000000,B00000000,B00000111,B10000000, + B00000011,B00000000,B00000000,B00000011,B00000000 + }; + + #elif HOTENDS == 3 + + #define STATUS_HEATERS_WIDTH 60 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111100,B11110000, + B00111011,B01110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000, + B00111011,B01110000,B00000000,B00111010,B11110000,B00000000,B00111111,B01110000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011110,B11100000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011101,B11100000, + B00111011,B01110000,B00000000,B00111110,B11110000,B00000000,B00111011,B11110000, + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111000,B01110000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000, + B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000, + B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000, + B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000, + B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000, + B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000, + B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000, + B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000, + B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000, + B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000 + }; + + #elif HOTENDS == 4 + + #define STATUS_HEATERS_WIDTH 84 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000, + B00111011,B01110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000, + B00111011,B01110000,B00000000,B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000, + B00111011,B01110000,B00000000,B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000, + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000, + B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000, + B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000,B00000000,B00111011,B01110000, + B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000,B00000000,B00011011,B01100000, + B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000,B00000000,B00011000,B00100000, + B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000,B00000000,B00111111,B01110000, + B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000,B00000000,B00111111,B01110000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000, + B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000, + B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000, + B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000 + }; + + #else // HOTENDS > 4 + + #define STATUS_HEATERS_WIDTH 108 + + const unsigned char status_heaters_bmp[] PROGMEM = { + B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000, + B00111011,B01110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000, + B00111011,B01110000,B00000000,B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000,B00000000,B00111011,B01110000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000,B00000000,B00011011,B01100000, + B00011011,B01100000,B00000000,B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000,B00000000,B00011000,B00100000, + B00111011,B01110000,B00000000,B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000,B00000000,B00111111,B01110000, + B00111100,B11110000,B00000000,B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000,B00000000,B00111111,B01110000, + #else + B00111110,B11110000,B00000000,B00111100,B11110000,B00000000,B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111000,B01110000, + B00111100,B11110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00111011,B01110000,B00000000,B00111011,B11110000, + B00111010,B11110000,B00000000,B00111111,B01110000,B00000000,B00111111,B01110000,B00000000,B00111011,B01110000,B00000000,B00111000,B11110000, + B00011110,B11100000,B00000000,B00011110,B11100000,B00000000,B00011100,B11100000,B00000000,B00011011,B01100000,B00000000,B00011111,B01100000, + B00011110,B11100000,B00000000,B00011101,B11100000,B00000000,B00011111,B01100000,B00000000,B00011000,B00100000,B00000000,B00011111,B01100000, + B00111110,B11110000,B00000000,B00111011,B11110000,B00000000,B00111011,B01110000,B00000000,B00111111,B01110000,B00000000,B00111011,B01110000, + B00111110,B11110000,B00000000,B00111000,B01110000,B00000000,B00111100,B11110000,B00000000,B00111111,B01110000,B00000000,B00111100,B11110000, + #endif + B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000,B00000000,B00111111,B11110000, + B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000,B00000000,B00001111,B11000000, + B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000,B00000000,B00000111,B10000000, + B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000 + }; + + #endif // HOTENDS + +#endif // !HAS_HEATED_BED || HOTENDS > 3 diff --git a/src/lcd/dogm/status/cooler.h b/src/lcd/dogm/status/cooler.h new file mode 100644 index 0000000..65c28ec --- /dev/null +++ b/src/lcd/dogm/status/cooler.h @@ -0,0 +1,119 @@ +/** + * 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/dogm/status/cooler.h - Status Screen Laser Cooler bitmaps +// +#if HAS_COOLER + + #define STATUS_COOLER_WIDTH 22 + + const unsigned char status_cooler_bmp2[] PROGMEM = { + B00000001,B00000000,B10000000, + B00000001,B00100100,B10010000, + B00000101,B01000010,B10100000, + B00000011,B10000001,B11000000, + B00001111,B11101111,B11110000, + B00000011,B10000001,B11000000, + B00000101,B01000010,B10100000, + B00001001,B00001000,B10010000, + B00000001,B00001000,B00000000, + B00000000,B01001001,B00000000, + B00000000,B00101010,B00000000, + B00000000,B00011100,B00000000, + B00000001,B11111111,B11000000, + B00000000,B00011100,B00000000, + B00000000,B00101010,B00000000, + B00000000,B01001001,B00000000 + }; + const unsigned char status_cooler_bmp1[] PROGMEM = { + B00000001,B00000000,B10000000, + B00000001,B00100100,B10010000, + B00000101,B01000010,B10100000, + B00000010,B10000001,B01000000, + B00001100,B01110110,B00110000, + B00000010,B10000001,B01000000, + B00000101,B01000010,B10100000, + B00001001,B00001000,B10010000, + B00000001,B00001000,B00000000, + B00000000,B01001001,B00000000, + B00000000,B00101010,B00000000, + B00000000,B00010100,B00000000, + B00000001,B11100011,B11000000, + B00000000,B00010100,B00000000, + B00000000,B00101010,B00000000, + B00000000,B01001001,B00000000 + }; + +#endif + +#if ENABLED(LASER_COOLANT_FLOW_METER) + + #define STATUS_FLOWMETER_WIDTH 24 + + const unsigned char status_flowmeter_bmp2[] PROGMEM = { + B00000000,B01111110,B00000000, + B00000001,B10000001,B10000000, + B00000010,B00011000,B01000000, + B00000100,B00011000,B00100000, + B00001000,B00011000,B00010000, + B00001000,B00011000,B00010000, + B00010000,B00011000,B00001000, + B00010000,B00011000,B00001000, + B00010111,B11111111,B11101000, + B00010111,B11111111,B11101000, + B00010000,B00011000,B00001000, + B00010000,B00011000,B00001000, + B00001000,B00011000,B00010000, + B00001000,B00011000,B00010000, + B00000100,B00011000,B00100000, + B00000010,B00011000,B01000000, + B00000001,B10000001,B10000000, + B00000000,B01111110,B00000000, + B00000000,B00011000,B00000000, + B00000111,B11111111,B11100000 + }; + const unsigned char status_flowmeter_bmp1[] PROGMEM = { + B00000000,B01111110,B00000000, + B00000001,B10000001,B10000000, + B00000010,B00000000,B01000000, + B00000101,B00000000,B10100000, + B00001011,B10000001,B11010000, + B00001001,B11000011,B10010000, + B00010000,B11100111,B00001000, + B00010000,B01111110,B00001000, + B00010000,B00111100,B00001000, + B00010000,B00111100,B00001000, + B00010000,B01111110,B00001000, + B00010000,B11100111,B00001000, + B00001001,B11000011,B10010000, + B00001011,B10000001,B11010000, + B00000101,B00000000,B10100000, + B00000010,B00000000,B01000000, + B00000001,B10000001,B10000000, + B00000000,B01111110,B00000000, + B00000000,B00011000,B00000000, + B00000111,B11111111,B11100000 + }; + +#endif diff --git a/src/lcd/dogm/status/cutter.h b/src/lcd/dogm/status/cutter.h new file mode 100644 index 0000000..0e3b9dd --- /dev/null +++ b/src/lcd/dogm/status/cutter.h @@ -0,0 +1,123 @@ +/** + * 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/dogm/status/cutter.h - Status Screen Laser / Spindle bitmaps +// + +#define STATUS_CUTTER_WIDTH 24 +#define STATUS_CUTTER_X 80 + +#if ENABLED(LASER_FEATURE) + #ifdef STATUS_CUTTER_ANIM + const unsigned char status_cutter_on_bmp[] PROGMEM = { + B00000000,B00100100,B00000000, + B00000000,B01100110,B00000000, + B00000000,B11000011,B00000000, + B00000001,B10011001,B10000000, + B00000011,B00100100,B11000000, + B00000000,B01000010,B00000000, + B00000000,B01000010,B00000000, + B00000011,B00100100,B11000000, + B00000001,B10011001,B10000000, + B00000000,B11000011,B00000000, + B00000000,B01100110,B00000000, + B00000000,B00100100,B00000000 + }; + const unsigned char status_cutter_bmp[] PROGMEM = { + B00000000,B00100100,B00000000, + B00000000,B01100110,B00000000, + B00000000,B00000000,B00000000, + B00000001,B00000000,B10000000, + B00000011,B00000000,B11000000, + B00000000,B00011000,B00000000, + B00000000,B00011000,B00000000, + B00000011,B00000000,B11000000, + B00000001,B00000000,B10000000, + B00000000,B00000000,B00000000, + B00000000,B01100110,B00000000, + B00000000,B00100100,B00000000 + }; + #else + const unsigned char status_cutter_bmp[] PROGMEM = { + B00000000,B00100100,B00000000, + B00000000,B01100110,B00000000, + B00000000,B11000011,B00000000, + B00000001,B10000001,B10000000, + B00000011,B00000000,B11000000, + B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000, + B00000011,B00000000,B11000000, + B00000001,B10000001,B10000000, + B00000000,B11000011,B00000000, + B00000000,B01100110,B00000000, + B00000000,B00100100,B00000000 + }; + #endif +#else + #ifdef STATUS_CUTTER_ANIM + const unsigned char status_cutter_on_bmp[] PROGMEM = { + B00000001,B11111110,B10000000, + B00000000,B11000000,B00000000, + B00000001,B10000000,B10000000, + B00000001,B00000000,B10000000, + B00000001,B11111100,B10000000, + B00000000,B11100000,B00000000, + B00000001,B11000000,B10000000, + B00000000,B10000001,B00000000, + B00000000,B01111010,B00000000, + B00000000,B00110100,B00000000, + B00000000,B00011000,B00000000, + B00000000,B00000000,B00000000 + }; + const unsigned char status_cutter_bmp[] PROGMEM = { + B00000001,B11111110,B10000000, + B00000000,B11000000,B00000000, + B00000001,B10000000,B10000000, + B00000001,B00000000,B10000000, + B00000001,B11111100,B10000000, + B00000000,B11100000,B00000000, + B00000001,B11000000,B10000000, + B00000000,B10000001,B00000000, + B00000000,B01111010,B00000000, + B00000000,B00110100,B00000000, + B00000000,B00011000,B00000000, + B00000000,B00000000,B00000000 + }; + #else + const unsigned char status_cutter_bmp[] PROGMEM = { + B00000001,B11000010,B10000000, + B00000001,B00011100,B10000000, + B00000000,B11100001,B00000000, + B00000001,B00001110,B10000000, + B00000001,B01110000,B10000000, + B00000000,B10000111,B10000000, + B00000001,B00111111,B10000000, + B00000000,B11111111,B00000000, + B00000000,B01111110,B00000000, + B00000000,B00111100,B00000000, + B00000000,B00011000,B00000000, + B00000000,B00000000,B00000000 + }; + #endif +#endif diff --git a/src/lcd/dogm/status/fan.h b/src/lcd/dogm/status/fan.h new file mode 100644 index 0000000..65f8e9c --- /dev/null +++ b/src/lcd/dogm/status/fan.h @@ -0,0 +1,443 @@ +/** + * 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/dogm/status/fan.h - Status Screen Fan bitmaps +// + +#undef STATUS_FAN_WIDTH +#define STATUS_FAN_WIDTH 20 + +#if STATUS_FAN_FRAMES <= 2 + + #define STATUS_FAN_Y 2 + + #if ENABLED(STATUS_ALT_FAN_BITMAP) + + const unsigned char status_fan0_bmp[] PROGMEM = { + B00000001,B11111110,B00000000, + B00000110,B00000001,B10000000, + B00001000,B11111100,B01000000, + B00010000,B11111100,B00100000, + B00010000,B01111000,B00100000, + B00100000,B00110000,B00010000, + B00101100,B00000000,B11010000, + B00101110,B00110001,B11010000, + B00101111,B01111011,B11010000, + B00101111,B01111011,B11010000, + B00101110,B00110001,B11010000, + B00101100,B00000000,B11010000, + B00100000,B00110000,B00010000, + B00010000,B01111000,B00100000, + B00010000,B11111100,B00100000, + B00001000,B11111100,B01000000, + B00000110,B00000001,B10000000, + B00000001,B11111110,B00000000 + }; + + #if STATUS_FAN_FRAMES == 2 + const unsigned char status_fan1_bmp[] PROGMEM = { + B00000001,B11111110,B00000000, + B00000110,B00000001,B10000000, + B00001001,B10000110,B01000000, + B00010011,B10000111,B00100000, + B00010111,B10000111,B10100000, + B00101111,B10000111,B11010000, + B00101111,B00000011,B11010000, + B00100000,B00110000,B00010000, + B00100000,B01111000,B00010000, + B00100000,B01111000,B00010000, + B00100000,B00110000,B00010000, + B00101111,B00000011,B11010000, + B00101111,B10000111,B11010000, + B00010111,B10000111,B10100000, + B00010011,B10000111,B00100000, + B00001001,B10000110,B01000000, + B00000110,B00000001,B10000000, + B00000001,B11111110,B00000000 + }; + #endif + + #else // !STATUS_ALT_FAN_BITMAP + + const unsigned char status_fan0_bmp[] PROGMEM = { + B00111111,B11111111,B11110000, + B00111000,B00000000,B01110000, + B00110000,B11111100,B00110000, + B00100000,B11111100,B00010000, + B00100000,B01111000,B00010000, + B00100000,B00110000,B00010000, + B00101100,B00000000,B11010000, + B00101110,B00110001,B11010000, + B00101111,B01111011,B11010000, + B00101111,B01111011,B11010000, + B00101110,B00110001,B11010000, + B00101100,B00000000,B11010000, + B00100000,B00110000,B00010000, + B00100000,B01111000,B00010000, + B00100000,B11111100,B00010000, + B00110000,B11111100,B00110000, + B00111000,B00000000,B01110000, + B00111111,B11111111,B11110000 + }; + + #if STATUS_FAN_FRAMES == 2 + const unsigned char status_fan1_bmp[] PROGMEM = { + B00111111,B11111111,B11110000, + B00111000,B00000000,B01110000, + B00110001,B10000110,B00110000, + B00100011,B10000111,B00010000, + B00100111,B10000111,B10010000, + B00101111,B10000111,B11010000, + B00101111,B00000011,B11010000, + B00100000,B00110000,B00010000, + B00100000,B01111000,B00010000, + B00100000,B01111000,B00010000, + B00100000,B00110000,B00010000, + B00101111,B00000011,B11010000, + B00101111,B10000111,B11010000, + B00100111,B10000111,B10010000, + B00100011,B10000111,B00010000, + B00110001,B10000110,B00110000, + B00111000,B00000000,B01110000, + B00111111,B11111111,B11110000 + }; + #endif + + #endif // !STATUS_ALT_FAN_BITMAP + +#elif STATUS_FAN_FRAMES == 3 + + #if ENABLED(STATUS_ALT_FAN_BITMAP) + + const unsigned char status_fan0_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B00000000,B11000000, + B00001001,B00000001,B00100000, + B00010111,B10000011,B11010000, + B00010111,B10000011,B11010000, + B00101111,B11000111,B11101000, + B00100111,B11000111,B11001000, + B00100001,B11111111,B00001000, + B00100000,B01111100,B00001000, + B00100000,B01111100,B00001000, + B00100000,B01111100,B00001000, + B00100001,B11111111,B00001000, + B00100111,B11000111,B11001000, + B00101111,B11000111,B11101000, + B00010111,B10000011,B11010000, + B00010111,B10000011,B11010000, + B00001001,B00000001,B00100000, + B00000110,B00000000,B11000000, + B00000001,B11111111,B00000000 + }; + const unsigned char status_fan1_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B00110000,B11000000, + B00001001,B11110000,B00100000, + B00010001,B11110000,B00010000, + B00010000,B11110000,B00010000, + B00100000,B11110000,B01101000, + B00100000,B00110001,B11101000, + B00100000,B00111001,B11101000, + B00100000,B01111111,B11111000, + B00111111,B11111111,B11111000, + B00111111,B11111100,B00001000, + B00101111,B00111000,B00001000, + B00101110,B00011000,B00001000, + B00101100,B00011110,B00001000, + B00010000,B00011110,B00010000, + B00010000,B00011111,B00010000, + B00001000,B00011111,B00100000, + B00000110,B00011000,B11000000, + B00000001,B11111111,B00000000 + }; + const unsigned char status_fan2_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B00011000,B11000000, + B00001000,B00011111,B00100000, + B00010000,B00011111,B10010000, + B00010100,B00011111,B00010000, + B00101110,B00011110,B00001000, + B00101111,B00011100,B00001000, + B00101111,B10111000,B00001000, + B00111111,B11111100,B00001000, + B00111111,B11111111,B11111000, + B00100000,B01111111,B11111000, + B00100000,B00111011,B11101000, + B00100000,B01110001,B11101000, + B00100000,B11110000,B11101000, + B00010001,B11110000,B01010000, + B00010011,B11110000,B00010000, + B00001001,B11110000,B00100000, + B00000110,B00110000,B11000000, + B00000001,B11111111,B00000000 + }; + + #else // !STATUS_ALT_FAN_BITMAP + + const unsigned char status_fan0_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B00000000,B11111000, + B00111001,B00000001,B00111000, + B00110111,B10000011,B11011000, + B00110111,B10000011,B11011000, + B00101111,B11000111,B11101000, + B00100111,B11000111,B11001000, + B00100001,B11111111,B00001000, + B00100000,B01111100,B00001000, + B00100000,B01111100,B00001000, + B00100000,B01111100,B00001000, + B00100001,B11111111,B00001000, + B00100111,B11000111,B11001000, + B00101111,B11000111,B11101000, + B00110111,B10000011,B11011000, + B00110111,B10000011,B11011000, + B00111001,B00000001,B00111000, + B00111110,B00000000,B11111000, + B00111111,B11111111,B11111000 + }; + const unsigned char status_fan1_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B00110000,B11111000, + B00111001,B11110000,B00111000, + B00110001,B11110000,B00011000, + B00110000,B11110000,B00011000, + B00100000,B11110000,B01101000, + B00100000,B00110001,B11101000, + B00100000,B00111001,B11101000, + B00100000,B01111111,B11111000, + B00111111,B11111111,B11111000, + B00111111,B11111100,B00001000, + B00101111,B00111000,B00001000, + B00101110,B00011000,B00001000, + B00101100,B00011110,B00001000, + B00110000,B00011110,B00011000, + B00110000,B00011111,B00011000, + B00111000,B00011111,B00111000, + B00111110,B00011000,B11111000, + B00111111,B11111111,B11111000 + }; + const unsigned char status_fan2_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B00011000,B11111000, + B00111000,B00011111,B00111000, + B00110000,B00011111,B10011000, + B00110100,B00011111,B00011000, + B00101110,B00011110,B00001000, + B00101111,B00011100,B00001000, + B00101111,B10111000,B00001000, + B00111111,B11111100,B00001000, + B00111111,B11111111,B11111000, + B00100000,B01111111,B11111000, + B00100000,B00111011,B11101000, + B00100000,B01110001,B11101000, + B00100000,B11110000,B11101000, + B00110001,B11110000,B01011000, + B00110011,B11110000,B00011000, + B00111001,B11110000,B00111000, + B00111110,B00110000,B11111000, + B00111111,B11111111,B11111000 + }; + + #endif // !STATUS_ALT_FAN_BITMAP + +#elif STATUS_FAN_FRAMES == 4 + + #if ENABLED(STATUS_ALT_FAN_BITMAP) + + const unsigned char status_fan0_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B00000000,B11000000, + B00001000,B00111111,B00100000, + B00010000,B01111110,B00010000, + B00010000,B01111100,B00010000, + B00101000,B01111100,B00001000, + B00101100,B00111000,B00001000, + B00101111,B00111001,B11001000, + B00101111,B11111111,B11101000, + B00101111,B11000111,B11101000, + B00101111,B11111111,B11101000, + B00100111,B00111001,B11101000, + B00100000,B00111000,B01101000, + B00100000,B01111100,B00101000, + B00010000,B01111100,B00010000, + B00010000,B11111100,B00010000, + B00001001,B11111000,B00100000, + B00000110,B00000000,B11000000, + B00000001,B11111111,B00000000 + }; + const unsigned char status_fan1_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B00000000,B11000000, + B00001000,B00001111,B00100000, + B00010100,B00011111,B11010000, + B00010110,B00011111,B10010000, + B00101111,B00011111,B00001000, + B00101111,B10011110,B00001000, + B00101111,B11111100,B00001000, + B00101111,B11011100,B00001000, + B00100111,B11101111,B11001000, + B00100000,B01110111,B11101000, + B00100000,B01111111,B11101000, + B00100000,B11110011,B11101000, + B00100001,B11110001,B11101000, + B00010011,B11110000,B11010000, + B00010111,B11110000,B01010000, + B00001001,B11100000,B00100000, + B00000110,B00000000,B11000000, + B00000001,B11111111,B00000000 + }; + const unsigned char status_fan2_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B10000000,B11000000, + B00001001,B10000000,B00100000, + B00010111,B10000001,B11010000, + B00010111,B11000011,B11010000, + B00100111,B11000111,B11101000, + B00100011,B11000111,B11111000, + B00100001,B11111111,B10001000, + B00100000,B01101100,B00001000, + B00100000,B01101100,B00001000, + B00100000,B01101100,B00001000, + B00100011,B11111111,B00001000, + B00111111,B11000111,B10001000, + B00101111,B11000111,B11001000, + B00010111,B10000111,B11010000, + B00010111,B00000011,B11010000, + B00001000,B00000011,B00100000, + B00000110,B00000010,B11000000, + B00000001,B11111111,B00000000 + }; + const unsigned char status_fan3_bmp[] PROGMEM = { + B00000001,B11111111,B00000000, + B00000110,B00000000,B11000000, + B00001001,B11110000,B00100000, + B00010001,B11100000,B00010000, + B00010001,B11100000,B00010000, + B00100001,B11100001,B11101000, + B00100000,B11110011,B11101000, + B00100000,B01111111,B11101000, + B00100000,B01110111,B11101000, + B00101000,B11101110,B00101000, + B00101111,B11011100,B00001000, + B00101111,B11111100,B00001000, + B00101111,B10011110,B00001000, + B00101111,B00001111,B00001000, + B00010000,B00001111,B00010000, + B00010000,B00001111,B00010000, + B00001000,B00011111,B00100000, + B00000110,B00000000,B11000000, + B00000001,B11111111,B00000000 + }; + + #else // !STATUS_ALT_FAN_BITMAP + + const unsigned char status_fan0_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B00000000,B11111000, + B00111000,B00111111,B00111000, + B00110000,B01111110,B00011000, + B00110000,B01111100,B00011000, + B00101000,B01111100,B00001000, + B00101100,B00111000,B00001000, + B00101111,B00111001,B11001000, + B00101111,B11111111,B11101000, + B00101111,B11000111,B11101000, + B00101111,B11111111,B11101000, + B00100111,B00111001,B11101000, + B00100000,B00111000,B01101000, + B00100000,B01111100,B00101000, + B00110000,B01111100,B00011000, + B00110000,B11111100,B00011000, + B00111001,B11111000,B00111000, + B00111110,B00000000,B11111000, + B00111111,B11111111,B11111000 + }; + const unsigned char status_fan1_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B00000000,B11111000, + B00111000,B00001111,B00111000, + B00110100,B00011111,B11011000, + B00110110,B00011111,B10011000, + B00101111,B00011111,B00001000, + B00101111,B10011110,B00001000, + B00101111,B11111100,B00001000, + B00101111,B11011100,B00001000, + B00100111,B11101111,B11001000, + B00100000,B01110111,B11101000, + B00100000,B01111111,B11101000, + B00100000,B11110011,B11101000, + B00100001,B11110001,B11101000, + B00110011,B11110000,B11011000, + B00110111,B11110000,B01011000, + B00111001,B11100000,B00111000, + B00111110,B00000000,B11111000, + B00111111,B11111111,B11111000 + }; + const unsigned char status_fan2_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B10000000,B11111000, + B00111001,B10000000,B00111000, + B00110111,B10000001,B11011000, + B00110111,B11000011,B11011000, + B00100111,B11000111,B11101000, + B00100011,B11000111,B11111000, + B00100001,B11111111,B10001000, + B00100000,B01101100,B00001000, + B00100000,B01101100,B00001000, + B00100000,B01101100,B00001000, + B00100011,B11111111,B00001000, + B00111111,B11000111,B10001000, + B00101111,B11000111,B11001000, + B00110111,B10000111,B11011000, + B00110111,B00000011,B11011000, + B00111000,B00000011,B00111000, + B00111110,B00000010,B11111000, + B00111111,B11111111,B11111000 + }; + const unsigned char status_fan3_bmp[] PROGMEM = { + B00111111,B11111111,B11111000, + B00111110,B00000000,B11111000, + B00111001,B11110000,B00111000, + B00110001,B11100000,B00011000, + B00110001,B11100000,B00011000, + B00100001,B11100001,B11101000, + B00100000,B11110011,B11101000, + B00100000,B01111111,B11101000, + B00100000,B01110111,B11101000, + B00101000,B11101110,B00101000, + B00101111,B11011100,B00001000, + B00101111,B11111100,B00001000, + B00101111,B10011110,B00001000, + B00101111,B00001111,B00001000, + B00110000,B00001111,B00011000, + B00110000,B00001111,B00011000, + B00111000,B00011111,B00111000, + B00111110,B00000000,B11111000, + B00111111,B11111111,B11111000 + }; + + #endif // !STATUS_ALT_FAN_BITMAP + +#endif diff --git a/src/lcd/dogm/status/hotend.h b/src/lcd/dogm/status/hotend.h new file mode 100644 index 0000000..aac29da --- /dev/null +++ b/src/lcd/dogm/status/hotend.h @@ -0,0 +1,759 @@ +/** + * 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/dogm/status/hotend.h - Status Screen Hotends bitmaps +// + +#if HAS_MMU + #define STATUS_HOTEND_BITMAPS EXTRUDERS + #define MAX_HOTEND_BITMAPS 8 +#else + #define STATUS_HOTEND_BITMAPS HOTENDS + #define MAX_HOTEND_BITMAPS 5 +#endif +#if STATUS_HOTEND_BITMAPS > MAX_HOTEND_BITMAPS + #undef STATUS_HOTEND_BITMAPS + #define STATUS_HOTEND_BITMAPS MAX_HOTEND_BITMAPS +#endif + +#define STATUS_HOTEND1_WIDTH 16 + +#if STATUS_HOTEND_BITMAPS == 1 || defined(STATUS_HOTEND_NUMBERLESS) + + const unsigned char status_hotend_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if defined(STATUS_HOTEND_INVERTED) && !defined(STATUS_HOTEND_ANIM) + B00100000,B00010000, + B00100000,B00010000, + B00100000,B00010000, + B00010000,B00100000, + B00010000,B00100000, + B00100000,B00010000, + B00100000,B00010000, + B00110000,B00110000, + B00001000,B01000000, + B00000100,B10000000, + #else + B00111111,B11110000, + B00111111,B11110000, + B00111111,B11110000, + B00011111,B11100000, + B00011111,B11100000, + B00111111,B11110000, + B00111111,B11110000, + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + #endif + B00000011,B00000000 + }; + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + B00100000,B00010000, + B00100000,B00010000, + B00010000,B00100000, + B00010000,B00100000, + B00100000,B00010000, + B00100000,B00010000, + B00110000,B00110000, + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #endif + +#elif STATUS_HOTEND_BITMAPS > 1 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend1_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000, + B00111011,B01110000, + B00111011,B01110000, + B00011011,B01100000, + B00011011,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111110,B11110000, + B00111100,B11110000, + B00011010,B11100000, + B00011110,B11100000, + B00111110,B11110000, + B00111110,B11110000, + B00111110,B11110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend1_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100011,B00010000, + B00100100,B10010000, + B00010100,B10100000, + B00010100,B10100000, + B00100100,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #else + B00100001,B00010000, + B00100011,B00010000, + B00010101,B00100000, + B00010001,B00100000, + B00100001,B00010000, + B00100001,B00010000, + B00110001,B00110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend2_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111110,B11110000, + B00111100,B11110000, + B00011010,B11100000, + B00011110,B11100000, + B00111110,B11110000, + B00111110,B11110000, + B00111110,B11110000, + #else + B00111100,B11110000, + B00111011,B01110000, + B00011111,B01100000, + B00011110,B11100000, + B00111101,B11110000, + B00111011,B11110000, + B00111000,B01110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend2_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100001,B00010000, + B00100011,B00010000, + B00010101,B00100000, + B00010001,B00100000, + B00100001,B00010000, + B00100001,B00010000, + B00110001,B00110000, + #else + B00100011,B00010000, + B00100100,B10010000, + B00010000,B10100000, + B00010001,B00100000, + B00100010,B00010000, + B00100100,B00010000, + B00110111,B10110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend1_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000, + B00111011,B01110000, + B00111011,B01110000, + B00011011,B01100000, + B00011011,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111110,B11110000, + B00111100,B11110000, + B00111010,B11110000, + B00011110,B11100000, + B00011110,B11100000, + B00111110,B11110000, + B00111110,B11110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend2_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111110,B11110000, + B00111100,B11110000, + B00111010,B11110000, + B00011110,B11100000, + B00011110,B11100000, + B00111110,B11110000, + B00111110,B11110000, + #else + B00111100,B11110000, + B00111011,B01110000, + B00111111,B01110000, + B00011110,B11100000, + B00011101,B11100000, + B00111011,B11110000, + B00111000,B01110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #if STATUS_HOTEND_BITMAPS >= 3 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend3_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000, + B00111011,B01110000, + B00011111,B01100000, + B00011110,B11100000, + B00111101,B11110000, + B00111011,B11110000, + B00111000,B01110000, + #else + B00111100,B11110000, + B00111011,B01110000, + B00011111,B01100000, + B00011100,B11100000, + B00111111,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend3_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100011,B00010000, + B00100100,B10010000, + B00010000,B10100000, + B00010001,B00100000, + B00100010,B00010000, + B00100100,B00010000, + B00110111,B10110000, + #else + B00100011,B00010000, + B00100100,B10010000, + B00010000,B10100000, + B00010011,B00100000, + B00100000,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend3_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000, + B00111011,B01110000, + B00111111,B01110000, + B00011110,B11100000, + B00011101,B11100000, + B00111011,B11110000, + B00111000,B01110000, + #else + B00111100,B11110000, + B00111011,B01110000, + B00111111,B01110000, + B00011100,B11100000, + B00011111,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #endif + + #if STATUS_HOTEND_BITMAPS >= 4 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend4_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000, + B00111011,B01110000, + B00011111,B01100000, + B00011100,B11100000, + B00111111,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111011,B01110000, + B00111011,B01110000, + B00011011,B01100000, + B00011011,B01100000, + B00111000,B00110000, + B00111111,B01110000, + B00111111,B01110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend4_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100011,B00010000, + B00100100,B10010000, + B00010000,B10100000, + B00010011,B00100000, + B00100000,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #else + B00100100,B10010000, + B00100100,B10010000, + B00010100,B10100000, + B00010100,B10100000, + B00100111,B11010000, + B00100000,B10010000, + B00110000,B10110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend4_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B11110000, + B00111011,B01110000, + B00111111,B01110000, + B00011100,B11100000, + B00011111,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111011,B01110000, + B00111011,B01110000, + B00111011,B01110000, + B00011011,B01100000, + B00011000,B00100000, + B00111111,B01110000, + B00111111,B01110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #endif + + #if STATUS_HOTEND_BITMAPS >= 5 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend5_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111011,B01110000, + B00111011,B01110000, + B00011011,B01100000, + B00011011,B01100000, + B00111000,B00110000, + B00111111,B01110000, + B00111111,B01110000, + #else + B00111000,B01110000, + B00111011,B11110000, + B00011000,B11100000, + B00011111,B01100000, + B00111111,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend5_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100100,B10010000, + B00100100,B10010000, + B00010100,B10100000, + B00010100,B10100000, + B00100111,B11010000, + B00100000,B10010000, + B00110000,B10110000, + #else + B00100111,B10010000, + B00100100,B00010000, + B00010111,B00100000, + B00010000,B10100000, + B00100000,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend5_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111011,B01110000, + B00111011,B01110000, + B00111011,B01110000, + B00011011,B01100000, + B00011000,B00100000, + B00111111,B01110000, + B00111111,B01110000, + #else + B00111000,B01110000, + B00111011,B11110000, + B00111000,B11110000, + B00011111,B01100000, + B00011111,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #endif + + #if STATUS_HOTEND_BITMAPS >= 6 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend6_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111000,B01110000, + B00111011,B11110000, + B00011000,B11100000, + B00011111,B01100000, + B00111111,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111100,B01110000, + B00111011,B11110000, + B00011011,B11100000, + B00011000,B11100000, + B00111011,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend6_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100111,B10010000, + B00100100,B00010000, + B00010111,B00100000, + B00010000,B10100000, + B00100000,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #else + B00100011,B10010000, + B00100100,B00010000, + B00010100,B00100000, + B00010111,B00100000, + B00100100,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend6_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111000,B01110000, + B00111011,B11110000, + B00111000,B11110000, + B00011111,B01100000, + B00011111,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111100,B01110000, + B00111011,B11110000, + B00111011,B11110000, + B00011000,B11100000, + B00011011,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #endif + + #if STATUS_HOTEND_BITMAPS >= 7 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend7_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111100,B01110000, + B00111011,B11110000, + B00011011,B11100000, + B00011000,B11100000, + B00111011,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111000,B01110000, + B00111011,B01110000, + B00011111,B01100000, + B00011110,B11100000, + B00111110,B11110000, + B00111101,B11110000, + B00111101,B11110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend7_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100011,B10010000, + B00100100,B00010000, + B00010100,B00100000, + B00010111,B00100000, + B00100100,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #else + B00100111,B10010000, + B00100100,B10010000, + B00010000,B10100000, + B00010001,B00100000, + B00100001,B00010000, + B00100010,B00010000, + B00110010,B00110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend7_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111100,B01110000, + B00111011,B11110000, + B00111011,B11110000, + B00011000,B11100000, + B00011011,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #else + B00111000,B01110000, + B00111011,B01110000, + B00111111,B01110000, + B00011110,B11100000, + B00011110,B11100000, + B00111101,B11110000, + B00111101,B11110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #endif + + #if STATUS_HOTEND_BITMAPS >= 8 + + #ifdef STATUS_HOTEND_ANIM + + const unsigned char status_hotend8_a_bmp[] PROGMEM = { + B00011111,B11100000, + B00111111,B11110000, + #if LCD_FIRST_TOOL == 0 + B00111000,B01110000, + B00111011,B01110000, + B00011111,B01100000, + B00011110,B11100000, + B00111110,B11110000, + B00111101,B11110000, + B00111101,B11110000, + #else + B00111100,B11110000, + B00111011,B01110000, + B00011011,B01100000, + B00011100,B11100000, + B00111011,B01110000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + const unsigned char status_hotend8_b_bmp[] PROGMEM = { + B00011111,B11100000, + B00100000,B00010000, + #if LCD_FIRST_TOOL == 0 + B00100111,B10010000, + B00100100,B10010000, + B00010000,B10100000, + B00010001,B00100000, + B00100001,B00010000, + B00100010,B00010000, + B00110010,B00110000, + #else + B00100011,B00010000, + B00100100,B10010000, + B00010100,B10100000, + B00010011,B00100000, + B00100100,B10010000, + B00100100,B10010000, + B00110011,B00110000, + #endif + B00001000,B01000000, + B00000100,B10000000, + B00000011,B00000000 + }; + + #else + + const unsigned char status_hotend8_a_bmp[] PROGMEM = { + B00011111,B11100000, + #if LCD_FIRST_TOOL == 0 + B00111000,B01110000, + B00111011,B01110000, + B00111111,B01110000, + B00011110,B11100000, + B00011110,B11100000, + B00111101,B11110000, + B00111101,B11110000, + #else + B00111100,B11110000, + B00111011,B01110000, + B00111011,B01110000, + B00011100,B11100000, + B00011011,B01100000, + B00111011,B01110000, + B00111100,B11110000, + #endif + B00111111,B11110000, + B00001111,B11000000, + B00000111,B10000000, + B00000011,B00000000 + }; + + #endif + + #endif + +#endif diff --git a/src/lcd/dogm/status_screen_DOGM.cpp b/src/lcd/dogm/status_screen_DOGM.cpp new file mode 100644 index 0000000..67039d5 --- /dev/null +++ b/src/lcd/dogm/status_screen_DOGM.cpp @@ -0,0 +1,1031 @@ +/** + * 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 . + * + */ + +// +// status_screen_DOGM.cpp +// Standard Status Screen for Graphical Display +// + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB && DISABLED(LIGHTWEIGHT_UI) + +#include "dogm_Statusscreen.h" +#include "marlinui_DOGM.h" +#include "../marlinui.h" +#include "../lcdprint.h" +#include "../../libs/numtostr.h" + +#include "../../module/motion.h" +#include "../../module/temperature.h" + +#include "../../gcode/parser.h" // for units (and volumetric) + +#if ENABLED(LCD_SHOW_E_TOTAL) + #include "../../MarlinCore.h" // for printingIsActive() +#endif + +#if ENABLED(FILAMENT_LCD_DISPLAY) + #include "../../feature/filwidth.h" + #include "../../module/planner.h" +#endif + +#if HAS_LEVELING + #include "../../module/planner.h" +#endif + +#if HAS_CUTTER + #include "../../feature/spindle_laser.h" +#endif + +#if EITHER(HAS_COOLER, LASER_COOLANT_FLOW_METER) + #include "../../feature/cooler.h" +#endif + +#if DO_DRAW_AMMETER + #include "../../feature/ammeter.h" +#endif + +#if HAS_POWER_MONITOR + #include "../../feature/power_monitor.h" +#endif + +#if ENABLED(SDSUPPORT) + #include "../../sd/cardreader.h" +#endif + +#if HAS_PRINT_PROGRESS + #include "../../module/printcounter.h" +#endif + +#if HAS_DUAL_MIXING + #include "../../feature/mixing.h" +#endif + +#define X_LABEL_POS 3 +#define X_VALUE_POS 11 +#define XYZ_SPACING 37 + +#define X_LABEL_POS_IN (X_LABEL_POS - 2) +#define X_VALUE_POS_IN (X_VALUE_POS - 5) +#define XYZ_SPACING_IN (XYZ_SPACING + 9) + +#define XYZ_BASELINE (30 + INFO_FONT_ASCENT) +#define EXTRAS_BASELINE (40 + INFO_FONT_ASCENT) +#define STATUS_BASELINE (LCD_PIXEL_HEIGHT - INFO_FONT_DESCENT) + +#if ANIM_HBCC + enum HeatBits : uint8_t { + DRAWBIT_HOTEND, + DRAWBIT_BED = HOTENDS, + DRAWBIT_CHAMBER, + DRAWBIT_CUTTER + }; + IF<(DRAWBIT_CUTTER > 7), uint16_t, uint8_t>::type draw_bits; +#endif + +#if ANIM_HOTEND + #define HOTEND_ALT(N) TEST(draw_bits, DRAWBIT_HOTEND + N) +#else + #define HOTEND_ALT(N) false +#endif +#if ANIM_BED + #define BED_ALT() TEST(draw_bits, DRAWBIT_BED) +#else + #define BED_ALT() false +#endif +#if ANIM_CHAMBER + #define CHAMBER_ALT() TEST(draw_bits, DRAWBIT_CHAMBER) +#else + #define CHAMBER_ALT() false +#endif +#if ANIM_CUTTER + #define CUTTER_ALT(N) TEST(draw_bits, DRAWBIT_CUTTER) +#else + #define CUTTER_ALT() false +#endif + +#if DO_DRAW_HOTENDS + #define MAX_HOTEND_DRAW _MIN(HOTENDS, ((LCD_PIXEL_WIDTH - (STATUS_LOGO_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) / (STATUS_HEATERS_XSPACE))) +#endif + +#if EITHER(DO_DRAW_BED, DO_DRAW_HOTENDS) + #define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1) +#endif + +#if HAS_POWER_MONITOR + + void display_power_monitor(const uint8_t x, const uint8_t y) { + + lcd_moveto(x, y); + + #if HAS_POWER_MONITOR_WATTS + const bool wflag = power_monitor.power_display_enabled(); + #endif + #if ENABLED(POWER_MONITOR_CURRENT) + const bool iflag = power_monitor.current_display_enabled(); + #endif + #if ENABLED(POWER_MONITOR_VOLTAGE) + const bool vflag = power_monitor.voltage_display_enabled(); + #endif + + #if HAS_POWER_MONITOR_WATTS + // Cycle between current, voltage, and power + if (ELAPSED(millis(), power_monitor.display_item_ms)) { + power_monitor.display_item_ms = millis() + 1000UL; + ++power_monitor.display_item; + } + #elif ENABLED(POWER_MONITOR_CURRENT) + power_monitor.display_item = 0; + #elif ENABLED(POWER_MONITOR_VOLTAGE) + power_monitor.display_item = 1; + #endif + + // ensure we have the right one selected for display + for (uint8_t i = 0; i < 3; i++) { + #if ENABLED(POWER_MONITOR_CURRENT) + if (power_monitor.display_item == 0 && !iflag) ++power_monitor.display_item; + #endif + #if ENABLED(POWER_MONITOR_VOLTAGE) + if (power_monitor.display_item == 1 && !vflag) ++power_monitor.display_item; + #endif + #if HAS_POWER_MONITOR_WATTS + if (power_monitor.display_item == 2 && !wflag) ++power_monitor.display_item; + #endif + if (power_monitor.display_item >= 3) power_monitor.display_item = 0; + } + + switch (power_monitor.display_item) { + #if ENABLED(POWER_MONITOR_CURRENT) // Current + case 0: if (iflag) power_monitor.draw_current(); break; + #endif + #if ENABLED(POWER_MONITOR_VOLTAGE) // Voltage + case 1: if (vflag) power_monitor.draw_voltage(); break; + #endif + #if HAS_POWER_MONITOR_WATTS // Power + case 2: if (wflag) power_monitor.draw_power(); break; + #endif + default: break; + } + } +#endif + +#define PROGRESS_BAR_X 54 +#define PROGRESS_BAR_Y (EXTRAS_BASELINE + 1) +#define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X) + +FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, const uint8_t ty) { + if (temp < 0) + lcd_put_u8str(tx - 3 * (INFO_FONT_WIDTH) / 2 + 1, ty, F("err")); + else { + const char *str = i16tostr3rj(temp); + const uint8_t len = str[0] != ' ' ? 3 : str[1] != ' ' ? 2 : 1; + lcd_put_u8str(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty, &str[3-len]); + lcd_put_lchar(LCD_STR_DEGREE[0]); + } +} + +#if DO_DRAW_FLOWMETER + FORCE_INLINE void _draw_centered_flowrate(const float flow, const uint8_t tx, const uint8_t ty) { + const char *str = ftostr11ns(flow); + const uint8_t len = str[0] != ' ' ? 3 : str[1] != ' ' ? 2 : 1; + lcd_put_u8str(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty, &str[3-len]); + lcd_put_u8str("L"); + } +#endif + +#if DO_DRAW_AMMETER + FORCE_INLINE void _draw_centered_current(const float current, const uint8_t tx, const uint8_t ty) { + const char *str = ftostr31ns(current); + const uint8_t len = str[0] != ' ' ? 3 : str[1] != ' ' ? 2 : 1; + lcd_put_u8str(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty, &str[3-len]); + } +#endif + +#if DO_DRAW_HOTENDS + + // Draw hotend bitmap with current and target temperatures + FORCE_INLINE void _draw_hotend_status(const heater_id_t heater_id, const bool blink) { + #if !HEATER_IDLE_HANDLER + UNUSED(blink); + #endif + + const bool isHeat = HOTEND_ALT(heater_id); + + const uint8_t tx = STATUS_HOTEND_TEXT_X(heater_id); + + const celsius_t temp = thermalManager.wholeDegHotend(heater_id), + target = thermalManager.degTargetHotend(heater_id); + + #if DISABLED(STATUS_HOTEND_ANIM) + #define STATIC_HOTEND true + #define HOTEND_DOT isHeat + #else + #define STATIC_HOTEND false + #define HOTEND_DOT false + #endif + + #if ENABLED(STATUS_HOTEND_NUMBERLESS) + #define OFF_BMP(N) TERN(STATUS_HOTEND_INVERTED, status_hotend_b_bmp, status_hotend_a_bmp) + #define ON_BMP(N) TERN(STATUS_HOTEND_INVERTED, status_hotend_a_bmp, status_hotend_b_bmp) + #else + #define OFF_BMP(N) TERN(STATUS_HOTEND_INVERTED, status_hotend##N##_b_bmp, status_hotend##N##_a_bmp) + #define ON_BMP(N) TERN(STATUS_HOTEND_INVERTED, status_hotend##N##_a_bmp, status_hotend##N##_b_bmp) + #endif + + #if STATUS_HOTEND_BITMAPS > 1 + #define _OFF_BMP(N) OFF_BMP(N), + #define _ON_BMP(N) ON_BMP(N), + static const unsigned char* const status_hotend_gfx[STATUS_HOTEND_BITMAPS] PROGMEM = { REPEAT_1(STATUS_HOTEND_BITMAPS, _OFF_BMP) }; + #if ANIM_HOTEND + static const unsigned char* const status_hotend_on_gfx[STATUS_HOTEND_BITMAPS] PROGMEM = { REPEAT_1(STATUS_HOTEND_BITMAPS, _ON_BMP) }; + #define HOTEND_BITMAP(N,S) (unsigned char*)pgm_read_ptr((S) ? &status_hotend_on_gfx[(N) % (STATUS_HOTEND_BITMAPS)] : &status_hotend_gfx[(N) % (STATUS_HOTEND_BITMAPS)]) + #else + #define HOTEND_BITMAP(N,S) (unsigned char*)pgm_read_ptr(&status_hotend_gfx[(N) % (STATUS_HOTEND_BITMAPS)]) + #endif + #elif ANIM_HOTEND + #define HOTEND_BITMAP(N,S) ((S) ? ON_BMP() : OFF_BMP()) + #else + #define HOTEND_BITMAP(N,S) status_hotend_a_bmp + #endif + + #if DISABLED(STATUS_COMBINE_HEATERS) + + if (PAGE_CONTAINS(STATUS_HEATERS_Y, STATUS_HEATERS_BOT)) { + + #define BAR_TALL (STATUS_HEATERS_HEIGHT - 2) + + const float prop = target - 20, + perc = prop > 0 && temp >= 20 ? (temp - 20) / prop : 0; + uint8_t tall = uint8_t(perc * BAR_TALL + 0.5f); + NOMORE(tall, BAR_TALL); + + // Draw hotend bitmap, either whole or split by the heating percent + const uint8_t hx = STATUS_HOTEND_X(heater_id), + bw = STATUS_HOTEND_BYTEWIDTH(heater_id); + #if ENABLED(STATUS_HEAT_PERCENT) + if (isHeat && tall <= BAR_TALL) { + const uint8_t ph = STATUS_HEATERS_HEIGHT - 1 - tall; + u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, ph, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), false)); + u8g.drawBitmapP(hx, STATUS_HEATERS_Y + ph, bw, tall + 1, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), true) + ph * bw); + } + else + #endif + u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, STATUS_HEATERS_HEIGHT, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), isHeat)); + + } // PAGE_CONTAINS + + #endif // !STATUS_COMBINE_HEATERS + + if (PAGE_UNDER(7)) { + #if HEATER_IDLE_HANDLER + const bool dodraw = (blink || !thermalManager.heater_idle[heater_id].timed_out); + #else + constexpr bool dodraw = true; + #endif + if (dodraw) _draw_centered_temp(target, tx, 7); + } + + if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1)) + _draw_centered_temp(temp, tx, 28); + + if (STATIC_HOTEND && HOTEND_DOT && PAGE_CONTAINS(17, 19)) { + u8g.setColorIndex(0); // set to white on black + u8g.drawBox(tx, 20 - 3, 2, 2); + u8g.setColorIndex(1); // restore black on white + } + + } + +#endif // DO_DRAW_HOTENDS + +#if DO_DRAW_BED + + // Draw bed bitmap with current and target temperatures + FORCE_INLINE void _draw_bed_status(const bool blink) { + #if !HEATER_IDLE_HANDLER + UNUSED(blink); + #endif + + const uint8_t tx = STATUS_BED_TEXT_X; + + const celsius_t temp = thermalManager.wholeDegBed(), + target = thermalManager.degTargetBed(); + + #if ENABLED(STATUS_HEAT_PERCENT) || DISABLED(STATUS_BED_ANIM) + const bool isHeat = BED_ALT(); + #endif + + #if DISABLED(STATUS_BED_ANIM) + #define STATIC_BED true + #define BED_DOT isHeat + #else + #define STATIC_BED false + #define BED_DOT false + #endif + + if (PAGE_CONTAINS(STATUS_HEATERS_Y, STATUS_HEATERS_BOT)) { + + #define BAR_TALL (STATUS_HEATERS_HEIGHT - 2) + + const float prop = target - 20, + perc = prop > 0 && temp >= 20 ? (temp - 20) / prop : 0; + uint8_t tall = uint8_t(perc * BAR_TALL + 0.5f); + NOMORE(tall, BAR_TALL); + + // Draw a heating progress bar, if specified + #if ENABLED(STATUS_HEAT_PERCENT) + + if (isHeat) { + const uint8_t bx = STATUS_BED_X + STATUS_BED_WIDTH; + u8g.drawFrame(bx, STATUS_HEATERS_Y, 3, STATUS_HEATERS_HEIGHT); + if (tall) { + const uint8_t ph = STATUS_HEATERS_HEIGHT - 1 - tall; + if (PAGE_OVER(STATUS_HEATERS_Y + ph)) + u8g.drawVLine(bx + 1, STATUS_HEATERS_Y + ph, tall); + } + } + + #endif + + } // PAGE_CONTAINS + + if (PAGE_UNDER(7)) { + #if HEATER_IDLE_HANDLER + const bool dodraw = (blink || !thermalManager.heater_idle[thermalManager.IDLE_INDEX_BED].timed_out); + #else + constexpr bool dodraw = true; + #endif + if (dodraw) _draw_centered_temp(target, tx, 7); + } + + if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1)) + _draw_centered_temp(temp, tx, 28); + + if (STATIC_BED && BED_DOT && PAGE_CONTAINS(17, 19)) { + u8g.setColorIndex(0); // set to white on black + u8g.drawBox(tx, 20 - 2, 2, 2); + u8g.setColorIndex(1); // restore black on white + } + + } + +#endif // DO_DRAW_BED + +#if DO_DRAW_CHAMBER + FORCE_INLINE void _draw_chamber_status() { + #if HAS_HEATED_CHAMBER + if (PAGE_UNDER(7)) + _draw_centered_temp(thermalManager.degTargetChamber(), STATUS_CHAMBER_TEXT_X, 7); + #endif + if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1)) + _draw_centered_temp(thermalManager.wholeDegChamber(), STATUS_CHAMBER_TEXT_X, 28); + } +#endif + +#if DO_DRAW_COOLER + FORCE_INLINE void _draw_cooler_status() { + if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1)) + _draw_centered_temp(thermalManager.wholeDegCooler(), STATUS_COOLER_TEXT_X, 28); + } +#endif + +#if DO_DRAW_FLOWMETER + FORCE_INLINE void _draw_flowmeter_status() { + if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1)) + _draw_centered_flowrate(cooler.flowrate, STATUS_FLOWMETER_TEXT_X, 28); + } +#endif + +#if DO_DRAW_AMMETER + FORCE_INLINE void _draw_ammeter_status() { + if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1)) + _draw_centered_current(ammeter.read(), STATUS_AMMETER_TEXT_X, 28); + } +#endif + +// +// Before homing, blink '123' <-> '???'. +// Homed but unknown... '123' <-> ' '. +// Homed and known, display constantly. +// +FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) { + const bool is_inch = parser.using_inch_units(); + const AxisEnum a = TERN(LCD_SHOW_E_TOTAL, axis == E_AXIS ? X_AXIS : axis, axis); + const uint8_t offs = a * (is_inch ? XYZ_SPACING_IN : XYZ_SPACING); + lcd_put_lchar((is_inch ? X_LABEL_POS_IN : X_LABEL_POS) + offs, XYZ_BASELINE, AXIS_CHAR(axis)); + lcd_moveto((is_inch ? X_VALUE_POS_IN : X_VALUE_POS) + offs, XYZ_BASELINE); + + if (blink) + lcd_put_u8str(value); + else if (axis_should_home(axis)) + while (const char c = *value++) lcd_put_lchar(c <= '.' ? c : '?'); + else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !axis_is_trusted(axis)) + lcd_put_u8str(axis == Z_AXIS ? F(" ") : F(" ")); + else + lcd_put_u8str(value); +} + +/** + * Draw the Status Screen for a 128x64 DOGM (U8glib) display. + * + * Called as needed to update the current display stripe. + * Use the PAGE_CONTAINS macros to avoid pointless draw calls. + */ +void MarlinUI::draw_status_screen() { + constexpr int xystorage = TERN(INCH_MODE_SUPPORT, 8, 5); + static char xstring[TERN(LCD_SHOW_E_TOTAL, 12, xystorage)], ystring[xystorage], zstring[8]; + + #if ENABLED(FILAMENT_LCD_DISPLAY) + static char wstring[5], mstring[4]; + #endif + + #if HAS_PRINT_PROGRESS + #if DISABLED(SHOW_SD_PERCENT) + #define _SD_INFO_X(len) (PROGRESS_BAR_X + (PROGRESS_BAR_WIDTH) / 2 - (len) * (MENU_FONT_WIDTH) / 2) + #else + #define _SD_INFO_X(len) (LCD_PIXEL_WIDTH - (len) * (MENU_FONT_WIDTH)) + #endif + + #if ENABLED(SHOW_SD_PERCENT) + static char progress_string[5]; + #endif + static uint8_t lastElapsed = 0xFF, lastProgress = 0xFF; + static u8g_uint_t elapsed_x_pos = 0, progress_bar_solid_width = 0; + static char elapsed_string[16]; + #if ENABLED(SHOW_REMAINING_TIME) + static u8g_uint_t estimation_x_pos = 0; + static char estimation_string[10]; + #if BOTH(SHOW_SD_PERCENT, ROTATE_PROGRESS_DISPLAY) + static u8g_uint_t progress_x_pos = 0; + static uint8_t progress_state = 0; + static bool prev_blink = 0; + #endif + #endif + #endif + + const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive()); + + // At the first page, generate new display values + if (first_page) { + #if ANIM_HBCC + uint8_t new_bits = 0; + #if ANIM_HOTEND + HOTEND_LOOP() if (thermalManager.isHeatingHotend(e)) SBI(new_bits, DRAWBIT_HOTEND + e); + #endif + if (TERN0(ANIM_BED, thermalManager.isHeatingBed())) SBI(new_bits, DRAWBIT_BED); + #if DO_DRAW_CHAMBER && HAS_HEATED_CHAMBER + if (thermalManager.isHeatingChamber()) SBI(new_bits, DRAWBIT_CHAMBER); + #endif + if (TERN0(ANIM_CUTTER, cutter.enabled())) SBI(new_bits, DRAWBIT_CUTTER); + draw_bits = new_bits; + #endif + + const xyz_pos_t lpos = current_position.asLogical(); + const bool is_inch = parser.using_inch_units(); + strcpy(zstring, is_inch ? ftostr42_52(LINEAR_UNIT(lpos.z)) : ftostr52sp(lpos.z)); + + if (show_e_total) { + #if ENABLED(LCD_SHOW_E_TOTAL) + const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm + sprintf_P(xstring, PSTR("%ld%cm"), uint32_t(_MAX(e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm + #endif + } + else { + strcpy(xstring, is_inch ? ftostr53_63(LINEAR_UNIT(lpos.x)) : ftostr4sign(lpos.x)); + strcpy(ystring, is_inch ? ftostr53_63(LINEAR_UNIT(lpos.y)) : ftostr4sign(lpos.y)); + } + + #if ENABLED(FILAMENT_LCD_DISPLAY) + strcpy(wstring, ftostr12ns(filwidth.measured_mm)); + strcpy(mstring, i16tostr3rj(planner.volumetric_percent(parser.volumetric_enabled))); + #endif + + // Progress / elapsed / estimation updates and string formatting to avoid float math on each LCD draw + #if HAS_PRINT_PROGRESS + const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)(); + duration_t elapsed = print_job_timer.duration(); + const uint8_t p = progress & 0xFF, ev = elapsed.value & 0xFF; + if (p != lastProgress) { + lastProgress = p; + + progress_bar_solid_width = u8g_uint_t((PROGRESS_BAR_WIDTH - 2) * (progress / (PROGRESS_SCALE)) * 0.01f); + + #if ENABLED(SHOW_SD_PERCENT) + if (progress == 0) { + progress_string[0] = '\0'; + #if ENABLED(SHOW_REMAINING_TIME) + estimation_string[0] = '\0'; + estimation_x_pos = _SD_INFO_X(0); + #endif + } + else + strcpy(progress_string, TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE)))); + + #if BOTH(SHOW_REMAINING_TIME, ROTATE_PROGRESS_DISPLAY) // Tri-state progress display mode + progress_x_pos = _SD_INFO_X(strlen(progress_string) + 1); + #endif + #endif + } + + constexpr bool can_show_days = DISABLED(SHOW_SD_PERCENT) || ENABLED(ROTATE_PROGRESS_DISPLAY); + if (ev != lastElapsed) { + lastElapsed = ev; + const uint8_t len = elapsed.toDigital(elapsed_string, can_show_days && elapsed.value >= 60*60*24L); + elapsed_x_pos = _SD_INFO_X(len); + + #if ENABLED(SHOW_REMAINING_TIME) + if (!(ev & 0x3)) { + uint32_t timeval = (0 + #if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME) + + get_remaining_time() + #endif + ); + if (!timeval && progress > 0) timeval = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress; + if (!timeval) { + estimation_string[0] = '\0'; + estimation_x_pos = _SD_INFO_X(0); + } + else { + duration_t estimation = timeval; + const uint8_t len = estimation.toDigital(estimation_string, can_show_days && estimation.value >= 60*60*24L); + estimation_x_pos = _SD_INFO_X(len + !BOTH(SHOW_SD_PERCENT, ROTATE_PROGRESS_DISPLAY)); + } + } + #endif + } + #endif + } + + const bool blink = get_blink(); + + // Status Menu Font + set_font(FONT_STATUSMENU); + + #if DO_DRAW_LOGO + if (PAGE_CONTAINS(STATUS_LOGO_Y, STATUS_LOGO_Y + STATUS_LOGO_HEIGHT - 1)) + u8g.drawBitmapP(STATUS_LOGO_X, STATUS_LOGO_Y, STATUS_LOGO_BYTEWIDTH, STATUS_LOGO_HEIGHT, status_logo_bmp); + #endif + + #if STATUS_HEATERS_WIDTH + // Draw all heaters (and maybe the bed) in one go + if (PAGE_CONTAINS(STATUS_HEATERS_Y, STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1)) + u8g.drawBitmapP(STATUS_HEATERS_X, STATUS_HEATERS_Y, STATUS_HEATERS_BYTEWIDTH, STATUS_HEATERS_HEIGHT, status_heaters_bmp); + #endif + + #if DO_DRAW_CUTTER && DISABLED(STATUS_COMBINE_HEATERS) + #if ANIM_CUTTER + #define CUTTER_BITMAP(S) ((S) ? status_cutter_on_bmp : status_cutter_bmp) + #else + #define CUTTER_BITMAP(S) status_cutter_bmp + #endif + const uint8_t cuttery = STATUS_CUTTER_Y(CUTTER_ALT()), + cutterh = STATUS_CUTTER_HEIGHT(CUTTER_ALT()); + if (PAGE_CONTAINS(cuttery, cuttery + cutterh - 1)) + u8g.drawBitmapP(STATUS_CUTTER_X, cuttery, STATUS_CUTTER_BYTEWIDTH, cutterh, CUTTER_BITMAP(CUTTER_ALT())); + #endif + + #if DO_DRAW_BED && DISABLED(STATUS_COMBINE_HEATERS) + #if ANIM_BED + #if BOTH(HAS_LEVELING, STATUS_ALT_BED_BITMAP) + #define BED_BITMAP(S) ((S) \ + ? (planner.leveling_active ? status_bed_leveled_on_bmp : status_bed_on_bmp) \ + : (planner.leveling_active ? status_bed_leveled_bmp : status_bed_bmp)) + #else + #define BED_BITMAP(S) ((S) ? status_bed_on_bmp : status_bed_bmp) + #endif + #else + #define BED_BITMAP(S) status_bed_bmp + #endif + const uint8_t bedy = STATUS_BED_Y(BED_ALT()), + bedh = STATUS_BED_HEIGHT(BED_ALT()); + if (PAGE_CONTAINS(bedy, bedy + bedh - 1)) + u8g.drawBitmapP(STATUS_BED_X, bedy, STATUS_BED_BYTEWIDTH, bedh, BED_BITMAP(BED_ALT())); + #endif + + #if DO_DRAW_CHAMBER && DISABLED(STATUS_COMBINE_HEATERS) + #if ANIM_CHAMBER + #define CHAMBER_BITMAP(S) ((S) ? status_chamber_on_bmp : status_chamber_bmp) + #else + #define CHAMBER_BITMAP(S) status_chamber_bmp + #endif + const uint8_t chambery = STATUS_CHAMBER_Y(CHAMBER_ALT()), + chamberh = STATUS_CHAMBER_HEIGHT(CHAMBER_ALT()); + if (PAGE_CONTAINS(chambery, chambery + chamberh - 1)) + u8g.drawBitmapP(STATUS_CHAMBER_X, chambery, STATUS_CHAMBER_BYTEWIDTH, chamberh, CHAMBER_BITMAP(CHAMBER_ALT())); + #endif + + #if DO_DRAW_FAN + #if STATUS_FAN_FRAMES > 2 + static bool old_blink; + static uint8_t fan_frame; + if (old_blink != blink) { + old_blink = blink; + if (!thermalManager.fan_speed[0] || ++fan_frame >= STATUS_FAN_FRAMES) fan_frame = 0; + } + #endif + if (PAGE_CONTAINS(STATUS_FAN_Y, STATUS_FAN_Y + STATUS_FAN_HEIGHT - 1)) + u8g.drawBitmapP(STATUS_FAN_X, STATUS_FAN_Y, STATUS_FAN_BYTEWIDTH, STATUS_FAN_HEIGHT, + #if STATUS_FAN_FRAMES > 2 + fan_frame == 1 ? status_fan1_bmp : + fan_frame == 2 ? status_fan2_bmp : + #if STATUS_FAN_FRAMES > 3 + fan_frame == 3 ? status_fan3_bmp : + #endif + #elif STATUS_FAN_FRAMES > 1 + blink && thermalManager.fan_speed[0] ? status_fan1_bmp : + #endif + status_fan0_bmp + ); + #endif + + // + // Temperature Graphics and Info + // + if (PAGE_UNDER(6 + 1 + 12 + 1 + 6 + 1)) { + // Extruders + #if DO_DRAW_HOTENDS + LOOP_L_N(e, MAX_HOTEND_DRAW) + _draw_hotend_status((heater_id_t)e, blink); + #endif + + // Laser / Spindle + #if DO_DRAW_CUTTER + if (cutter.isReadyForUI && PAGE_CONTAINS(STATUS_CUTTER_TEXT_Y - INFO_FONT_ASCENT, STATUS_CUTTER_TEXT_Y - 1)) { + #if CUTTER_UNIT_IS(PERCENT) + lcd_put_u8str(STATUS_CUTTER_TEXT_X, STATUS_CUTTER_TEXT_Y, cutter_power2str(cutter.unitPower)); + #elif CUTTER_UNIT_IS(RPM) + lcd_put_u8str(STATUS_CUTTER_TEXT_X - 2, STATUS_CUTTER_TEXT_Y, ftostr61rj(float(cutter.unitPower) / 1000)); + lcd_put_lchar('K'); + #else + lcd_put_u8str(STATUS_CUTTER_TEXT_X, STATUS_CUTTER_TEXT_Y, cutter_power2str(cutter.unitPower)); + #endif + } + #endif + + // Laser Cooler + #if DO_DRAW_COOLER + const uint8_t coolery = STATUS_COOLER_Y(status_cooler_bmp1), + coolerh = STATUS_COOLER_HEIGHT(status_cooler_bmp1); + if (PAGE_CONTAINS(coolery, coolery + coolerh - 1)) + u8g.drawBitmapP(STATUS_COOLER_X, coolery, STATUS_COOLER_BYTEWIDTH, coolerh, blink && cooler.enabled ? status_cooler_bmp2 : status_cooler_bmp1); + #endif + + // Laser Cooler Flow Meter + #if DO_DRAW_FLOWMETER + const uint8_t flowmetery = STATUS_FLOWMETER_Y(status_flowmeter_bmp1), + flowmeterh = STATUS_FLOWMETER_HEIGHT(status_flowmeter_bmp1); + if (PAGE_CONTAINS(flowmetery, flowmetery + flowmeterh - 1)) + u8g.drawBitmapP(STATUS_FLOWMETER_X, flowmetery, STATUS_FLOWMETER_BYTEWIDTH, flowmeterh, blink && cooler.flowpulses ? status_flowmeter_bmp2 : status_flowmeter_bmp1); + #endif + + // Laser Ammeter + #if DO_DRAW_AMMETER + const uint8_t ammetery = STATUS_AMMETER_Y(status_ammeter_bmp_mA), + ammeterh = STATUS_AMMETER_HEIGHT(status_ammeter_bmp_mA); + if (PAGE_CONTAINS(ammetery, ammetery + ammeterh - 1)) + u8g.drawBitmapP(STATUS_AMMETER_X, ammetery, STATUS_AMMETER_BYTEWIDTH, ammeterh, (ammeter.current < 0.1f) ? status_ammeter_bmp_mA : status_ammeter_bmp_A); + #endif + + // Heated Bed + TERN_(DO_DRAW_BED, _draw_bed_status(blink)); + + // Heated Chamber + TERN_(DO_DRAW_CHAMBER, _draw_chamber_status()); + + // Cooler + TERN_(DO_DRAW_COOLER, _draw_cooler_status()); + + // Flowmeter + TERN_(DO_DRAW_FLOWMETER, _draw_flowmeter_status()); + + // Flowmeter + TERN_(DO_DRAW_AMMETER, _draw_ammeter_status()); + + // Fan, if a bitmap was provided + #if DO_DRAW_FAN + if (PAGE_CONTAINS(STATUS_FAN_TEXT_Y - INFO_FONT_ASCENT, STATUS_FAN_TEXT_Y - 1)) { + char c = '%'; + uint16_t spd = thermalManager.fan_speed[0]; + if (spd) { + #if ENABLED(ADAPTIVE_FAN_SLOWING) + if (!blink && thermalManager.fan_speed_scaler[0] < 128) { + spd = thermalManager.scaledFanSpeed(0, spd); + c = '*'; + } + #endif + lcd_put_u8str(STATUS_FAN_TEXT_X, STATUS_FAN_TEXT_Y, i16tostr3rj(thermalManager.pwmToPercent(spd))); + lcd_put_lchar(c); + } + } + #endif + } + + #if ENABLED(SDSUPPORT) + // + // SD Card Symbol + // + if (card.isFileOpen() && PAGE_CONTAINS(42, 51)) { + // Upper box + u8g.drawBox(42, 42, 8, 7); // 42-48 (or 41-47) + // Right edge + u8g.drawBox(50, 44, 2, 5); // 44-48 (or 43-47) + // Bottom hollow box + u8g.drawFrame(42, 49, 10, 4); // 49-52 (or 48-51) + // Corner pixel + u8g.drawPixel(50, 43); // 43 (or 42) + } + #endif // SDSUPPORT + + #if HAS_PRINT_PROGRESS + // + // Progress bar frame + // + + if (PAGE_CONTAINS(PROGRESS_BAR_Y, PROGRESS_BAR_Y + 3)) + u8g.drawFrame(PROGRESS_BAR_X, PROGRESS_BAR_Y, PROGRESS_BAR_WIDTH, 4); + + // + // Progress bar solid part + // + + if (PAGE_CONTAINS(PROGRESS_BAR_Y + 1, PROGRESS_BAR_Y + 2)) + u8g.drawBox(PROGRESS_BAR_X + 1, PROGRESS_BAR_Y + 1, progress_bar_solid_width, 2); + + if (PAGE_CONTAINS(EXTRAS_BASELINE - INFO_FONT_ASCENT, EXTRAS_BASELINE - 1)) { + + #if ALL(SHOW_SD_PERCENT, SHOW_REMAINING_TIME, ROTATE_PROGRESS_DISPLAY) + + if (prev_blink != blink) { + prev_blink = blink; + if (++progress_state >= 3) progress_state = 0; + } + + if (progress_state == 0) { + if (progress_string[0]) { + lcd_put_u8str(progress_x_pos, EXTRAS_BASELINE, progress_string); + lcd_put_lchar('%'); + } + } + else if (progress_state == 2 && estimation_string[0]) { + lcd_put_u8str(PROGRESS_BAR_X, EXTRAS_BASELINE, F("R:")); + lcd_put_u8str(estimation_x_pos, EXTRAS_BASELINE, estimation_string); + } + else if (elapsed_string[0]) { + lcd_put_u8str(PROGRESS_BAR_X, EXTRAS_BASELINE, F("E:")); + lcd_put_u8str(elapsed_x_pos, EXTRAS_BASELINE, elapsed_string); + } + + #else // !SHOW_SD_PERCENT || !SHOW_REMAINING_TIME || !ROTATE_PROGRESS_DISPLAY + + // + // SD Percent Complete + // + + #if ENABLED(SHOW_SD_PERCENT) + if (progress_string[0]) { + lcd_put_u8str(55, EXTRAS_BASELINE, progress_string); // Percent complete + lcd_put_lchar('%'); + } + #endif + + // + // Elapsed Time + // + + #if ENABLED(SHOW_REMAINING_TIME) + if (blink && estimation_string[0]) { + lcd_put_lchar(estimation_x_pos, EXTRAS_BASELINE, 'R'); + lcd_put_u8str(estimation_string); + } + else + #endif + lcd_put_u8str(elapsed_x_pos, EXTRAS_BASELINE, elapsed_string); + + #endif // !SHOW_SD_PERCENT || !SHOW_REMAINING_TIME || !ROTATE_PROGRESS_DISPLAY + } + + #endif // HAS_PRINT_PROGRESS + + // + // XYZ Coordinates + // + + #if EITHER(XYZ_NO_FRAME, XYZ_HOLLOW_FRAME) + #define XYZ_FRAME_TOP 29 + #define XYZ_FRAME_HEIGHT INFO_FONT_ASCENT + 3 + #else + #define XYZ_FRAME_TOP 30 + #define XYZ_FRAME_HEIGHT INFO_FONT_ASCENT + 1 + #endif + + if (PAGE_CONTAINS(XYZ_FRAME_TOP, XYZ_FRAME_TOP + XYZ_FRAME_HEIGHT - 1)) { + + #if DISABLED(XYZ_NO_FRAME) + #if ENABLED(XYZ_HOLLOW_FRAME) + u8g.drawFrame(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 29-40 7: 29-39 + #else + u8g.drawBox(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 30-39 7: 30-37 + #endif + #endif + + if (PAGE_CONTAINS(XYZ_BASELINE - (INFO_FONT_ASCENT - 1), XYZ_BASELINE)) { + + #if NONE(XYZ_NO_FRAME, XYZ_HOLLOW_FRAME) + u8g.setColorIndex(0); // white on black + #endif + + #if HAS_DUAL_MIXING + + // Two-component mix / gradient instead of XY + + char mixer_messages[15]; + PGM_P mix_label; + #if ENABLED(GRADIENT_MIX) + if (mixer.gradient.enabled) { + mixer.update_mix_from_gradient(); + mix_label = PSTR("Gr"); + } + else + #endif + { + mixer.update_mix_from_vtool(); + mix_label = PSTR("Mx"); + } + + #pragma GCC diagnostic push + #if GCC_VERSION <= 50000 + #pragma GCC diagnostic ignored "-Wformat-overflow" + #endif + + sprintf_P(mixer_messages, PSTR(S_FMT " %d;%d%% "), mix_label, int(mixer.mix[0]), int(mixer.mix[1])); + lcd_put_u8str(X_LABEL_POS, XYZ_BASELINE, mixer_messages); + + #pragma GCC diagnostic pop + + #else + + if (show_e_total) { + #if ENABLED(LCD_SHOW_E_TOTAL) + _draw_axis_value(E_AXIS, xstring, true); + lcd_put_u8str(F(" ")); + #endif + } + else { + _draw_axis_value(X_AXIS, xstring, blink); + _draw_axis_value(Y_AXIS, ystring, blink); + } + + #endif + + _draw_axis_value(Z_AXIS, zstring, blink); + + #if NONE(XYZ_NO_FRAME, XYZ_HOLLOW_FRAME) + u8g.setColorIndex(1); // black on white + #endif + } + } + + // + // Feedrate + // + #define EXTRAS_2_BASELINE (EXTRAS_BASELINE + 3) + + if (PAGE_CONTAINS(EXTRAS_2_BASELINE - INFO_FONT_ASCENT, EXTRAS_2_BASELINE - 1)) { + set_font(FONT_MENU); + lcd_put_lchar(3, EXTRAS_2_BASELINE, LCD_STR_FEEDRATE[0]); + + set_font(FONT_STATUSMENU); + lcd_put_u8str(12, EXTRAS_2_BASELINE, i16tostr3rj(feedrate_percentage)); + lcd_put_lchar('%'); + + // + // Filament sensor display if SD is disabled + // + #if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT) + lcd_put_u8str(56, EXTRAS_2_BASELINE, wstring); + lcd_put_u8str(102, EXTRAS_2_BASELINE, mstring); + lcd_put_lchar('%'); + set_font(FONT_MENU); + lcd_put_lchar(47, EXTRAS_2_BASELINE, LCD_STR_FILAM_DIA[0]); // lcd_put_u8str(F(LCD_STR_FILAM_DIA)); + lcd_put_lchar(93, EXTRAS_2_BASELINE, LCD_STR_FILAM_MUL[0]); + #endif + } + + // + // Status line + // + if (PAGE_CONTAINS(STATUS_BASELINE - INFO_FONT_ASCENT, STATUS_BASELINE + INFO_FONT_DESCENT)) { + lcd_moveto(0, STATUS_BASELINE); + + #if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT) + // Alternate Status message and Filament display + if (ELAPSED(millis(), next_filament_display)) { + lcd_put_u8str(F(LCD_STR_FILAM_DIA)); + lcd_put_lchar(':'); + lcd_put_u8str(wstring); + lcd_put_u8str(F(" " LCD_STR_FILAM_MUL)); + lcd_put_lchar(':'); + lcd_put_u8str(mstring); + lcd_put_lchar('%'); + return; + } + #endif + + draw_status_message(blink); + } +} + +/** + * Draw the Status Message area + */ +void MarlinUI::draw_status_message(const bool blink) { + + // Get the UTF8 character count of the string + uint8_t lcd_width = LCD_WIDTH, pixel_width = LCD_PIXEL_WIDTH, + slen = utf8_strlen(status_message); + + #if HAS_POWER_MONITOR + if (power_monitor.display_enabled()) { + // make room at the end of the status line for the power monitor reading + lcd_width -= 6; + pixel_width -= (MENU_FONT_WIDTH) * 6; + } + #endif + + #if ENABLED(STATUS_MESSAGE_SCROLLING) + + static bool last_blink = false; + + if (slen <= lcd_width) { + // The string fits within the line. Print with no scrolling + lcd_put_u8str(status_message); + while (slen < lcd_width) { lcd_put_lchar(' '); ++slen; } + } + else { + // String is longer than the available space + if (blink != last_blink) { + last_blink = blink; + advance_status_scroll(); + } + + // Get a pointer to the next valid UTF8 character + // and the string remaining length + uint8_t rlen; + const char *stat = status_and_len(rlen); + lcd_put_u8str_max(stat, pixel_width); + + // If the remaining string doesn't completely fill the screen + if (rlen < lcd_width) { + uint8_t chars = lcd_width - rlen; // Amount of space left in characters + lcd_put_lchar(' '); // Always at 1+ spaces left, draw a space + if (--chars) { // Draw a second space if there's room + lcd_put_lchar(' '); + if (--chars) { // Draw a third space if there's room + lcd_put_lchar(' '); + if (--chars) { // Print a second copy of the message + lcd_put_u8str_max(status_message, pixel_width - (rlen + 2) * (MENU_FONT_WIDTH)); + lcd_put_lchar(' '); + } + } + } + } + } + + #else // !STATUS_MESSAGE_SCROLLING + + UNUSED(blink); + + // Just print the string to the LCD + lcd_put_u8str_max(status_message, pixel_width); + + // Fill the rest with spaces + for (; slen < lcd_width; ++slen) lcd_put_lchar(' '); + + #endif // !STATUS_MESSAGE_SCROLLING + + #if HAS_POWER_MONITOR + display_power_monitor(pixel_width + MENU_FONT_WIDTH, STATUS_BASELINE); + #endif +} + +#endif // HAS_MARLINUI_U8GLIB && !LIGHTWEIGHT_UI diff --git a/src/lcd/dogm/status_screen_lite_ST7920.cpp b/src/lcd/dogm/status_screen_lite_ST7920.cpp new file mode 100644 index 0000000..492a79a --- /dev/null +++ b/src/lcd/dogm/status_screen_lite_ST7920.cpp @@ -0,0 +1,920 @@ +/** + * Lightweight Status Screen for the RepRapDiscount Full + * Graphics Smart Controller (ST7920-based 128x64 LCD) + * + * (c) 2017 Aleph Objects, Inc. + * + * The code in this page is free software: you can + * redistribute it and/or modify it under the terms of the GNU + * General Public License (GNU GPL) as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. The code is distributed WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. + */ + +/** + * Implementation of a Status Screen for the RepRapDiscount + * Full Graphics Smart Controller using native ST7920 commands + * instead of U8Glib. + * + * This alternative Status Screen makes use of the built-in character + * generation capabilities of the ST7920 to update the Status Screen + * with less SPI traffic and CPU use. In particular: + * + * - The fan and bed animations are handled using custom characters + * that are stored in CGRAM. This allows for the animation to be + * updated by writing a single character to the text-buffer (DDRAM). + * + * - All the information in the Status Screen is text that is written + * to DDRAM, so the work of generating the bitmaps is offloaded to + * the ST7920 rather than being render by U8Glib on the MCU. + * + * - The graphics buffer (GDRAM) is only used for static graphics + * elements (nozzle and feedrate bitmaps) and for the progress + * bar, so updates are sporadic. + */ + +// +// status_screen_lite_ST7920.cpp +// Lightweight Status Screen for Graphical Display +// + +#include "../../inc/MarlinConfigPre.h" + +#if ENABLED(LIGHTWEIGHT_UI) + +#include "status_screen_lite_ST7920.h" + +#include "../marlinui.h" +#include "../fontutils.h" +#include "../lcdprint.h" +#include "../../libs/duration_t.h" +#include "../../module/motion.h" +#include "../../module/printcounter.h" +#include "../../module/temperature.h" + +#if ENABLED(SDSUPPORT) + #include "../../sd/cardreader.h" +#endif + +#if ENABLED(LCD_SHOW_E_TOTAL) + #include "../../MarlinCore.h" // for printingIsActive +#endif + +#define TEXT_MODE_LCD_WIDTH 16 + +#define BUFFER_WIDTH 256 +#define BUFFER_HEIGHT 32 + +#define DDRAM_LINE_1 0x00 +#define DDRAM_LINE_2 0x10 +#define DDRAM_LINE_3 0x08 +#define DDRAM_LINE_4 0x18 + +ST7920_Lite_Status_Screen::st7920_state_t ST7920_Lite_Status_Screen::current_bits; + +void ST7920_Lite_Status_Screen::cmd(const uint8_t cmd) { + if (!current_bits.synced || !current_bits.cmd) { + current_bits.synced = true; + current_bits.cmd = true; + sync_cmd(); + } + write_byte(cmd); +} + +void ST7920_Lite_Status_Screen::begin_data() { + if (!current_bits.synced || current_bits.cmd) { + current_bits.synced = true; + current_bits.cmd = false; + sync_dat(); + } +} + +void ST7920_Lite_Status_Screen::write_str(const char *str) { + while (*str) write_byte(*str++); +} + +void ST7920_Lite_Status_Screen::write_str(const char *str, uint8_t len) { + while (*str && len--) write_byte(*str++); +} + +void ST7920_Lite_Status_Screen::write_str(FSTR_P const fstr) { + PGM_P pstr = FTOP(fstr); + while (char c = pgm_read_byte(pstr++)) write_byte(c); +} + +void ST7920_Lite_Status_Screen::write_number(const int16_t value, const uint8_t digits/*=3*/) { + char str[7]; + PGM_P fmt; + switch (digits) { + case 6: fmt = PSTR("%6d"); break; + case 5: fmt = PSTR("%5d"); break; + case 4: fmt = PSTR("%4d"); break; + case 3: fmt = PSTR("%3d"); break; + case 2: fmt = PSTR("%2d"); break; + case 1: fmt = PSTR("%1d"); break; + default: return; + } + sprintf_P(str, fmt, value); + write_str(str); +} + +void ST7920_Lite_Status_Screen::display_status(const bool display_on, const bool cursor_on, const bool blink_on) { + extended_function_set(false); + cmd(0b00001000 | + (display_on ? 0b0100 : 0) | + (cursor_on ? 0b0010 : 0) | + (blink_on ? 0b0001 : 0) + ); +} + +// Sets the extended and graphics bits simultaneously, regardless of +// the current state. This is a helper function for extended_function_set() +// and graphics() +void ST7920_Lite_Status_Screen::_extended_function_set(const bool extended, const bool graphics) { + cmd( 0b00100000 | + (extended ? 0b00000100 : 0) | + (graphics ? 0b00000010 : 0) + ); + current_bits.extended = extended; + current_bits.graphics = graphics; +} + +void ST7920_Lite_Status_Screen::extended_function_set(const bool extended) { + if (extended != current_bits.extended) + _extended_function_set(extended, current_bits.graphics); +} + +void ST7920_Lite_Status_Screen::graphics(const bool graphics) { + if (graphics != current_bits.graphics) + _extended_function_set(current_bits.extended, graphics); +} + +void ST7920_Lite_Status_Screen::entry_mode_select(const bool ac_increase, const bool shift) { + extended_function_set(false); + cmd(0b00000100 | + (ac_increase ? 0b00000010 : 0) | + (shift ? 0b00000001 : 0) + ); +} + +// Sets the sa bit regardless of the current state. This is a helper +// function for scroll_or_addr_select() +void ST7920_Lite_Status_Screen::_scroll_or_addr_select(const bool sa) { + extended_function_set(true); + cmd(0b00000010 | (sa ? 0b00000001 : 0)); + current_bits.sa = sa; +} + +void ST7920_Lite_Status_Screen::scroll_or_addr_select(const bool sa) { + if (sa != current_bits.sa) + _scroll_or_addr_select(sa); +} + +void ST7920_Lite_Status_Screen::set_ddram_address(const uint8_t addr) { + extended_function_set(false); + cmd(0b10000000 | (addr & 0b00111111)); +} + +void ST7920_Lite_Status_Screen::set_cgram_address(const uint8_t addr) { + extended_function_set(false); + cmd(0b01000000 | (addr & 0b00111111)); +} + +void ST7920_Lite_Status_Screen::set_gdram_address(const uint8_t x, const uint8_t y) { + extended_function_set(true); + cmd(0b10000000 | (y & 0b01111111)); + cmd(0b10000000 | (x & 0b00001111)); +} + +void ST7920_Lite_Status_Screen::clear() { + extended_function_set(false); + cmd(0x00000001); + delay(15); //delay for CGRAM clear +} + +void ST7920_Lite_Status_Screen::home() { + extended_function_set(false); + cmd(0x00000010); +} + +/* This fills the entire text buffer with spaces */ +void ST7920_Lite_Status_Screen::clear_ddram() { + set_ddram_address(DDRAM_LINE_1); + begin_data(); + for (uint8_t i = 64; i--;) write_byte(' '); +} + +/* This fills the entire graphics buffer with zeros */ +void ST7920_Lite_Status_Screen::clear_gdram() { + LOOP_L_N(y, BUFFER_HEIGHT) { + set_gdram_address(0, y); + begin_data(); + for (uint8_t i = (BUFFER_WIDTH) / 16; i--;) write_word(0); + } +} + +void ST7920_Lite_Status_Screen::load_cgram_icon(const uint16_t addr, const void *data) { + const uint16_t *p_word = (const uint16_t *)data; + set_cgram_address(addr); + begin_data(); + for (uint8_t i = 16; i--;) + write_word(pgm_read_word(p_word++)); +} + +/** + * Draw an icon in GDRAM. Position specified in DDRAM + * coordinates. i.e., X from 1 to 8, Y from 1 to 4. + */ +void ST7920_Lite_Status_Screen::draw_gdram_icon(uint8_t x, uint8_t y, const void *data) { + const uint16_t *p_word = (const uint16_t *)data; + // Handle display folding + if (y > 1) y -= 2, x += 8; + for (int i = 0; i < 16; i++) { + set_gdram_address(x, i + y * 16); + begin_data(); + write_word(pgm_read_word(p_word++)); + } +} + +/************************** ICON DEFINITIONS *************************************/ + +#define CGRAM_ICON_1_ADDR 0x00 +#define CGRAM_ICON_2_ADDR 0x10 +#define CGRAM_ICON_3_ADDR 0x20 +#define CGRAM_ICON_4_ADDR 0x30 + +#define CGRAM_ICON_1_WORD 0x00 +#define CGRAM_ICON_2_WORD 0x02 +#define CGRAM_ICON_3_WORD 0x04 +#define CGRAM_ICON_4_WORD 0x06 + +const uint8_t degree_symbol_y_top = 1; +PROGMEM const uint8_t degree_symbol[] = { + 0b00110000, + 0b01001000, + 0b01001000, + 0b00110000, +}; + +const uint16_t nozzle_icon[] PROGMEM = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000111111110000, + 0b0001111111111000, + 0b0001111111111000, + 0b0001111111111000, + 0b0000111111110000, + 0b0000111111110000, + 0b0001111111111000, + 0b0001111111111000, + 0b0001111111111000, + 0b0000011111100000, + 0b0000001111000000, + 0b0000000110000000, + 0b0000000000000000, + 0b0000000000000000 +}; + +const uint16_t bed_icon[] PROGMEM = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0111111111111110, + 0b0111111111111110, + 0b0110000000000110, + 0b0000000000000000, + 0b0000000000000000 +}; + +const uint16_t heat1_icon[] PROGMEM = { + 0b0000000000000000, + 0b0010001000100000, + 0b0001000100010000, + 0b0000100010001000, + 0b0000100010001000, + 0b0001000100010000, + 0b0010001000100000, + 0b0010001000100000, + 0b0001000100010000, + 0b0000100010001000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 +}; + +const uint16_t heat2_icon[] PROGMEM = { + 0b0000000000000000, + 0b0000100010001000, + 0b0000100010001000, + 0b0001000100010000, + 0b0010001000100000, + 0b0010001000100000, + 0b0001000100010000, + 0b0000100010001000, + 0b0000100010001000, + 0b0001000100010000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 +}; + +const uint16_t fan1_icon[] PROGMEM = { + 0b0000000000000000, + 0b0111111111111110, + 0b0111000000001110, + 0b0110001111000110, + 0b0100001111000010, + 0b0100000110000010, + 0b0101100000011010, + 0b0101110110111010, + 0b0101100000011010, + 0b0100000110000010, + 0b0100001111000010, + 0b0110001111000110, + 0b0111000000001110, + 0b0111111111111110, + 0b0000000000000000, + 0b0000000000000000 +}; + +const uint16_t fan2_icon[] PROGMEM = { + 0b0000000000000000, + 0b0111111111111110, + 0b0111000000001110, + 0b0110010000100110, + 0b0100111001110010, + 0b0101111001111010, + 0b0100110000110010, + 0b0100000110000010, + 0b0100110000110010, + 0b0101111001111010, + 0b0100111001110010, + 0b0110010000100110, + 0b0111000000001110, + 0b0111111111111110, + 0b0000000000000000, + 0b0000000000000000 +}; + +const uint16_t feedrate_icon[] PROGMEM = { + 0b0000000000000000, + 0b0111111000000000, + 0b0110000000000000, + 0b0110000000000000, + 0b0110000000000000, + 0b0111111011111000, + 0b0110000011001100, + 0b0110000011001100, + 0b0110000011001100, + 0b0110000011111000, + 0b0000000011001100, + 0b0000000011001100, + 0b0000000011001100, + 0b0000000011001100, + 0b0000000000000000, + 0b0000000000000000 +}; + +/************************** MAIN SCREEN *************************************/ + +/** + * The ST7920 has no degree character, so draw it to GDRAM. + * This function takes character position xy + * i.e., x is [0-15], while the y position is [0-3] + */ +void ST7920_Lite_Status_Screen::draw_degree_symbol(uint8_t x, uint8_t y, const bool draw) { + const uint8_t *p_bytes = degree_symbol; + // Handle display folding + if (y > 1) y -= 2, x += 16; + const bool oddChar = x & 1; + const uint8_t x_word = x >> 1, + y_top = degree_symbol_y_top, + y_bot = y_top + COUNT(degree_symbol); + LOOP_S_L_N(i, y_top, y_bot) { + uint8_t byte = pgm_read_byte(p_bytes++); + set_gdram_address(x_word, i + y * 16); + begin_data(); + if (draw) { + write_byte(oddChar ? 0x00 : byte); + write_byte(oddChar ? byte : 0x00); + } + else + write_word(0x0000); + } +} + +void ST7920_Lite_Status_Screen::draw_static_elements() { + scroll_or_addr_select(0); + + // Load the animated bed and fan icons + load_cgram_icon(CGRAM_ICON_1_ADDR, heat1_icon); + load_cgram_icon(CGRAM_ICON_2_ADDR, heat2_icon); + load_cgram_icon(CGRAM_ICON_3_ADDR, fan1_icon); + load_cgram_icon(CGRAM_ICON_4_ADDR, fan2_icon); + + // Draw the static icons in GDRAM + draw_gdram_icon(0, 0, nozzle_icon); + #if HAS_MULTI_HOTEND + draw_gdram_icon(0, 1, nozzle_icon); + draw_gdram_icon(0, 2, bed_icon); + #else + draw_gdram_icon(0, 1, bed_icon); + #endif + draw_gdram_icon(5, 1, feedrate_icon); + + // Draw the initial fan icon + draw_fan_icon(false); +} + +/** + * Although this is undocumented, the ST7920 allows the character + * data buffer (DDRAM) to be used in conjunction with the graphics + * bitmap buffer (CGRAM). The contents of the graphics buffer is + * XORed with the data from the character generator. This allows + * us to make the progress bar out of graphical data (the bar) and + * text data (the percentage). + */ +void ST7920_Lite_Status_Screen::draw_progress_bar(const uint8_t value) { + #if HOTENDS == 1 + // If we have only one extruder, draw a long progress bar on the third line + constexpr uint8_t top = 1, // Top in pixels + bottom = 13, // Bottom in pixels + left = 12, // Left edge, in 16-bit words + width = 4; // Width of progress bar, in 16-bit words + #else + constexpr uint8_t top = 16 + 1, + bottom = 16 + 13, + left = 5, + width = 3; + #endif + const uint8_t char_pcnt = 100 / width; // How many percent does each 16-bit word represent? + + // Draw the progress bar as a bitmap in CGRAM + LOOP_S_LE_N(y, top, bottom) { + set_gdram_address(left, y); + begin_data(); + LOOP_L_N(x, width) { + uint16_t gfx_word = 0x0000; + if ((x + 1) * char_pcnt <= value) + gfx_word = 0xFFFF; // Draw completely filled bytes + else if ((x * char_pcnt) < value) + gfx_word = int(0x8000) >> (value % char_pcnt) * 16 / char_pcnt; // Draw partially filled bytes + + // Draw the frame around the progress bar + if (y == top || y == bottom) + gfx_word = 0xFFFF; // Draw top/bottom border + else if (x == width - 1) + gfx_word |= 0x0001; // Draw right border + else if (x == 0) + gfx_word |= 0x8000; // Draw left border + write_word(gfx_word); + } + } + + // Draw the percentage as text in DDRAM + #if HOTENDS == 1 + set_ddram_address(DDRAM_LINE_3 + 4); + begin_data(); + write_byte(' '); + #else + set_ddram_address(DDRAM_LINE_2 + left); + begin_data(); + #endif + + // Draw centered + if (value > 9) { + write_number(value, 4); + write_str(F("% ")); + } + else { + write_number(value, 3); + write_str(F("% ")); + } +} + +void ST7920_Lite_Status_Screen::draw_fan_icon(const bool whichIcon) { + set_ddram_address(DDRAM_LINE_1 + 5); + begin_data(); + write_word(whichIcon ? CGRAM_ICON_3_WORD : CGRAM_ICON_4_WORD); +} + +void ST7920_Lite_Status_Screen::draw_heat_icon(const bool whichIcon, const bool heating) { + set_ddram_address( + #if HOTENDS == 1 + DDRAM_LINE_2 + #else + DDRAM_LINE_3 + #endif + ); + begin_data(); + if (heating) + write_word(whichIcon ? CGRAM_ICON_1_WORD : CGRAM_ICON_2_WORD); + else { + write_byte(' '); + write_byte(' '); + } +} + +#define FAR(a,b) (((a > b) ? (a-b) : (b-a)) > 2) + +static struct { + bool E1_show_target : 1; + bool E2_show_target : 1; + #if HAS_HEATED_BED + bool bed_show_target : 1; + #endif +} display_state = { + true, true, TERN_(HAS_HEATED_BED, true) +}; + +void ST7920_Lite_Status_Screen::draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange) { + switch (line) { + case 0: set_ddram_address(DDRAM_LINE_1 + 1); break; + case 1: set_ddram_address(DDRAM_LINE_2 + 1); break; + case 2: set_ddram_address(DDRAM_LINE_3 + 1); break; + case 3: set_ddram_address(DDRAM_LINE_3 + 1); break; + } + begin_data(); + write_number(temp); + + if (showTarget) { + write_byte('\x1A'); + write_number(target); + }; + + if (targetStateChange) { + if (!showTarget) write_str(F(" ")); + draw_degree_symbol(5, line, !showTarget); + draw_degree_symbol(9, line, showTarget); + } +} + +void ST7920_Lite_Status_Screen::draw_extruder_1_temp(const int16_t temp, const int16_t target, bool forceUpdate) { + const bool show_target = target && FAR(temp, target); + draw_temps(0, temp, target, show_target, display_state.E1_show_target != show_target || forceUpdate); + display_state.E1_show_target = show_target; +} + +void ST7920_Lite_Status_Screen::draw_extruder_2_temp(const int16_t temp, const int16_t target, bool forceUpdate) { + const bool show_target = target && FAR(temp, target); + draw_temps(1, temp, target, show_target, display_state.E2_show_target != show_target || forceUpdate); + display_state.E2_show_target = show_target; +} + +#if HAS_HEATED_BED + void ST7920_Lite_Status_Screen::draw_bed_temp(const int16_t temp, const int16_t target, bool forceUpdate) { + const bool show_target = target && FAR(temp, target); + draw_temps(TERN(HAS_MULTI_HOTEND, 2, 1), temp, target, show_target, display_state.bed_show_target != show_target || forceUpdate); + display_state.bed_show_target = show_target; + } +#endif + +void ST7920_Lite_Status_Screen::draw_fan_speed(const uint8_t value) { + set_ddram_address(DDRAM_LINE_1 + 6); + begin_data(); + write_number(value, 3); + write_byte('%'); +} + +void ST7920_Lite_Status_Screen::draw_print_time(const duration_t &elapsed, char suffix) { + #if HOTENDS == 1 + set_ddram_address(DDRAM_LINE_3); + #else + set_ddram_address(DDRAM_LINE_3 + 5); + #endif + char str[7]; + int str_length = elapsed.toDigital(str); + str[str_length++] = suffix; + begin_data(); + write_str(str, str_length); +} + +void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint16_t percentage) { + // We only have enough room for the feedrate when + // we have one extruder + #if HOTENDS == 1 + set_ddram_address(DDRAM_LINE_2 + 6); + begin_data(); + write_number(percentage, 3); + write_byte('%'); + #else + UNUSED(percentage); + #endif +} + +void ST7920_Lite_Status_Screen::draw_status_message() { + const char *str = ui.status_message; + + set_ddram_address(DDRAM_LINE_4); + begin_data(); + #if ENABLED(STATUS_MESSAGE_SCROLLING) + uint8_t slen = utf8_strlen(str); + + if (slen <= TEXT_MODE_LCD_WIDTH) { + // String fits the LCD, so just print it + write_str(str); + while (slen < TEXT_MODE_LCD_WIDTH) { write_byte(' '); ++slen; } + } + else { + // String is larger than the available space in screen. + + // Get a pointer to the next valid UTF8 character + // and the string remaining length + uint8_t rlen; + const char *stat = ui.status_and_len(rlen); + write_str(stat, TEXT_MODE_LCD_WIDTH); + + // If the remaining string doesn't completely fill the screen + if (rlen < TEXT_MODE_LCD_WIDTH) { + uint8_t chars = TEXT_MODE_LCD_WIDTH - rlen; // Amount of space left in characters + write_byte(' '); // Always at 1+ spaces left, draw a space + if (--chars) { // Draw a second space if there's room + write_byte(' '); + if (--chars) { // Draw a third space if there's room + write_byte(' '); + if (--chars) write_str(str, chars); // Print a second copy of the message + } + } + } + ui.advance_status_scroll(); + } + + #else + + uint8_t slen = utf8_strlen(str); + write_str(str, TEXT_MODE_LCD_WIDTH); + for (; slen < TEXT_MODE_LCD_WIDTH; ++slen) write_byte(' '); + + #endif +} + +void ST7920_Lite_Status_Screen::draw_position(const xyze_pos_t &pos, const bool position_trusted) { + char str[7]; + set_ddram_address(DDRAM_LINE_4); + begin_data(); + + // If position is unknown, flash the labels. + const unsigned char alt_label = position_trusted ? 0 : (ui.get_blink() ? ' ' : 0); + + if (TERN0(LCD_SHOW_E_TOTAL, printingIsActive())) { + #if ENABLED(LCD_SHOW_E_TOTAL) + char tmp[15]; + const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm + sprintf_P(tmp, PSTR("E%-7ld%cm "), uint32_t(_MAX(e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm + write_str(tmp); + #endif + } + else { + write_byte(alt_label ? alt_label : 'X'); + write_str(dtostrf(pos.x, -4, 0, str), 4); + + write_byte(alt_label ? alt_label : 'Y'); + write_str(dtostrf(pos.y, -4, 0, str), 4); + } + + write_byte(alt_label ? alt_label : 'Z'); + write_str(dtostrf(pos.z, -5, 1, str), 5); +} + +bool ST7920_Lite_Status_Screen::indicators_changed() { + // We only add the target temperatures to the checksum + // because the actual temps fluctuate so by updating + // them only during blinks we gain a bit of stability. + const bool blink = ui.get_blink(); + const uint16_t feedrate_perc = feedrate_percentage; + const uint16_t fs = thermalManager.scaledFanSpeed(0); + const celsius_t extruder_1_target = thermalManager.degTargetHotend(0); + #if HAS_MULTI_HOTEND + const celsius_t extruder_2_target = thermalManager.degTargetHotend(1); + #endif + #if HAS_HEATED_BED + const celsius_t bed_target = thermalManager.degTargetBed(); + #endif + static uint16_t last_checksum = 0; + const uint16_t checksum = blink ^ feedrate_perc ^ fs ^ extruder_1_target + ^ TERN0(HAS_MULTI_HOTEND, extruder_2_target) + ^ TERN0(HAS_HEATED_BED, bed_target); + if (last_checksum == checksum) return false; + last_checksum = checksum; + return true; +} + +void ST7920_Lite_Status_Screen::update_indicators(const bool forceUpdate) { + if (forceUpdate || indicators_changed()) { + const bool blink = ui.get_blink(); + const duration_t elapsed = print_job_timer.duration(); + duration_t remaining = TERN0(USE_M73_REMAINING_TIME, ui.get_remaining_time()); + const uint16_t feedrate_perc = feedrate_percentage; + const celsius_t extruder_1_temp = thermalManager.wholeDegHotend(0), + extruder_1_target = thermalManager.degTargetHotend(0); + #if HAS_MULTI_HOTEND + const celsius_t extruder_2_temp = thermalManager.wholeDegHotend(1), + extruder_2_target = thermalManager.degTargetHotend(1); + #endif + #if HAS_HEATED_BED + const celsius_t bed_temp = thermalManager.wholeDegBed(), + bed_target = thermalManager.degTargetBed(); + #endif + + draw_extruder_1_temp(extruder_1_temp, extruder_1_target, forceUpdate); + TERN_(HAS_MULTI_HOTEND, draw_extruder_2_temp(extruder_2_temp, extruder_2_target, forceUpdate)); + TERN_(HAS_HEATED_BED, draw_bed_temp(bed_temp, bed_target, forceUpdate)); + + uint8_t spd = thermalManager.fan_speed[0]; + #if ENABLED(ADAPTIVE_FAN_SLOWING) + if (!blink && thermalManager.fan_speed_scaler[0] < 128) + spd = thermalManager.scaledFanSpeed(0, spd); + #endif + draw_fan_speed(thermalManager.pwmToPercent(spd)); + + // Draw elapsed/remaining time + const bool show_remaining = ENABLED(SHOW_REMAINING_TIME) && (DISABLED(ROTATE_PROGRESS_DISPLAY) || blink); + if (show_remaining && !remaining.second()) { + const auto progress = ui.get_progress_percent(); + if (progress) + remaining = elapsed.second() * (100 - progress) / progress; + } + if (show_remaining && remaining.second()) + draw_print_time(remaining, 'R'); + else + draw_print_time(elapsed); + + draw_feedrate_percentage(feedrate_perc); + + // Update the fan and bed animations + if (spd) draw_fan_icon(blink); + TERN_(HAS_HEATED_BED, draw_heat_icon(bed_target > 0 && blink, bed_target > 0)); + } +} + +bool ST7920_Lite_Status_Screen::position_changed() { + const xyz_pos_t pos = current_position; + const uint8_t checksum = uint8_t(pos.x) ^ uint8_t(pos.y) ^ uint8_t(pos.z); + static uint8_t last_checksum = 0, changed = last_checksum != checksum; + if (changed) last_checksum = checksum; + return changed; +} + +bool ST7920_Lite_Status_Screen::status_changed() { + uint8_t checksum = 0; + for (const char *p = ui.status_message; *p; p++) checksum ^= *p; + static uint8_t last_checksum = 0; + bool changed = last_checksum != checksum; + if (changed) last_checksum = checksum; + return changed; +} + +bool ST7920_Lite_Status_Screen::blink_changed() { + static uint8_t last_blink = 0; + const bool blink = ui.get_blink(), changed = last_blink != blink; + if (changed) last_blink = blink; + return changed; +} + +#ifndef STATUS_EXPIRE_SECONDS + #define STATUS_EXPIRE_SECONDS 20 +#endif + +void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) { + + #if STATUS_EXPIRE_SECONDS + static uint8_t countdown = 0; + #endif + + /** + * There's only enough room for either the status message or the position, + * so draw one or the other. When the status message changes, show it for + * a few seconds, then return to the position display once the head moves. + * + * countdown > 1 -- Show status + * countdown = 1 -- Show status, until movement + * countdown = 0 -- Show position + * + * If STATUS_EXPIRE_SECONDS is zero, only the status is shown. + */ + if (forceUpdate || status_changed()) { + TERN_(STATUS_MESSAGE_SCROLLING, ui.status_scroll_offset = 0); + #if STATUS_EXPIRE_SECONDS + countdown = ui.status_message[0] ? STATUS_EXPIRE_SECONDS : 0; + #endif + draw_status_message(); + blink_changed(); // Clear changed flag + } + #if !STATUS_EXPIRE_SECONDS + else if (TERN0(STATUS_MESSAGE_SCROLLING, blink_changed())) + draw_status_message(); + #else + else if (blink_changed()) { + if (countdown > 1) { + countdown--; + TERN_(STATUS_MESSAGE_SCROLLING, draw_status_message()); + } + else if (countdown > 0) { + if (position_changed()) { + countdown--; + forceUpdate = true; + } + TERN_(STATUS_MESSAGE_SCROLLING, draw_status_message()); + } + } + + if (countdown == 0 && (forceUpdate || position_changed() || TERN(DISABLE_REDUCED_ACCURACY_WARNING, 0, blink_changed()))) + draw_position(current_position, TERN(DISABLE_REDUCED_ACCURACY_WARNING, 1, all_axes_trusted())); + #endif +} + +void ST7920_Lite_Status_Screen::update_progress(const bool forceUpdate) { + #if EITHER(LCD_SET_PROGRESS_MANUALLY, SDSUPPORT) + + // Since the progress bar involves writing + // quite a few bytes to GDRAM, only do this + // when an update is actually necessary. + + static uint8_t last_progress = 0; + const uint8_t progress = ui.get_progress_percent(); + if (forceUpdate || last_progress != progress) { + last_progress = progress; + draw_progress_bar(progress); + } + + #else + + UNUSED(forceUpdate); + + #endif +} + +void ST7920_Lite_Status_Screen::update(const bool forceUpdate) { + cs(); + update_indicators(forceUpdate); + update_status_or_position(forceUpdate); + update_progress(forceUpdate); + ncs(); +} + +void ST7920_Lite_Status_Screen::reset_state_from_unknown() { + _extended_function_set(true, true); // Do it twice as only one bit + _extended_function_set(true, true); // get set at a time. + _scroll_or_addr_select(false); +} + +void ST7920_Lite_Status_Screen::on_entry() { + cs(); + reset_state_from_unknown(); + clear(); + clear_gdram(); + draw_static_elements(); + update(true); + ncs(); +} + +void ST7920_Lite_Status_Screen::on_exit() { + cs(); + clear(); + _extended_function_set(true, true); // Restore state to what u8g expects. + ncs(); +} + +// Called prior to the KILL screen to +// clear the screen, preventing a garbled display. +void ST7920_Lite_Status_Screen::clear_text_buffer() { + cs(); + reset_state_from_unknown(); + clear(); + _extended_function_set(true, true); // Restore state to what u8g expects. + ncs(); +} + +void MarlinUI::draw_status_screen() { + ST7920_Lite_Status_Screen::update(false); +} + +// This method is called before each screen update and +// fires on_entry() and on_exit() events upon entering +// or exiting the Status Screen. +void MarlinUI::lcd_in_status(const bool inStatus) { + static bool lastInStatus = false; + if (lastInStatus == inStatus) return; + if ((lastInStatus = inStatus)) + ST7920_Lite_Status_Screen::on_entry(); + else + ST7920_Lite_Status_Screen::on_exit(); +} + +#endif // LIGHTWEIGHT_UI diff --git a/src/lcd/dogm/status_screen_lite_ST7920.h b/src/lcd/dogm/status_screen_lite_ST7920.h new file mode 100644 index 0000000..7fe8783 --- /dev/null +++ b/src/lcd/dogm/status_screen_lite_ST7920.h @@ -0,0 +1,106 @@ +/** + * Lightweight Status Screen for the RepRapDiscount Full + * Graphics Smart Controller (ST7920-based 128x64 LCD) + * + * (c) 2017 Aleph Objects, Inc. + * + * The code in this page is free software: you can + * redistribute it and/or modify it under the terms of the GNU + * General Public License (GNU GPL) as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. The code is distributed WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. + */ +#pragma once + +#include "../../HAL/shared/HAL_ST7920.h" + +#include "../../core/types.h" +#include "../../core/macros.h" +#include "../../libs/duration_t.h" + +class ST7920_Lite_Status_Screen { + private: + static struct st7920_state_t { + uint8_t synced : 1; // Whether a sync has been sent + uint8_t cmd : 1; // Whether the sync was cmd or data + uint8_t extended : 1; + uint8_t graphics : 1; + uint8_t sa : 1; + } current_bits; + + static void cs() { ST7920_cs(); current_bits.synced = false; } + static void ncs() { ST7920_cs(); current_bits.synced = false; } + static void sync_cmd() { ST7920_set_cmd(); } + static void sync_dat() { ST7920_set_dat(); } + static void write_byte(const uint8_t w) { ST7920_write_byte(w); } + + FORCE_INLINE static void write_word(const uint16_t w) { + write_byte((w >> 8) & 0xFF); + write_byte((w >> 0) & 0xFF); + } + + static void cmd(const uint8_t cmd); + static void begin_data(); + + static void write_str(const char *str); + static void write_str(const char *str, const uint8_t len); + static void write_str(FSTR_P const fstr); + static void write_number(const int16_t value, const uint8_t digits=3); + + static void _extended_function_set(const bool extended, const bool graphics); + static void _scroll_or_addr_select(const bool sa); + static void reset_state_from_unknown(); + + static void home(); + static void display_status(const bool display_on, const bool cursor_on, const bool blink_on); + static void extended_function_set(const bool extended); + static void graphics(const bool graphics); + static void entry_mode_select(const bool ac_increase, const bool shift); + static void scroll_or_addr_select(const bool sa); + static void set_ddram_address(const uint8_t addr); + static void set_cgram_address(const uint8_t addr); + static void set_gdram_address(const uint8_t x, const uint8_t y); + + static void clear(); + static void clear_ddram(); + static void clear_gdram(); + + static void load_cgram_icon(const uint16_t addr, const void *data); + static void draw_gdram_icon(uint8_t x, uint8_t y, const void *data); + + static uint8_t string_checksum(const char *str); + + protected: + static void draw_degree_symbol(uint8_t x, uint8_t y, const bool draw); + static void draw_static_elements(); + static void draw_progress_bar(const uint8_t value); + static void draw_fan_icon(const bool whichIcon); + static void draw_heat_icon(const bool whichIcon, const bool heating); + static void draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange); + static void draw_extruder_1_temp(const int16_t temp, const int16_t target, bool forceUpdate=false); + static void draw_extruder_2_temp(const int16_t temp, const int16_t target, bool forceUpdate=false); + static void draw_bed_temp(const int16_t temp, const int16_t target, bool forceUpdate=false); + static void draw_fan_speed(const uint8_t value); + static void draw_print_time(const duration_t &elapsed, char suffix=' '); + static void draw_feedrate_percentage(const uint16_t percentage); + static void draw_status_message(); + static void draw_position(const xyze_pos_t &pos, bool position_known=true); + + static bool indicators_changed(); + static bool position_changed(); + static bool blink_changed(); + static bool status_changed(); + + static void update_indicators(const bool forceUpdate); + static void update_position(const bool forceUpdate, bool resetChecksum); + static void update_status_or_position(bool forceUpdate); + static void update_progress(const bool forceUpdate); + + public: + static void update(const bool forceUpdate); + static void on_entry(); + static void on_exit(); + static void clear_text_buffer(); +}; diff --git a/src/lcd/dogm/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp b/src/lcd/dogm/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp new file mode 100644 index 0000000..b3e579e --- /dev/null +++ b/src/lcd/dogm/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp @@ -0,0 +1,302 @@ +/** + * 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 . + * + */ + +/** + * Based on u8g_dev_ssd1306_128x64.c + * + * Universal 8bit Graphics Library + * + * Copyright (c) 2015, olikraus@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * These routines are meant for two wire I2C interfaces. + * + * Three and four wire I2C interfaces have an A0 line. That line is + * used to switch between command and data modes. + * + * The two wire LCDs use an instruction byte to signal if data or + * command info is to follow. The command stream needs the instruction + * byte between eack command byte. The data stream needs one at the + * beginning. + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB + +#include "HAL_LCD_com_defines.h" + +#define WIDTH 128 +#define HEIGHT 64 +#define PAGE_HEIGHT 8 + +uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq); + +// The sh1106 is compatible to the ssd1306, but is 132x64. 128x64 display area is centered within +// the 132x64. + +static const uint8_t u8g_dev_sh1106_128x64_data_start_2_wire[] PROGMEM = { + 0x010, // set upper 4 bit of the col adr to 0 + 0x002, // set lower 4 bit of the col adr to 2 (centered display with ssd1306) + U8G_ESC_END // end of sequence +}; + +#define SH1106_PAGE_ADR(N) (0x20), (N) +#define SH1106_COLUMN_RANGE(N) (0x21), (((N) >> 8) & 0xFF), ((N) & 0xFF) +#define SH1106_PAGE_RANGE(N,O) (0x22), (N), (O) +#define SH1106_SCROLL(N) ((N) ? 0x2F : 0x2E) +#define SH1106_START_LINE(N) (0x40 | (N)) +#define SH1106_CONTRAST(N) (0x81), (N) +#define SH1106_CHARGE_PUMP(N) (0x8D), ((N) ? 0x14 : 0x10) +#define SH1106_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) +#define SH1106_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) +#define SH1106_INVERTED(N) ((N) ? 0xA7 : 0xA6) +#define SH1106_MUX_RATIO(N) (0xA8), (N) +#define SH1106_ON(N) ((N) ? 0xAF : 0xAE) +#define SH1106_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) +#define SH1106_DISP_OFFS(N) (0xD3), (N) +#define SH1106_OSC_FREQ(R,F) (0xD5), ((F) << 4 | (R)) +#define SH1106_CHARGE_PER(P,D) (0xD9), ((D) << 4 | (P)) +#define SH1106_COM_CONFIG(N) (0xDA), ((N) ? 0x12 : 0x02) +#define SH1106_VCOM_DESEL(N) (0xDB), (N) +#define SH1106_NOOP() (0xE3) + +static const uint8_t u8g_dev_sh1106_128x64_init_seq_2_wire[] PROGMEM = { + U8G_ESC_ADR(0), // Initiate command mode + SH1106_ON(0), // Display off, sleep mode + SH1106_MUX_RATIO(0x3F), // Mux ratio + SH1106_DISP_OFFS(0), // Display offset + SH1106_START_LINE(0), // Start line + SH1106_ADC_REVERSE(1), // Segment remap A0/A1 + SH1106_OUT_MODE(1), // C0: scan dir normal, C8: reverse + SH1106_COM_CONFIG(1), // Com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + SH1106_CONTRAST(0xCF), // [2] set contrast control + SH1106_PAGE_ADR(0x02), // 2012-05-27: page addressing mode + SH1106_COLUMN_RANGE(0x281), // Set column range from 0 through 131 + SH1106_PAGE_RANGE(0, 7), // Set page range from 0 through 7 + SH1106_CHARGE_PER(0x1, 0xF), // [2] pre-charge period 0x22/F1 + SH1106_VCOM_DESEL(0x40), // Vcomh deselect level + SH1106_ALL_PIX(0), // Output ram to display + SH1106_INVERTED(0), // Normal display mode + SH1106_OSC_FREQ(0, 8), // Clock divide ratio (0:1) and oscillator frequency (8) + SH1106_CHARGE_PUMP(1), // [2] charge pump setting (P62): 0x14 enable, 0x10 disable + SH1106_SCROLL(0), // 2012-05-27: Deactivate scroll + SH1106_ON(1), // Display on + U8G_ESC_END // End of sequence +}; + +uint8_t u8g_dev_sh1106_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_init_seq_2_wire); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_SetAddress(u8g, dev, 0); // instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2)); // select current page + u8g_SetAddress(u8g, dev, 1); // data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf); + u8g_SetChipSelect(u8g, dev, 0); + u8g_SetAddress(u8g, dev, 0); // instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2+1)); // select current page + u8g_SetAddress(u8g, dev, 1); // data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); + u8g_SetChipSelect(u8g, dev, 0); + } + break; + case U8G_DEV_MSG_SLEEP_ON: + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + return 1; + } + return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg); +} + +uint8_t u8g_dev_sh1106_128x64_2x_i2c_2_wire_buf[WIDTH*2] U8G_NOCOMMON ; +u8g_pb_t u8g_dev_sh1106_128x64_2x_i2c_2_wire_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_sh1106_128x64_2x_i2c_2_wire_buf}; +u8g_dev_t u8g_dev_sh1106_128x64_2x_i2c_2_wire = { u8g_dev_sh1106_128x64_2x_2_wire_fn, &u8g_dev_sh1106_128x64_2x_i2c_2_wire_pb, U8G_COM_SSD_I2C_HAL }; + +///////////////////////////////////////////////////////////////////////////////////////////// + +static const uint8_t u8g_dev_ssd1306_128x64_data_start_2_wire[] PROGMEM = { + 0x010, // set upper 4 bit of the col adr to 0 + 0x000, // set lower 4 bit of the col adr to 0 + U8G_ESC_END // end of sequence +}; + +static const uint8_t u8g_dev_ssd1306_128x64_init_seq_2_wire[] PROGMEM = { + U8G_ESC_ADR(0), // initiate command mode + 0x0AE, // display off, sleep mode + 0x0A8, 0x03F, // mux ratio + 0x0D3, 0x00, // display offset + 0x040, // start line + 0x0A1, // segment remap a0/a1 + 0x0C8, // c0: scan dir normal, c8: reverse + 0x0DA, 0x012, // com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + 0x081, 0x0CF, // [2] set contrast control + 0x020, 0x002, // 2012-05-27: page addressing mode + 0x21, 0, 0x7F, // set column range from 0 through 127 + 0x22, 0, 7, // set page range from 0 through 7 + 0x0D9, 0x0F1, // [2] pre-charge period 0x022/f1 + 0x0DB, 0x040, // vcomh deselect level + 0x0A4, // output ram to display + 0x0A6, // none inverted normal display mode + 0x0D5, 0x080, // clock divide ratio (0x00=1) and oscillator frequency (0x8) + 0x08D, 0x014, // [2] charge pump setting (p62): 0x014 enable, 0x010 disable + 0x02E, // 2012-05-27: Deactivate scroll + 0x0AF, // display on + U8G_ESC_END // end of sequence +}; + +uint8_t u8g_dev_ssd1306_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_init_seq_2_wire); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_SetAddress(u8g, dev, 0); // instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2)); // select current page + u8g_SetAddress(u8g, dev, 1); // data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf); + u8g_SetChipSelect(u8g, dev, 0); + u8g_SetAddress(u8g, dev, 0); // instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2+1)); // select current page + u8g_SetAddress(u8g, dev, 1); // data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); + u8g_SetChipSelect(u8g, dev, 0); + } + break; + case U8G_DEV_MSG_SLEEP_ON: + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + return 1; + } + return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg); +} + + +uint8_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire_buf[WIDTH*2] U8G_NOCOMMON ; +u8g_pb_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_ssd1306_128x64_2x_i2c_2_wire_buf}; +u8g_dev_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire = { u8g_dev_ssd1306_128x64_2x_2_wire_fn, &u8g_dev_ssd1306_128x64_2x_i2c_2_wire_pb, U8G_COM_SSD_I2C_HAL }; + + +///////////////////////////////////////////////////////////////////////////////////////////// + +// This routine adds the instruction byte in between the command bytes. This makes the init +// sequences a lot easier to read. + +#define I2C_CMD_MODE 0x080 + +uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) { + uint8_t is_escape = 0; + for (;;) { + uint8_t value = u8g_pgm_read(esc_seq); + if (is_escape == 0) { + if (value != 255) { + if (u8g_WriteByte(u8g, dev, value) == 0 ) + return 0; + if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0 ) + return 0; + } + else { + is_escape = 1; + } + } + else { + if (value == 255) { + if (u8g_WriteByte(u8g, dev, value) == 0 ) + return 0; + if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0 ) + return 0; + } + else if (value == 254) { + break; + } + else if (value >= 0x0F0) { + /* not yet used, do nothing */ + } + else if (value >= 0xE0 ) { + u8g_SetAddress(u8g, dev, value & 0x0F); + } + else if (value >= 0xD0) { + u8g_SetChipSelect(u8g, dev, value & 0x0F); + } + else if (value >= 0xC0) { + u8g_SetResetLow(u8g, dev); + value &= 0x0F; + value <<= 4; + value+=2; + u8g_Delay(value); + u8g_SetResetHigh(u8g, dev); + u8g_Delay(value); + } + else if (value >= 0xBE) { /* not yet implemented */ + /* u8g_SetVCC(u8g, dev, value & 0x01); */ + } + else if (value <= 127) { + u8g_Delay(value); + } + is_escape = 0; + } + esc_seq++; + } + return 1; +} + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/u8g_dev_ssd1309_12864.cpp b/src/lcd/dogm/u8g_dev_ssd1309_12864.cpp new file mode 100644 index 0000000..6d40ea0 --- /dev/null +++ b/src/lcd/dogm/u8g_dev_ssd1309_12864.cpp @@ -0,0 +1,129 @@ +/** + * 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_MARLINUI_U8GLIB + +#include "HAL_LCD_com_defines.h" +#include + +#define WIDTH 128 +#define HEIGHT 64 +#define PAGE_HEIGHT 8 + +// SSD1309 init sequence +static const uint8_t u8g_dev_ssd1309_128x64_init_seq[] PROGMEM = { + U8G_ESC_CS(0), // Disable chip + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_RST(1), // Do reset low pulse with (1*16)+2 milliseconds + U8G_ESC_CS(1), // Enable chip + + 0xFD,0x12, // Command Lock + 0xAE, // Set Display Off + 0xD5,0xA0, // Set Display Clock Divide Ratio/Oscillator Frequency + 0xA8,0x3F, // Set Multiplex Ratio + 0x3D,0x00, // Set Display Offset + 0x40, // Set Display Start Line + 0xA1, // Set Segment Re-Map + 0xC8, // Set COM Output Scan Direction + 0xDA,0x12, // Set COM Pins Hardware Configuration + 0x81,0xDF, // Set Current Control + 0xD9,0x82, // Set Pre-Charge Period + 0xDB,0x34, // Set VCOMH Deselect Level + 0xA4, // Set Entire Display On/Off + 0xA6, // Set Normal/Inverse Display + U8G_ESC_VCC(1), // Power up VCC & Stabilized + U8G_ESC_DLY(50), + 0xAF, // Set Display On + U8G_ESC_DLY(50), + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +// Select one init sequence here +#define u8g_dev_ssd1309_128x64_init_seq u8g_dev_ssd1309_128x64_init_seq + +static const uint8_t u8g_dev_ssd1309_128x64_data_start[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + 0x010, // Set upper 4 bit of the col adr to 0 + 0x000, // Set lower 4 bit of the col adr to 4 + U8G_ESC_END // End of sequence +}; + +static const uint8_t u8g_dev_ssd13xx_sleep_on[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + 0x0AE, // Display off + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +static const uint8_t u8g_dev_ssd13xx_sleep_off[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + 0x0AF, // Display on + U8G_ESC_DLY(50), // Delay 50 ms + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +uint8_t u8g_dev_ssd1309_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1309_128x64_init_seq); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1309_128x64_data_start); + u8g_WriteByte(u8g, dev, 0x0B0 | pb->p.page); // Select current page (SSD1306) + u8g_SetAddress(u8g, dev, 1); // Data mode + if (u8g_pb_WriteBuffer(pb, u8g, dev) == 0) return 0; + u8g_SetChipSelect(u8g, dev, 0); + } + break; + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteByte(u8g, dev, 0x081); + u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) ); // 11 Jul 2015: fixed contrast calculation + u8g_SetChipSelect(u8g, dev, 0); + return 1; + case U8G_DEV_MSG_SLEEP_ON: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd13xx_sleep_on); + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd13xx_sleep_off); + return 1; + } + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); +} + +uint8_t u8g_dev_ssd1309_buf[WIDTH*2] U8G_NOCOMMON ; +u8g_pb_t u8g_dev_ssd1309_pb = { {8, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_ssd1309_buf}; +u8g_dev_t u8g_dev_ssd1309_sw_spi = { u8g_dev_ssd1309_128x64_fn, &u8g_dev_ssd1309_pb, U8G_COM_HAL_SW_SPI_FN }; + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/u8g_dev_st7565_64128n_HAL.cpp b/src/lcd/dogm/u8g_dev_st7565_64128n_HAL.cpp new file mode 100644 index 0000000..63e7b2e --- /dev/null +++ b/src/lcd/dogm/u8g_dev_st7565_64128n_HAL.cpp @@ -0,0 +1,241 @@ +/** + * 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 . + * + */ + +/** + * Based on u8g_dev_st7565_64128n_HAL.c (Displaytech) + * + * Universal 8bit Graphics Library + * + * Copyright (c) 2011, olikraus@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../../inc/MarlinConfig.h" + +#if HAS_MARLINUI_U8GLIB + +#include +#include "HAL_LCD_com_defines.h" + +#define WIDTH 128 +#define HEIGHT 64 +#define PAGE_HEIGHT 8 +#ifndef ST7565_XOFFSET + #define ST7565_XOFFSET 0x00 +#endif + +#define ST7565_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) +#define ST7565_BIAS_MODE(N) ((N) ? 0xA3 : 0xA2) +#define ST7565_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) +#define ST7565_INVERTED(N) ((N) ? 0xA7 : 0xA6) +#define ST7565_ON(N) ((N) ? 0xAF : 0xAE) +#define ST7565_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) +#define ST7565_POWER_CONTROL(N) (0x28 | (N)) +#define ST7565_V5_RATIO(N) (0x20 | ((N) & 0x7)) +#define ST7565_CONTRAST(N) (0x81), (N) + +#define ST7565_COLUMN_ADR(N) (0x10 | (((N) >> 4) & 0xF)), ((N) & 0xF) +#define ST7565_PAGE_ADR(N) (0xB0 | (N)) +#define ST7565_START_LINE(N) (0x40 | (N)) +#define ST7565_SLEEP_MODE() (0xAC) // ,(N) needed? +#define ST7565_NOOP() (0xE3) + +/* init sequence from https://github.com/adafruit/ST7565-LCD/blob/master/ST7565/ST7565.cpp */ +static const uint8_t u8g_dev_st7565_64128n_HAL_init_seq[] PROGMEM = { + U8G_ESC_CS(0), // disable chip + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_CS(1), // enable chip + U8G_ESC_RST(15), // do reset low pulse with (15*16)+2 milliseconds (=maximum delay)*/ + + ST7565_BIAS_MODE(0), // 0xA2: LCD bias 1/9 (according to Displaytech 64128N datasheet) + ST7565_ADC_REVERSE(0), // Normal ADC Select (according to Displaytech 64128N datasheet) + + ST7565_OUT_MODE(1), // common output mode: set scan direction + ST7565_START_LINE(0), // Display start line for Displaytech 64128N + + ST7565_POWER_CONTROL(0x4), // power control: turn on voltage converter + U8G_ESC_DLY(50), // delay 50 ms + + ST7565_POWER_CONTROL(0x6), // power control: turn on voltage regulator + U8G_ESC_DLY(50), // delay 50 ms + + ST7565_POWER_CONTROL(0x7), // power control: turn on voltage follower + U8G_ESC_DLY(50), // delay 50 ms + + #ifdef ST7565_VOLTAGE_DIVIDER_VALUE + // Set V5 voltage resistor ratio. Affects brightness of Displaytech 64128N + ST7565_V5_RATIO(ST7565_VOLTAGE_DIVIDER_VALUE), + #endif + + ST7565_INVERTED(0), // display normal, bit val 0: LCD pixel off. + + ST7565_CONTRAST(0x1E), // Contrast value for Displaytech 64128N + + ST7565_ON(1), // display on + + U8G_ESC_DLY(100), // delay 100 ms + ST7565_ALL_PIX(1), // display all points, ST7565 + U8G_ESC_DLY(100), // delay 100 ms + U8G_ESC_DLY(100), // delay 100 ms + ST7565_ALL_PIX(0), // normal display + U8G_ESC_CS(0), // disable chip + U8G_ESC_END // end of sequence +}; + +static const uint8_t u8g_dev_st7565_64128n_HAL_data_start[] PROGMEM = { + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_CS(1), // enable chip + ST7565_COLUMN_ADR(ST7565_XOFFSET), // high 4 bits to 0, low 4 bits to 0. Changed for DisplayTech 64128N + U8G_ESC_END // end of sequence +}; + +static const uint8_t u8g_dev_st7565_64128n_HAL_sleep_on[] PROGMEM = { + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_CS(1), // enable chip + ST7565_SLEEP_MODE(), // static indicator off + //0x00, // indicator register set (not sure if this is required) + ST7565_ON(0), // display off + ST7565_ALL_PIX(1), // all points on + U8G_ESC_CS(0), // disable chip, bugfix 12 nov 2014 + U8G_ESC_END // end of sequence + }; + +static const uint8_t u8g_dev_st7565_64128n_HAL_sleep_off[] PROGMEM = { + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_CS(1), // enable chip + ST7565_ALL_PIX(0), // all points off + ST7565_ON(1), // display on + U8G_ESC_DLY(50), // delay 50 ms + U8G_ESC_CS(0), // disable chip, bugfix 12 nov 2014 + U8G_ESC_END // end of sequence +}; + +uint8_t u8g_dev_st7565_64128n_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_init_seq); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_data_start); + u8g_WriteByte(u8g, dev, ST7565_PAGE_ADR(pb->p.page)); /* select current page (ST7565R) */ + u8g_SetAddress(u8g, dev, 1); /* data mode */ + if (!u8g_pb_WriteBuffer(pb, u8g, dev)) return 0; + u8g_SetChipSelect(u8g, dev, 0); + } + break; + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); /* instruction mode */ + u8g_WriteByte(u8g, dev, 0x81); + u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 2); + u8g_SetChipSelect(u8g, dev, 0); + return 1; + case U8G_DEV_MSG_SLEEP_ON: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_sleep_on); + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_sleep_off); + return 1; + } + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); +} + +uint8_t u8g_dev_st7565_64128n_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_init_seq); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_data_start); + u8g_WriteByte(u8g, dev, ST7565_PAGE_ADR(2 * pb->p.page)); /* select current page (ST7565R) */ + u8g_SetAddress(u8g, dev, 1); /* data mode */ + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)pb->buf); + u8g_SetChipSelect(u8g, dev, 0); + + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_data_start); + u8g_WriteByte(u8g, dev, ST7565_PAGE_ADR(2 * pb->p.page + 1)); /* select current page (ST7565R) */ + u8g_SetAddress(u8g, dev, 1); /* data mode */ + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); + u8g_SetChipSelect(u8g, dev, 0); + } + break; + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); /* instruction mode */ + u8g_WriteByte(u8g, dev, 0x81); + u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 2); + u8g_SetChipSelect(u8g, dev, 0); + return 1; + case U8G_DEV_MSG_SLEEP_ON: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_sleep_on); + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_sleep_off); + return 1; + } + return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg); +} + +U8G_PB_DEV(u8g_dev_st7565_64128n_HAL_sw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_st7565_64128n_HAL_fn, U8G_COM_HAL_SW_SPI_FN); + +uint8_t u8g_dev_st7565_64128n_HAL_2x_buf[WIDTH*2] U8G_NOCOMMON ; +u8g_pb_t u8g_dev_st7565_64128n_HAL_2x_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_st7565_64128n_HAL_2x_buf}; +u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_sw_spi = { u8g_dev_st7565_64128n_HAL_2x_fn, &u8g_dev_st7565_64128n_HAL_2x_pb, U8G_COM_HAL_SW_SPI_FN }; + + +U8G_PB_DEV(u8g_dev_st7565_64128n_HAL_hw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_st7565_64128n_HAL_fn, U8G_COM_HAL_HW_SPI_FN); +u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_hw_spi = { u8g_dev_st7565_64128n_HAL_2x_fn, &u8g_dev_st7565_64128n_HAL_2x_pb, U8G_COM_HAL_HW_SPI_FN }; + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/u8g_dev_st7920_128x64_HAL.cpp b/src/lcd/dogm/u8g_dev_st7920_128x64_HAL.cpp new file mode 100644 index 0000000..fde6e41 --- /dev/null +++ b/src/lcd/dogm/u8g_dev_st7920_128x64_HAL.cpp @@ -0,0 +1,208 @@ +/** + * 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 . + * + */ + +/** + * Based on u8g_dev_st7920_128x64.c + * + * Universal 8bit Graphics Library + * + * Copyright (c) 2011, olikraus@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB && DISABLED(TFT_CLASSIC_UI) + +#include "HAL_LCD_com_defines.h" + +#define PAGE_HEIGHT 8 + +/* init sequence from https://github.com/adafruit/ST7565-LCD/blob/master/ST7565/ST7565.cpp */ +static const uint8_t u8g_dev_st7920_128x64_HAL_init_seq[] PROGMEM = { + U8G_ESC_CS(0), // disable chip + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_RST(15), // do reset low pulse with (15*16)+2 milliseconds (=maximum delay) + U8G_ESC_DLY(100), // 8 Dez 2012: additional delay 100 ms because of reset + U8G_ESC_CS(1), // enable chip + U8G_ESC_DLY(50), // delay 50 ms + + 0x038, // 8 Bit interface (DL=1), basic instruction set (RE=0) + 0x00C, // display on, cursor & blink off; 0x08: all off + 0x006, // Entry mode: Cursor move to right, DDRAM address counter (AC) plus 1, no shift + 0x002, // disable scroll, enable CGRAM address + 0x001, // clear RAM, needs 1.6 ms + U8G_ESC_DLY(100), // delay 100 ms + + U8G_ESC_CS(0), // disable chip + U8G_ESC_END // end of sequence +}; + +void clear_graphics_DRAM(u8g_t *u8g, u8g_dev_t *dev) { + u8g_SetChipSelect(u8g, dev, 1); + u8g_Delay(1); + u8g_SetAddress(u8g, dev, 0); // cmd mode + u8g_WriteByte(u8g, dev, 0x08); //display off, cursor+blink off + u8g_WriteByte(u8g, dev, 0x3E); //extended mode + GDRAM active + LOOP_L_N(y, (LCD_PIXEL_HEIGHT) / 2) { //clear GDRAM + u8g_WriteByte(u8g, dev, 0x80 | y); //set y + u8g_WriteByte(u8g, dev, 0x80); //set x = 0 + u8g_SetAddress(u8g, dev, 1); /* data mode */ + LOOP_L_N(i, 2 * (LCD_PIXEL_WIDTH) / 8) //2x width clears both segments + u8g_WriteByte(u8g, dev, 0); + u8g_SetAddress(u8g, dev, 0); /* cmd mode */ + } + + u8g_WriteByte(u8g, dev, 0x0C); //display on, cursor+blink off + + u8g_SetChipSelect(u8g, dev, 0); +} + +uint8_t u8g_dev_st7920_128x64_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7920_128x64_HAL_init_seq); + clear_graphics_DRAM(u8g, dev); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + uint8_t y, i; + uint8_t *ptr; + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + + u8g_SetAddress(u8g, dev, 0); /* cmd mode */ + u8g_SetChipSelect(u8g, dev, 1); + y = pb->p.page_y0; + ptr = (uint8_t *)pb->buf; + for (i = 0; i < 8; i ++) { + u8g_SetAddress(u8g, dev, 0); /* cmd mode */ + u8g_WriteByte(u8g, dev, 0x03E ); /* enable extended mode */ + + if (y < 32) { + u8g_WriteByte(u8g, dev, 0x080 | y ); /* y pos */ + u8g_WriteByte(u8g, dev, 0x080 ); /* set x pos to 0*/ + } + else { + u8g_WriteByte(u8g, dev, 0x080 | (y-32) ); /* y pos */ + u8g_WriteByte(u8g, dev, 0x080 | 8); /* set x pos to 64*/ + } + + u8g_SetAddress(u8g, dev, 1); /* data mode */ + u8g_WriteSequence(u8g, dev, (LCD_PIXEL_WIDTH) / 8, ptr); + ptr += (LCD_PIXEL_WIDTH) / 8; + y++; + } + u8g_SetChipSelect(u8g, dev, 0); + } + break; + } + return u8g_dev_pb8h1_base_fn(u8g, dev, msg, arg); +} + +uint8_t u8g_dev_st7920_128x64_HAL_4x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7920_128x64_HAL_init_seq); + clear_graphics_DRAM(u8g, dev); + break; + + case U8G_DEV_MSG_STOP: + break; + + case U8G_DEV_MSG_PAGE_NEXT: { + uint8_t y, i; + uint8_t *ptr; + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + + u8g_SetAddress(u8g, dev, 0); /* cmd mode */ + u8g_SetChipSelect(u8g, dev, 1); + y = pb->p.page_y0; + ptr = (uint8_t *)pb->buf; + for (i = 0; i < 32; i ++) { + u8g_SetAddress(u8g, dev, 0); /* cmd mode */ + u8g_WriteByte(u8g, dev, 0x03E ); /* enable extended mode */ + + if (y < 32) { + u8g_WriteByte(u8g, dev, 0x080 | y ); /* y pos */ + u8g_WriteByte(u8g, dev, 0x080 ); /* set x pos to 0*/ + } + else { + u8g_WriteByte(u8g, dev, 0x080 | (y-32) ); /* y pos */ + u8g_WriteByte(u8g, dev, 0x080 | 8); /* set x pos to 64*/ + } + + u8g_SetAddress(u8g, dev, 1); /* data mode */ + u8g_WriteSequence(u8g, dev, (LCD_PIXEL_WIDTH) / 8, ptr); + ptr += (LCD_PIXEL_WIDTH) / 8; + y++; + } + u8g_SetChipSelect(u8g, dev, 0); + } + break; + } + return u8g_dev_pb32h1_base_fn(u8g, dev, msg, arg); +} + +U8G_PB_DEV(u8g_dev_st7920_128x64_HAL_sw_spi, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, PAGE_HEIGHT, u8g_dev_st7920_128x64_HAL_fn, U8G_COM_ST7920_HAL_SW_SPI); + +#define QWIDTH ((LCD_PIXEL_WIDTH) * 4) +uint8_t u8g_dev_st7920_128x64_HAL_4x_buf[QWIDTH] U8G_NOCOMMON ; +u8g_pb_t u8g_dev_st7920_128x64_HAL_4x_pb = { { 32, LCD_PIXEL_HEIGHT, 0, 0, 0 }, LCD_PIXEL_WIDTH, u8g_dev_st7920_128x64_HAL_4x_buf}; +u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_sw_spi = { u8g_dev_st7920_128x64_HAL_4x_fn, &u8g_dev_st7920_128x64_HAL_4x_pb, U8G_COM_ST7920_HAL_SW_SPI }; + +U8G_PB_DEV(u8g_dev_st7920_128x64_HAL_hw_spi, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, PAGE_HEIGHT, u8g_dev_st7920_128x64_HAL_fn, U8G_COM_ST7920_HAL_HW_SPI); +u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_hw_spi = { u8g_dev_st7920_128x64_HAL_4x_fn, &u8g_dev_st7920_128x64_HAL_4x_pb, U8G_COM_ST7920_HAL_HW_SPI }; + +#if NONE(__AVR__, ARDUINO_ARCH_STM32, ARDUINO_ARCH_ESP32) || defined(U8G_HAL_LINKS) + // Also use this device for HAL version of rrd class. This results in the same device being used + // for the ST7920 for HAL systems no matter what is selected in marlinui_DOGM.h. + u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi = { u8g_dev_st7920_128x64_HAL_4x_fn, &u8g_dev_st7920_128x64_HAL_4x_pb, U8G_COM_ST7920_HAL_SW_SPI }; +#endif + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/u8g_dev_tft_upscale_from_128x64.cpp b/src/lcd/dogm/u8g_dev_tft_upscale_from_128x64.cpp new file mode 100644 index 0000000..f1bf9d0 --- /dev/null +++ b/src/lcd/dogm/u8g_dev_tft_upscale_from_128x64.cpp @@ -0,0 +1,559 @@ +/** + * 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 . + * + */ + +/** + * u8g_dev_tft_320x240_upscale_from_128x64.cpp + * + * Universal 8bit Graphics Library + * + * Copyright (c) 2011, olikraus@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../../inc/MarlinConfig.h" + +#if HAS_MARLINUI_U8GLIB && (PIN_EXISTS(FSMC_CS) || HAS_SPI_GRAPHICAL_TFT || HAS_LTDC_GRAPHICAL_TFT) + +#include "HAL_LCD_com_defines.h" +#include "marlinui_DOGM.h" + +#include + +#if ANY(LCD_USE_DMA_FSMC, LCD_USE_DMA_SPI, HAS_LTDC_GRAPHICAL_TFT) + #define HAS_LCD_IO 1 +#endif + +#include "../tft_io/tft_io.h" +TFT_IO tftio; + +#define WIDTH LCD_PIXEL_WIDTH +#define HEIGHT LCD_PIXEL_HEIGHT +#define PAGE_HEIGHT 8 + +#if ENABLED(TOUCH_SCREEN_CALIBRATION) + #include "../tft_io/touch_calibration.h" + #include "../marlinui.h" +#endif + +#if HAS_TOUCH_BUTTONS && HAS_TOUCH_SLEEP + #define HAS_TOUCH_BUTTONS_SLEEP 1 +#endif + +#include "../touch/touch_buttons.h" +#include "../scaled_tft.h" + +#define X_HI (UPSCALE(TFT_PIXEL_OFFSET_X, WIDTH) - 1) +#define Y_HI (UPSCALE(TFT_PIXEL_OFFSET_Y, HEIGHT) - 1) + +// 16 bit color generator: https://ee-programming-notepad.blogspot.com/2016/10/16-bit-color-generator-picker.html +// RGB565 color picker: https://trolsoft.ru/en/articles/rgb565-color-picker + +#define COLOR_BLACK 0x0000 // #000000 +#define COLOR_WHITE 0xFFFF // #FFFFFF +#define COLOR_SILVER 0xC618 // #C0C0C0 +#define COLOR_GREY 0x7BEF // #808080 +#define COLOR_DARKGREY 0x4208 // #404040 +#define COLOR_DARKGREY2 0x39E7 // #303030 +#define COLOR_DARK 0x0003 // #000019 + +#define COLOR_RED 0xF800 // #FF0000 +#define COLOR_LIME 0x7E00 // #00FF00 +#define COLOR_BLUE 0x001F // #0000FF +#define COLOR_YELLOW 0xFFE0 // #FFFF00 +#define COLOR_MAGENTA 0xF81F // #FF00FF +#define COLOR_FUCHSIA 0xF81F // #FF00FF +#define COLOR_CYAN 0x07FF // #00FFFF +#define COLOR_AQUA 0x07FF // #00FFFF + +#define COLOR_MAROON 0x7800 // #800000 +#define COLOR_GREEN 0x03E0 // #008000 +#define COLOR_NAVY 0x000F // #000080 +#define COLOR_OLIVE 0x8400 // #808000 +#define COLOR_PURPLE 0x8010 // #800080 +#define COLOR_TEAL 0x0410 // #008080 + +#define COLOR_ORANGE 0xFC00 // #FF7F00 + +#ifndef TFT_MARLINUI_COLOR + #define TFT_MARLINUI_COLOR COLOR_WHITE +#endif +#ifndef TFT_MARLINBG_COLOR + #define TFT_MARLINBG_COLOR COLOR_BLACK +#endif +#ifndef TFT_DISABLED_COLOR + #define TFT_DISABLED_COLOR COLOR_DARK +#endif +#ifndef TFT_BTCANCEL_COLOR + #define TFT_BTCANCEL_COLOR COLOR_RED +#endif +#ifndef TFT_BTARROWS_COLOR + #define TFT_BTARROWS_COLOR COLOR_BLUE +#endif +#ifndef TFT_BTOKMENU_COLOR + #define TFT_BTOKMENU_COLOR COLOR_RED +#endif + +static void setWindow(u8g_t *u8g, u8g_dev_t *dev, uint16_t Xmin, uint16_t Ymin, uint16_t Xmax, uint16_t Ymax) { + tftio.set_window(Xmin, Ymin, Xmax, Ymax); +} + +#if HAS_TOUCH_BUTTONS + + static const uint8_t buttonD[] = { + B01111111,B11111111,B11111111,B11111110, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00011000,B00110000,B00000001, + B10000000,B00001100,B01100000,B00000001, + B10000000,B00000110,B11000000,B00000001, + B10000000,B00000011,B10000000,B00000001, + B10000000,B00000011,B10000000,B00000001, + B10000000,B00000110,B11000000,B00000001, + B10000000,B00001100,B01100000,B00000001, + B10000000,B00011000,B00110000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B01111111,B11111111,B11111111,B11111110, + }; + + #if ENABLED(REVERSE_MENU_DIRECTION) + + static const uint8_t buttonA[] = { + B01111111,B11111111,B11111111,B11111110, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00111111,B11100001, + B10000111,B11111100,B00111111,B11100001, + B10000011,B11111000,B00000000,B00000001, + B10000001,B11110000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B01000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B01111111,B11111111,B11111111,B11111110, + }; + static const uint8_t buttonB[] = { + B01111111,B11111111,B11111111,B11111110, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B01100000,B00000010,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00001111,B10000001, + B10000000,B01100000,B00011111,B11000001, + B10000111,B11111110,B00111111,B11100001, + B10000111,B11111110,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B01111111,B11111111,B11111111,B11111110, + }; + + #else + + static const uint8_t buttonA[] = { + B01111111,B11111111,B11111111,B11111110, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B01000000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000001,B11110000,B00000000,B00000001, + B10000011,B11111000,B00000000,B00000001, + B10000111,B11111100,B00111111,B11100001, + B10000000,B11100000,B00111111,B11100001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B11100000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B01111111,B11111111,B11111111,B11111110, + }; + + static const uint8_t buttonB[] = { + B01111111,B11111111,B11111111,B11111110, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000111,B00000001, + B10000111,B11111110,B00000111,B00000001, + B10000111,B11111110,B00111111,B11100001, + B10000000,B01100000,B00011111,B11000001, + B10000000,B01100000,B00001111,B10000001, + B10000000,B01100000,B00000111,B00000001, + B10000000,B01100000,B00000010,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B01111111,B11111111,B11111111,B11111110, + }; + + #endif + + static const uint8_t buttonC[] = { + B01111111,B11111111,B11111111,B11111110, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00011100,B00000001, + B10000000,B00000100,B00011100,B00000001, + B10000000,B00001100,B00011100,B00000001, + B10000000,B00011111,B11111100,B00000001, + B10000000,B00111111,B11111100,B00000001, + B10000000,B00011111,B11111100,B00000001, + B10000000,B00001100,B00000000,B00000001, + B10000000,B00000100,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B10000000,B00000000,B00000000,B00000001, + B01111111,B11111111,B11111111,B11111110, + }; + + void drawImage(const uint8_t *data, u8g_t *u8g, u8g_dev_t *dev, uint16_t length, uint16_t height, uint16_t color) { + uint16_t buffer[BUTTON_WIDTH * sq(GRAPHICAL_TFT_UPSCALE)]; + + if (length > BUTTON_WIDTH) return; + + for (uint16_t i = 0; i < height; i++) { + uint16_t k = 0; + for (uint16_t j = 0; j < length; j++) { + uint16_t v = TFT_MARLINBG_COLOR; + if (*(data + (i * (length >> 3) + (j >> 3))) & (0x80 >> (j & 7))) + v = color; + else + v = TFT_MARLINBG_COLOR; + LOOP_L_N(n, GRAPHICAL_TFT_UPSCALE) buffer[k++] = v; + } + #if HAS_LCD_IO + LOOP_S_L_N(n, 1, GRAPHICAL_TFT_UPSCALE) + for (uint16_t l = 0; l < UPSCALE0(length); l++) + buffer[l + n * UPSCALE0(length)] = buffer[l]; + + tftio.WriteSequence(buffer, length * sq(GRAPHICAL_TFT_UPSCALE)); + #else + for (uint8_t i = GRAPHICAL_TFT_UPSCALE; i--;) + u8g_WriteSequence(u8g, dev, k << 1, (uint8_t*)buffer); + #endif + } + } + +#endif // HAS_TOUCH_BUTTONS + +// Used to fill RGB565 (16bits) background +inline void memset2(const void *ptr, uint16_t fill, size_t cnt) { + uint16_t *wptr = (uint16_t*)ptr; + for (size_t i = 0; i < cnt; i += 2) { *wptr = fill; wptr++; } +} + +static bool preinit = true; +static uint8_t page; + +#if HAS_TOUCH_BUTTONS + + static bool redrawTouchButtons = true; + static void drawTouchButtons(u8g_t *u8g, u8g_dev_t *dev) { + if (!redrawTouchButtons) return; + redrawTouchButtons = false; + + // Bottom buttons + setWindow(u8g, dev, BUTTOND_X_LO, BUTTON_Y_LO, BUTTOND_X_HI, BUTTON_Y_HI); + drawImage(buttonD, u8g, dev, BUTTON_DRAW_WIDTH, BUTTON_DRAW_HEIGHT, TFT_BTCANCEL_COLOR); + + setWindow(u8g, dev, BUTTONA_X_LO, BUTTON_Y_LO, BUTTONA_X_HI, BUTTON_Y_HI); + drawImage(buttonA, u8g, dev, BUTTON_DRAW_WIDTH, BUTTON_DRAW_HEIGHT, TFT_BTARROWS_COLOR); + + setWindow(u8g, dev, BUTTONB_X_LO, BUTTON_Y_LO, BUTTONB_X_HI, BUTTON_Y_HI); + drawImage(buttonB, u8g, dev, BUTTON_DRAW_WIDTH, BUTTON_DRAW_HEIGHT, TFT_BTARROWS_COLOR); + + setWindow(u8g, dev, BUTTONC_X_LO, BUTTON_Y_LO, BUTTONC_X_HI, BUTTON_Y_HI); + drawImage(buttonC, u8g, dev, BUTTON_DRAW_WIDTH, BUTTON_DRAW_HEIGHT, TFT_BTOKMENU_COLOR); + } + +#endif // HAS_TOUCH_BUTTONS + +static void u8g_upscale_clear_lcd(u8g_t *u8g, u8g_dev_t *dev, uint16_t *buffer) { + setWindow(u8g, dev, 0, 0, (TFT_WIDTH) - 1, (TFT_HEIGHT) - 1); + #if HAS_LCD_IO + UNUSED(buffer); + tftio.WriteMultiple(TFT_MARLINBG_COLOR, (TFT_WIDTH) * (TFT_HEIGHT)); + #else + memset2(buffer, TFT_MARLINBG_COLOR, (TFT_WIDTH) / 2); + for (uint16_t i = 0; i < (TFT_HEIGHT) * sq(GRAPHICAL_TFT_UPSCALE); i++) + u8g_WriteSequence(u8g, dev, (TFT_WIDTH) / 2, (uint8_t *)buffer); + #endif +} + +static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT + +uint8_t u8g_dev_tft_320x240_upscale_from_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + + #if HAS_LCD_IO + static uint16_t bufferA[WIDTH * sq(GRAPHICAL_TFT_UPSCALE)], bufferB[WIDTH * sq(GRAPHICAL_TFT_UPSCALE)]; + uint16_t *buffer = &bufferA[0]; + #else + uint16_t buffer[WIDTH * GRAPHICAL_TFT_UPSCALE]; // 16-bit RGB 565 pixel line buffer + #endif + + switch (msg) { + case U8G_DEV_MSG_INIT: + dev->com_fn(u8g, U8G_COM_MSG_INIT, U8G_SPI_CLK_CYCLE_NONE, nullptr); + + if (preinit) { + preinit = false; + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); + } + + if (msgInitCount) return -1; + tftio.Init(); + tftio.InitTFT(); + TERN_(TOUCH_SCREEN_CALIBRATION, touch_calibration.calibration_reset()); + u8g_upscale_clear_lcd(u8g, dev, buffer); + return 0; + + case U8G_DEV_MSG_STOP: preinit = true; break; + + case U8G_DEV_MSG_PAGE_FIRST: { + page = 0; + #if HAS_TOUCH_BUTTONS_SLEEP + static bool sleepCleared; + if (touchBt.isSleeping()) { + if (!sleepCleared) { + sleepCleared = true; + u8g_upscale_clear_lcd(u8g, dev, buffer); + TERN_(HAS_TOUCH_BUTTONS, redrawTouchButtons = true); + } + break; + } + else + sleepCleared = false; + #endif + TERN_(HAS_TOUCH_BUTTONS, drawTouchButtons(u8g, dev)); + setWindow(u8g, dev, TFT_PIXEL_OFFSET_X, TFT_PIXEL_OFFSET_Y, X_HI, Y_HI); + } break; + + case U8G_DEV_MSG_PAGE_NEXT: + if (TERN0(HAS_TOUCH_BUTTONS_SLEEP, touchBt.isSleeping())) break; + if (++page > (HEIGHT / PAGE_HEIGHT)) return 1; + + LOOP_L_N(y, PAGE_HEIGHT) { + uint32_t k = 0; + TERN_(HAS_LCD_IO, buffer = (y & 1) ? bufferB : bufferA); + for (uint16_t i = 0; i < (uint32_t)pb->width; i++) { + const uint8_t b = *(((uint8_t *)pb->buf) + i); + const uint16_t c = TEST(b, y) ? TFT_MARLINUI_COLOR : TFT_MARLINBG_COLOR; + LOOP_L_N(n, GRAPHICAL_TFT_UPSCALE) buffer[k++] = c; + } + #if HAS_LCD_IO + LOOP_S_L_N(n, 1, GRAPHICAL_TFT_UPSCALE) + for (uint16_t l = 0; l < UPSCALE0(WIDTH); l++) + buffer[l + n * UPSCALE0(WIDTH)] = buffer[l]; + + tftio.WriteSequence(buffer, COUNT(bufferA)); + #else + uint8_t *bufptr = (uint8_t*) buffer; + for (uint8_t i = GRAPHICAL_TFT_UPSCALE; i--;) { + LOOP_S_L_N(n, 0, GRAPHICAL_TFT_UPSCALE * 2) { + u8g_WriteSequence(u8g, dev, WIDTH, &bufptr[WIDTH * n]); + } + } + #endif + } + break; + + case U8G_DEV_MSG_SLEEP_ON: + // Enter Sleep Mode (10h) + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + // Sleep Out (11h) + return 1; + } + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); +} + +uint8_t u8g_com_hal_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { + if (msgInitCount) { + if (msg == U8G_COM_MSG_INIT) msgInitCount--; + if (msgInitCount) return -1; + } + + static uint8_t isCommand; + + switch (msg) { + case U8G_COM_MSG_STOP: break; + case U8G_COM_MSG_INIT: + isCommand = 0; + break; + + case U8G_COM_MSG_ADDRESS: // define cmd (arg_val = 0) or data mode (arg_val = 1) + isCommand = arg_val == 0 ? 1 : 0; + break; + + case U8G_COM_MSG_RESET: + break; + + case U8G_COM_MSG_WRITE_BYTE: + tftio.DataTransferBegin(DATASIZE_8BIT); + if (isCommand) + tftio.WriteReg(arg_val); + else + tftio.WriteData((uint16_t)arg_val); + tftio.DataTransferEnd(); + break; + + case U8G_COM_MSG_WRITE_SEQ: + tftio.DataTransferBegin(DATASIZE_16BIT); + for (uint8_t i = 0; i < arg_val; i += 2) + tftio.WriteData(*(uint16_t *)(((uintptr_t)arg_ptr) + i)); + tftio.DataTransferEnd(); + break; + + } + return 1; +} + +U8G_PB_DEV(u8g_dev_tft_320x240_upscale_from_128x64, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_tft_320x240_upscale_from_128x64_fn, U8G_COM_HAL_TFT_FN); + +#if ENABLED(TOUCH_SCREEN_CALIBRATION) + + static void drawCross(uint16_t x, uint16_t y, uint16_t color) { + tftio.set_window(x - 15, y, x + 15, y); + tftio.WriteMultiple(color, 31); + tftio.set_window(x, y - 15, x, y + 15); + tftio.WriteMultiple(color, 31); + } + + void MarlinUI::touch_calibration_screen() { + uint16_t x, y; + calibrationState calibration_stage = touch_calibration.get_calibration_state(); + + if (calibration_stage == CALIBRATION_NONE) { + // start and clear screen + defer_status_screen(true); + calibration_stage = touch_calibration.calibration_start(); + tftio.set_window(0, 0, (TFT_WIDTH) - 1, (TFT_HEIGHT) - 1); + tftio.WriteMultiple(TFT_MARLINBG_COLOR, uint32_t(TFT_WIDTH) * (TFT_HEIGHT)); + } + else { + // clear last cross + x = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].x; + y = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].y; + drawCross(x, y, TFT_MARLINBG_COLOR); + } + + FSTR_P str = nullptr; + if (calibration_stage < CALIBRATION_SUCCESS) { + // handle current state + switch (calibration_stage) { + case CALIBRATION_TOP_LEFT: str = GET_TEXT_F(MSG_TOP_LEFT); break; + case CALIBRATION_BOTTOM_LEFT: str = GET_TEXT_F(MSG_BOTTOM_LEFT); break; + case CALIBRATION_TOP_RIGHT: str = GET_TEXT_F(MSG_TOP_RIGHT); break; + case CALIBRATION_BOTTOM_RIGHT: str = GET_TEXT_F(MSG_BOTTOM_RIGHT); break; + default: break; + } + + x = touch_calibration.calibration_points[calibration_stage].x; + y = touch_calibration.calibration_points[calibration_stage].y; + drawCross(x, y, TFT_MARLINUI_COLOR); + } + else { + // end calibration + str = calibration_stage == CALIBRATION_SUCCESS ? GET_TEXT_F(MSG_CALIBRATION_COMPLETED) : GET_TEXT_F(MSG_CALIBRATION_FAILED); + defer_status_screen(false); + touch_calibration.calibration_end(); + TERN_(HAS_TOUCH_BUTTONS, redrawTouchButtons = true); + } + + // draw current message + tftio.set_window(TFT_PIXEL_OFFSET_X, TFT_PIXEL_OFFSET_Y, X_HI, Y_HI); + do { + set_font(FONT_MENU); + lcd_put_u8str(0, LCD_PIXEL_HEIGHT / 2, str); + } while (u8g.nextPage()); + drawing_screen = false; + safe_delay(250); + if (calibration_stage == CALIBRATION_SUCCESS) { + safe_delay(500); + ui.goto_previous_screen(); + } + } + +#endif // TOUCH_SCREEN_CALIBRATION + +#endif // HAS_MARLINUI_U8GLIB && (FSMC_CS_PIN || HAS_SPI_GRAPHICAL_TFT) diff --git a/src/lcd/dogm/u8g_dev_uc1701_mini12864_HAL.cpp b/src/lcd/dogm/u8g_dev_uc1701_mini12864_HAL.cpp new file mode 100644 index 0000000..172afbd --- /dev/null +++ b/src/lcd/dogm/u8g_dev_uc1701_mini12864_HAL.cpp @@ -0,0 +1,213 @@ +/** + * 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 . + * + */ + +/** + * Based on u8g_dev_uc1701_mini12864.c (dealextreme) + * + * Universal 8bit Graphics Library + * + * Copyright (c) 2011, olikraus@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB + +#include "HAL_LCD_com_defines.h" + +#define WIDTH 128 +#define HEIGHT 64 +#define PAGE_HEIGHT 8 + +#define UC1701_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) +#define UC1701_BIAS_MODE(N) ((N) ? 0xA3 : 0xA2) +#define UC1701_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) +#define UC1701_INVERTED(N) ((N) ? 0xA7 : 0xA6) +#define UC1701_ON(N) ((N) ? 0xAF : 0xAE) +#define UC1701_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) +#define UC1701_POWER_CONTROL(N) (0x28 | (N)) +#define UC1701_V5_RATIO(N) (0x20 | ((N) & 0x7)) +#define UC1701_CONTRAST(N) (0x81), (N) + +#define UC1701_COLUMN_HI(N) (0x10 | (((N) >> 4) & 0xF)) +#define UC1701_COLUMN_ADR(N) UC1701_COLUMN_HI(N), ((N) & 0xF) +#define UC1701_PAGE_ADR(N) (0xB0 | (N)) +#define UC1701_START_LINE(N) (0x40 | (N)) +#define UC1701_INDICATOR(N) (0xAC), (N) +#define UC1701_RESET() (0xE2) +#define UC1701_NOOP() (0xE3) +#define UC1701_BOOST_RATIO(N) (0xF8), (N) + +static const uint8_t u8g_dev_uc1701_mini12864_HAL_init_seq[] PROGMEM = { + U8G_ESC_CS(0), // disable chip + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_RST(1), // do reset low pulse with (1*16)+2 milliseconds + U8G_ESC_CS(1), // enable chip + + UC1701_RESET(), // soft reset + UC1701_START_LINE(0), // set display start line to 0 + UC1701_ADC_REVERSE(0), // ADC set to reverse + UC1701_OUT_MODE(1), // common output mode + UC1701_INVERTED(0), // display normal, bit val 0: LCD pixel off + UC1701_BIAS_MODE(0), // LCD bias 1/9 + UC1701_POWER_CONTROL(0x7), // all power control circuits on + UC1701_BOOST_RATIO(0x0), // set booster ratio to 4x + UC1701_V5_RATIO(3), // set V0 voltage resistor ratio to large + UC1701_CONTRAST(0x27), // set contrast + UC1701_INDICATOR(0), // indicator disable + UC1701_ON(1), // display on + + U8G_ESC_CS(0), // disable chip + U8G_ESC_DLY(100), // delay 100 ms + U8G_ESC_CS(1), // enable chip + + UC1701_ALL_PIX(1), // display all points, ST7565 + U8G_ESC_CS(0), // disable chip + U8G_ESC_DLY(100), // delay 100 ms + U8G_ESC_DLY(100), // delay 100 ms + U8G_ESC_CS(1), // enable chip + UC1701_ALL_PIX(0), // normal display + U8G_ESC_CS(0), // disable chip + U8G_ESC_DLY(150), // delay 150 ms before sending any data + U8G_ESC_END // end of sequence +}; + +static const uint8_t u8g_dev_uc1701_mini12864_HAL_data_start[] PROGMEM = { + U8G_ESC_ADR(0), // instruction mode + U8G_ESC_CS(1), // enable chip + #if ANY(MKS_MINI_12864, ENDER2_STOCKDISPLAY, FYSETC_MINI_12864) + UC1701_START_LINE(0), // set display start line to 0 + UC1701_ADC_REVERSE(0), // ADC set to reverse + UC1701_OUT_MODE(1), // common output mode + UC1701_INVERTED(0), // display normal, bit val 0: LCD pixel off + UC1701_BIAS_MODE(0), // LCD bias 1/9 + UC1701_POWER_CONTROL(0x7),// all power control circuits on + UC1701_BOOST_RATIO(0x0), // set booster ratio to 4x + UC1701_V5_RATIO(3), // set V0 voltage resistor ratio to large + UC1701_INDICATOR(0), // indicator disable + UC1701_ON(1), // display on + UC1701_COLUMN_HI(0), // set upper 4 bit of the col adr to 0 + U8G_ESC_END, // end of sequence + U8G_ESC_DLY(5) // delay 5 ms + #else + UC1701_COLUMN_ADR(0), // address 0 + U8G_ESC_END // end of sequence + #endif +}; + +uint8_t u8g_dev_uc1701_mini12864_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq); + break; + + case U8G_DEV_MSG_STOP: break; + + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_data_start); + u8g_WriteByte(u8g, dev, 0x0B0 | pb->p.page); /* select current page */ + u8g_SetAddress(u8g, dev, 1); /* data mode */ + if (!u8g_pb_WriteBuffer(pb, u8g, dev)) return 0; + u8g_SetChipSelect(u8g, dev, 0); + } break; + + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); /* instruction mode */ + u8g_WriteByte(u8g, dev, 0x081); + u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 2); + u8g_SetChipSelect(u8g, dev, 0); + return 1; + } + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); +} + +uint8_t u8g_dev_uc1701_mini12864_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch (msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq); + break; + + case U8G_DEV_MSG_STOP: break; + + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_data_start); + u8g_WriteByte(u8g, dev, 0x0B0 | (2 * pb->p.page)); /* select current page */ + u8g_SetAddress(u8g, dev, 1); /* data mode */ + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)pb->buf); + u8g_SetChipSelect(u8g, dev, 0); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_data_start); + u8g_WriteByte(u8g, dev, 0x0B0 | (2 * pb->p.page + 1)); /* select current page */ + u8g_SetAddress(u8g, dev, 1); /* data mode */ + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); + u8g_SetChipSelect(u8g, dev, 0); + } break; + + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); /* instruction mode */ + u8g_WriteByte(u8g, dev, 0x081); + u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 2); + u8g_SetChipSelect(u8g, dev, 0); + return 1; + } + return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg); +} + +U8G_PB_DEV(u8g_dev_uc1701_mini12864_HAL_sw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_uc1701_mini12864_HAL_fn, U8G_COM_HAL_SW_SPI_FN); +U8G_PB_DEV(u8g_dev_uc1701_mini12864_HAL_hw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_uc1701_mini12864_HAL_fn, U8G_COM_HAL_HW_SPI_FN); + +uint8_t u8g_dev_uc1701_mini12864_HAL_2x_buf[WIDTH*2] U8G_NOCOMMON ; +u8g_pb_t u8g_dev_uc1701_mini12864_HAL_2x_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_uc1701_mini12864_HAL_2x_buf}; +u8g_dev_t u8g_dev_uc1701_mini12864_HAL_2x_sw_spi = { u8g_dev_uc1701_mini12864_HAL_2x_fn, &u8g_dev_uc1701_mini12864_HAL_2x_pb, U8G_COM_HAL_SW_SPI_FN }; +u8g_dev_t u8g_dev_uc1701_mini12864_HAL_2x_hw_spi = { u8g_dev_uc1701_mini12864_HAL_2x_fn, &u8g_dev_uc1701_mini12864_HAL_2x_pb, U8G_COM_HAL_HW_SPI_FN }; + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/u8g_fontutf8.cpp b/src/lcd/dogm/u8g_fontutf8.cpp new file mode 100644 index 0000000..d5e0e5b --- /dev/null +++ b/src/lcd/dogm/u8g_fontutf8.cpp @@ -0,0 +1,315 @@ +/** + * @file u8g_fontutf8.cpp + * @brief font api for u8g lib + * @author Yunhui Fu (yhfudev@gmail.com) + * @version 1.0 + * @date 2015-02-19 + * @copyright GPL/BSD + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_MARLINUI_U8GLIB + +#include +#include "../fontutils.h" +#include "u8g_fontutf8.h" + +typedef void font_t; + +/** + * @brief the callback function to draw something + * + * @param userdata : User's data + * @param msg : the u8g's string + * @param fnt_current : the font + * + * @return 0 on success, 1 to force quit, <0 on error + * + * Get the screen pixel width of a ROM UTF-8 string + */ +typedef int (* fontgroup_cb_draw_t)(void *userdata, const font_t *fnt_current, const char *msg); + +/* return v1 - v2 */ +static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) { + if (v1->page < v2->page) return -1; + else if (v1->page > v2->page) return 1; + + if (v1->end < v2->begin) return -1; + else if (v1->begin > v2->end) return 1; + + return 0; +} + +/*"data_list[idx] - *data_pin"*/ +static int pf_bsearch_cb_comp_fntifo_pgm (void *userdata, size_t idx, void *data_pin) { + uxg_fontinfo_t *fntinfo = (uxg_fontinfo_t*)userdata; + uxg_fontinfo_t localval; + memcpy_P(&localval, fntinfo + idx, sizeof(localval)); + return fontinfo_compare(&localval, (uxg_fontinfo_t*)data_pin); +} + +typedef struct _font_group_t { + const uxg_fontinfo_t * m_fntifo; + int m_fntinfo_num; +} font_group_t; + +static int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number) { + root->m_fntifo = fntinfo; + root->m_fntinfo_num = number; + return 0; +} + +static const font_t* fontgroup_find(font_group_t * root, const lchar_t &val) { + if (val <= 0xFF) return nullptr; + + uxg_fontinfo_t vcmp = { uint16_t(val >> 7), uint8_t((val & 0x7F) + 0x80), uint8_t((val & 0x7F) + 0x80), 0, 0 }; + size_t idx = 0; + + if (pf_bsearch_r((void*)root->m_fntifo, root->m_fntinfo_num, pf_bsearch_cb_comp_fntifo_pgm, (void*)&vcmp, &idx) < 0) + return nullptr; + + memcpy_P(&vcmp, root->m_fntifo + idx, sizeof(vcmp)); + return vcmp.fntdata; +} + +static void fontgroup_drawwchar(font_group_t *group, const font_t *fnt_default, const lchar_t &val, void * userdata, fontgroup_cb_draw_t cb_draw_ram) { + uint8_t buf[2] = {0, 0}; + const font_t * fntpqm = (font_t*)fontgroup_find(group, val); + if (!fntpqm) { + // Unknown char, use default font + buf[0] = (uint8_t)(val & 0xFF); + fntpqm = fnt_default; + } + if (fnt_default != fntpqm) { + buf[0] = (uint8_t)(val & 0x7F); + buf[0] |= 0x80; // use upper page to avoid 0x00 error in C. you may want to generate the font data + } + + cb_draw_ram (userdata, fntpqm, (char*) buf); +} + +/** + * @brief try to process a utf8 string + * + * @param pu8g : U8G pointer + * @param fnt_default : the default font + * @param utf8_msg : the UTF-8 string + * @param cb_read_byte : how to read the utf8_msg, from RAM or ROM (call read_byte_ram or pgm_read_byte) + * @param userdata : User's data + * @param cb_draw_ram : the callback function of userdata to draw a !RAM! string (actually it is to draw a one byte string in RAM) + * + * @return N/A + * + * Get the screen pixel width of a ROM UTF-8 string + */ +static void fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, read_byte_cb_t cb_read_byte, void * userdata, fontgroup_cb_draw_t cb_draw_ram) { + const uint8_t *p = (uint8_t*)utf8_msg; + for (;;) { + lchar_t wc; + p = get_utf8_value_cb(p, cb_read_byte, wc); + if (!wc) break; + fontgroup_drawwchar(group, fnt_default, wc, userdata, cb_draw_ram); + } +} + +static bool flag_fontgroup_was_inited = false; +static font_group_t g_fontgroup_root = { nullptr, 0 }; + +/** + * @brief check if font is loaded + */ +static inline bool uxg_Utf8FontIsInited() { return flag_fontgroup_was_inited; } + +int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) { + flag_fontgroup_was_inited = 1; + return fontgroup_init(&g_fontgroup_root, fntinfo, number); +} + +struct _uxg_drawu8_data_t { + u8g_t *pu8g; + unsigned int x; + unsigned int y; + unsigned int adv; + unsigned int max_width; // the max pixel width of the string allowed + const void * fnt_prev; +}; + +static int fontgroup_cb_draw_u8g(void *userdata, const font_t *fnt_current, const char *msg) { + struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata; + + if (pdata->fnt_prev != fnt_current) { + u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current); + pdata->fnt_prev = fnt_current; + } + if ((pdata->max_width != PIXEL_LEN_NOLIMIT) && (pdata->adv + u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg) > pdata->max_width)) + return 1; + pdata->adv += u8g_DrawStr(pdata->pu8g, pdata->x + pdata->adv, pdata->y, (char*) msg); + return 0; +} + +/** + * @brief Draw a lchar_t at the specified position + * + * @param pu8g : U8G pointer + * @param x : position x axis + * @param y : position y axis + * @param wc : the lchar_t + * @param max_width : the pixel width of the string allowed + * + * @return number of pixels advanced + * + * Draw a UTF-8 string at the specified position + */ +unsigned int uxg_DrawWchar(u8g_t *pu8g, unsigned int x, unsigned int y, const lchar_t &wc, pixel_len_t max_width) { + struct _uxg_drawu8_data_t data; + font_group_t *group = &g_fontgroup_root; + const font_t *fnt_default = uxg_GetFont(pu8g); + + if (!uxg_Utf8FontIsInited()) { + u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized.")); + return 0; + } + data.pu8g = pu8g; + data.x = x; + data.y = y; + data.adv = 0; + data.max_width = max_width; + data.fnt_prev = nullptr; + fontgroup_drawwchar(group, fnt_default, wc, (void*)&data, fontgroup_cb_draw_u8g); + u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default); + + return data.adv; +} + +/** + * @brief Draw a UTF-8 string at the specified position + * + * @param pu8g : U8G pointer + * @param x : position x axis + * @param y : position y axis + * @param utf8_msg : the UTF-8 string + * @param max_width : the pixel width of the string allowed + * + * @return number of pixels advanced + * + * Draw a UTF-8 string at the specified position + */ +unsigned int uxg_DrawUtf8Str(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_width) { + struct _uxg_drawu8_data_t data; + font_group_t *group = &g_fontgroup_root; + const font_t *fnt_default = uxg_GetFont(pu8g); + + if (!uxg_Utf8FontIsInited()) { + u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized.")); + return 0; + } + data.pu8g = pu8g; + data.x = x; + data.y = y; + data.adv = 0; + data.max_width = max_width; + data.fnt_prev = nullptr; + fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8g); + u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default); + + return data.adv; +} + +/** + * @brief Draw a ROM UTF-8 string at the specified position + * + * @param pu8g : U8G pointer + * @param x : position x axis + * @param y : position y axis + * @param utf8_msg : the UTF-8 string + * @param max_width : the pixel width of the string allowed + * + * @return number of pixels advanced + * + * Draw a ROM UTF-8 string at the specified position + */ +unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, PGM_P utf8_msg, pixel_len_t max_width) { + struct _uxg_drawu8_data_t data; + font_group_t *group = &g_fontgroup_root; + const font_t *fnt_default = uxg_GetFont(pu8g); + + if (!uxg_Utf8FontIsInited()) { + u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized.")); + return 0; + } + data.pu8g = pu8g; + data.x = x; + data.y = y; + data.adv = 0; + data.max_width = max_width; + data.fnt_prev = nullptr; + fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8g); + u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default); + + return data.adv; +} + +static int fontgroup_cb_draw_u8gstrlen(void *userdata, const font_t *fnt_current, const char *msg) { + struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata; + + if (pdata->fnt_prev != fnt_current) { + u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current); + pdata->fnt_prev = fnt_current; + } + pdata->adv += u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg); + return 0; +} + +/** + * @brief Get the screen pixel width of a UTF-8 string + * + * @param pu8g : U8G pointer + * @param utf8_msg : the UTF-8 string + * + * @return the pixel width + * + * Get the screen pixel width of a UTF-8 string + */ +int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg) { + struct _uxg_drawu8_data_t data; + font_group_t *group = &g_fontgroup_root; + const font_t *fnt_default = uxg_GetFont(pu8g); + + if (!uxg_Utf8FontIsInited()) return -1; + + memset(&data, 0, sizeof(data)); + data.pu8g = pu8g; + data.adv = 0; + fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8gstrlen); + u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default); + + return data.adv; +} + +/** + * @brief Get the screen pixel width of a ROM UTF-8 string + * + * @param pu8g : U8G pointer + * @param utf8_msg : the UTF-8 string + * + * @return the pixel width + * + * Get the screen pixel width of a ROM UTF-8 string + */ +int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, PGM_P utf8_msg) { + struct _uxg_drawu8_data_t data; + font_group_t *group = &g_fontgroup_root; + const font_t *fnt_default = uxg_GetFont(pu8g); + + if (!uxg_Utf8FontIsInited()) return -1; + + memset(&data, 0, sizeof(data)); + data.pu8g = pu8g; + data.adv = 0; + fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8gstrlen); + u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default); + return data.adv; +} + +#endif // HAS_MARLINUI_U8GLIB diff --git a/src/lcd/dogm/u8g_fontutf8.h b/src/lcd/dogm/u8g_fontutf8.h new file mode 100644 index 0000000..0109b66 --- /dev/null +++ b/src/lcd/dogm/u8g_fontutf8.h @@ -0,0 +1,40 @@ +/** + * @file fontutf8.h + * @brief font api for u8g lib + * @author Yunhui Fu (yhfudev@gmail.com) + * @version 1.0 + * @date 2015-02-19 + * @copyright GPL/BSD + */ +#pragma once + +#include +#include "../fontutils.h" + +// the macro to indicate a UTF-8 string +// You should to save the C/C++ source in UTF-8 encoding! +// Once you change your UTF-8 strings, you need to call the script uxggenpages.sh to create the font data file fontutf8-data.h +#define _UxGT(a) a + +typedef struct _uxg_fontinfo_t { + uint16_t page; + uint8_t begin; + uint8_t end; + uint16_t size; + const u8g_fntpgm_uint8_t *fntdata; +} uxg_fontinfo_t; + +int uxg_SetUtf8Fonts(const uxg_fontinfo_t * fntinfo, int number); // fntinfo is type of PROGMEM + +unsigned int uxg_DrawWchar(u8g_t *pu8g, unsigned int x, unsigned int y, const lchar_t &ch, const pixel_len_t max_length); + +unsigned int uxg_DrawUtf8Str(u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, const pixel_len_t max_length); +unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, PGM_P utf8_msg, const pixel_len_t max_length); + +int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg); +int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, PGM_P utf8_msg); + +#define uxg_GetFont(puxg) ((puxg)->font) + +#define _LANG_FONT_INFO(L) g_fontinfo_##L +#define LANG_FONT_INFO(L) _LANG_FONT_INFO(L) diff --git a/src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.cpp b/src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.cpp new file mode 100644 index 0000000..e844eee --- /dev/null +++ b/src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.cpp @@ -0,0 +1,196 @@ +/** + * 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 . + * + */ + +// NOTE - the HAL version of the rrd device uses a generic ST7920 device. See the +// file u8g_dev_st7920_128x64_HAL.cpp for the HAL version. + +#include "../../inc/MarlinConfigPre.h" + +#if !defined(U8G_HAL_LINKS) && ANY(__AVR__, ARDUINO_ARCH_STM32, ARDUINO_ARCH_ESP32) + +#include "../../inc/MarlinConfig.h" + +#if IS_U8GLIB_ST7920 + +#include "ultralcd_st7920_u8glib_rrd_AVR.h" + +// Optimize this code with -O3 +#pragma GCC optimize (3) + +#ifndef ST7920_DELAY_1 + #ifndef LCD_ST7920_DELAY_1 + #define LCD_ST7920_DELAY_1 0 + #endif + #ifndef BOARD_ST7920_DELAY_1 + #define BOARD_ST7920_DELAY_1 0 + #endif + #ifndef CPU_ST7920_DELAY_1 + #define CPU_ST7920_DELAY_1 0 + #endif + #if LCD_ST7920_DELAY_1 || BOARD_ST7920_DELAY_1 || CPU_ST7920_DELAY_1 + #define ST7920_DELAY_1 DELAY_NS(_MAX(LCD_ST7920_DELAY_1, BOARD_ST7920_DELAY_1, CPU_ST7920_DELAY_1)) + #else + #define ST7920_DELAY_1 + #endif +#endif +#ifndef ST7920_DELAY_2 + #ifndef LCD_ST7920_DELAY_2 + #define LCD_ST7920_DELAY_2 0 + #endif + #ifndef BOARD_ST7920_DELAY_2 + #define BOARD_ST7920_DELAY_2 0 + #endif + #ifndef CPU_ST7920_DELAY_2 + #define CPU_ST7920_DELAY_2 0 + #endif + #if LCD_ST7920_DELAY_2 || BOARD_ST7920_DELAY_2 || CPU_ST7920_DELAY_2 + #define ST7920_DELAY_2 DELAY_NS(_MAX(LCD_ST7920_DELAY_2, BOARD_ST7920_DELAY_2, CPU_ST7920_DELAY_2)) + #else + #define ST7920_DELAY_2 + #endif +#endif +#ifndef ST7920_DELAY_3 + #ifndef LCD_ST7920_DELAY_3 + #define LCD_ST7920_DELAY_3 0 + #endif + #ifndef BOARD_ST7920_DELAY_3 + #define BOARD_ST7920_DELAY_3 0 + #endif + #ifndef CPU_ST7920_DELAY_3 + #define CPU_ST7920_DELAY_3 0 + #endif + #if LCD_ST7920_DELAY_3 || BOARD_ST7920_DELAY_3 || CPU_ST7920_DELAY_3 + #define ST7920_DELAY_3 DELAY_NS(_MAX(LCD_ST7920_DELAY_3, BOARD_ST7920_DELAY_3, CPU_ST7920_DELAY_3)) + #else + #define ST7920_DELAY_3 + #endif +#endif + +#ifdef ARDUINO_ARCH_STM32F1 + #define ST7920_DAT(V) !!((V) & 0x80) +#else + #define ST7920_DAT(V) ((V) & 0x80) +#endif + +#define ST7920_SND_BIT do{ \ + WRITE(ST7920_CLK_PIN, LOW); ST7920_DELAY_1; \ + WRITE(ST7920_DAT_PIN, ST7920_DAT(val)); ST7920_DELAY_2; \ + WRITE(ST7920_CLK_PIN, HIGH); ST7920_DELAY_3; \ + val <<= 1; }while(0) + +// Optimize this code with -O3 +#pragma GCC optimize (3) + +void ST7920_SWSPI_SND_8BIT(uint8_t val) { + ST7920_SND_BIT; // 1 + ST7920_SND_BIT; // 2 + ST7920_SND_BIT; // 3 + ST7920_SND_BIT; // 4 + ST7920_SND_BIT; // 5 + ST7920_SND_BIT; // 6 + ST7920_SND_BIT; // 7 + ST7920_SND_BIT; // 8 +} + +uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + uint8_t i, y; + switch (msg) { + case U8G_DEV_MSG_INIT: { + OUT_WRITE(ST7920_CS_PIN, LOW); + OUT_WRITE(ST7920_DAT_PIN, LOW); + OUT_WRITE(ST7920_CLK_PIN, HIGH); + + ST7920_CS(); + u8g_Delay(120); // Initial delay for boot up + ST7920_SET_CMD(); + ST7920_WRITE_BYTE(0x20); // Non-extended mode + ST7920_WRITE_BYTE(0x08); // Display off, cursor+blink off + ST7920_WRITE_BYTE(0x01); // Clear DDRAM ram + u8g_Delay(15); // Delay for DDRAM clear + ST7920_WRITE_BYTE(0x24); // Extended mode + ST7920_WRITE_BYTE(0x26); // Extended mode + GDRAM active + for (y = 0; y < (LCD_PIXEL_HEIGHT) / 2; y++) { // Clear GDRAM + ST7920_WRITE_BYTE(0x80 | y); // Set y + ST7920_WRITE_BYTE(0x80); // Set x = 0 + ST7920_SET_DAT(); + for (i = 0; i < 2 * (LCD_PIXEL_WIDTH) / 8; i++) // 2x width clears both segments + ST7920_WRITE_BYTE(0); + ST7920_SET_CMD(); + } + ST7920_WRITE_BYTE(0x0C); // Display on, cursor+blink off + ST7920_NCS(); + } + break; + + case U8G_DEV_MSG_STOP: break; + + case U8G_DEV_MSG_PAGE_NEXT: { + uint8_t *ptr; + u8g_pb_t *pb = (u8g_pb_t*)(dev->dev_mem); + y = pb->p.page_y0; + ptr = (uint8_t*)pb->buf; + + ST7920_CS(); + for (i = 0; i < PAGE_HEIGHT; i ++) { + ST7920_SET_CMD(); + if (y < 32) { + ST7920_WRITE_BYTE(0x80 | y); // y + ST7920_WRITE_BYTE(0x80); // x = 0 + } + else { + ST7920_WRITE_BYTE(0x80 | (y - 32)); // y + ST7920_WRITE_BYTE(0x80 | 8); // x = 64 + } + ST7920_SET_DAT(); + ST7920_WRITE_BYTES(ptr, (LCD_PIXEL_WIDTH) / 8); // ptr incremented inside of macro! + y++; + } + ST7920_NCS(); + } + break; + } + #if PAGE_HEIGHT == 8 + return u8g_dev_pb8h1_base_fn(u8g, dev, msg, arg); + #elif PAGE_HEIGHT == 16 + return u8g_dev_pb16h1_base_fn(u8g, dev, msg, arg); + #else + return u8g_dev_pb32h1_base_fn(u8g, dev, msg, arg); + #endif +} + +uint8_t u8g_dev_st7920_128x64_rrd_buf[(LCD_PIXEL_WIDTH) * (PAGE_HEIGHT) / 8] U8G_NOCOMMON; +u8g_pb_t u8g_dev_st7920_128x64_rrd_pb = { { PAGE_HEIGHT, LCD_PIXEL_HEIGHT, 0, 0, 0 }, LCD_PIXEL_WIDTH, u8g_dev_st7920_128x64_rrd_buf }; +u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi = { u8g_dev_rrd_st7920_128x64_fn, &u8g_dev_st7920_128x64_rrd_pb, &u8g_com_null_fn }; + +#pragma GCC reset_options + +#if ENABLED(LIGHTWEIGHT_UI) + #include "../../HAL/shared/HAL_ST7920.h" + void ST7920_cs() { ST7920_CS(); } + void ST7920_ncs() { ST7920_NCS(); } + void ST7920_set_cmd() { ST7920_SET_CMD(); } + void ST7920_set_dat() { ST7920_SET_DAT(); } + void ST7920_write_byte(const uint8_t val) { ST7920_WRITE_BYTE(val); } +#endif + +#endif // IS_U8GLIB_ST7920 +#endif // !U8G_HAL_LINKS && (__AVR__ || ARDUINO_ARCH_STM32 || ARDUINO_ARCH_ESP32) diff --git a/src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.h b/src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.h new file mode 100644 index 0000000..446bfcf --- /dev/null +++ b/src/lcd/dogm/ultralcd_st7920_u8glib_rrd_AVR.h @@ -0,0 +1,53 @@ +/** + * 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 + +// NOTE - the HAL version of the rrd device uses a generic ST7920 device. See the +// file u8g_dev_st7920_128x64_HAL.cpp for the HAL version. + +#include "../../inc/MarlinConfig.h" +#include "../../HAL/shared/Delay.h" + +#define ST7920_CLK_PIN LCD_PINS_D4 +#define ST7920_DAT_PIN LCD_PINS_ENABLE +#define ST7920_CS_PIN LCD_PINS_RS + +//#define PAGE_HEIGHT 8 // 128 byte framebuffer +#define PAGE_HEIGHT 16 // 256 byte framebuffer +//#define PAGE_HEIGHT 32 // 512 byte framebuffer + +#include + +void ST7920_SWSPI_SND_8BIT(uint8_t val); + +#if DOGM_SPI_DELAY_US > 0 + #define U8G_DELAY() DELAY_US(DOGM_SPI_DELAY_US) +#else + #define U8G_DELAY() DELAY_US(10) +#endif + +#define ST7920_CS() { WRITE(ST7920_CS_PIN, HIGH); U8G_DELAY(); } +#define ST7920_NCS() { WRITE(ST7920_CS_PIN, LOW); } +#define ST7920_SET_CMD() { ST7920_SWSPI_SND_8BIT(0xF8); U8G_DELAY(); } +#define ST7920_SET_DAT() { ST7920_SWSPI_SND_8BIT(0xFA); U8G_DELAY(); } +#define ST7920_WRITE_BYTE(a) { ST7920_SWSPI_SND_8BIT((uint8_t)((a)&0xF0u)); ST7920_SWSPI_SND_8BIT((uint8_t)((a)<<4U)); U8G_DELAY(); } +#define ST7920_WRITE_BYTES(p,l) { for (uint8_t i = l + 1; --i;) { ST7920_SWSPI_SND_8BIT(*p&0xF0); ST7920_SWSPI_SND_8BIT(*p<<4); p++; } U8G_DELAY(); } diff --git a/src/lcd/e3v2/README.md b/src/lcd/e3v2/README.md new file mode 100644 index 0000000..83ccb74 --- /dev/null +++ b/src/lcd/e3v2/README.md @@ -0,0 +1,7 @@ +# DWIN for Creality Ender 3 v2 + +Marlin's Ender 3 v2 support requires the `DWIN_SET` included with the Ender 3 V2 [example configuration](https://github.com/MarlinFirmware/Configurations/tree/bugfix-2.0.x/config/examples/Creality/Ender-3%20V2). + +## Easy Install + +Copy the `DWIN_SET` folder onto a Micro-SD card and insert the card into the slot on the DWIN screen. Cycle the machine and wait for the screen to go from blue to orange. Turn the machine off and remove the SD card. When you turn on the machine the screen will display a "Creality" loading screen. diff --git a/src/lcd/e3v2/common/dwin_api.cpp b/src/lcd/e3v2/common/dwin_api.cpp new file mode 100644 index 0000000..3f69946 --- /dev/null +++ b/src/lcd/e3v2/common/dwin_api.cpp @@ -0,0 +1,471 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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_DWIN_E3V2 || IS_DWIN_MARLINUI + +#include "dwin_api.h" +#include "dwin_set.h" +#include "dwin_font.h" + +#include "../../../inc/MarlinConfig.h" + +#include // for memset + +uint8_t DWIN_SendBuf[11 + DWIN_WIDTH / 6 * 2] = { 0xAA }; +uint8_t DWIN_BufTail[4] = { 0xCC, 0x33, 0xC3, 0x3C }; +uint8_t databuf[26] = { 0 }; + +// Send the data in the buffer plus the packet tail +void DWIN_Send(size_t &i) { + ++i; + LOOP_L_N(n, i) { LCD_SERIAL.write(DWIN_SendBuf[n]); delayMicroseconds(1); } + LOOP_L_N(n, 4) { LCD_SERIAL.write(DWIN_BufTail[n]); delayMicroseconds(1); } +} + +/*-------------------------------------- System variable function --------------------------------------*/ + +// Handshake (1: Success, 0: Fail) +bool DWIN_Handshake() { + static int recnum = 0; + #ifndef LCD_BAUDRATE + #define LCD_BAUDRATE 115200 + #endif + LCD_SERIAL.begin(LCD_BAUDRATE); + const millis_t serial_connect_timeout = millis() + 1000UL; + while (!LCD_SERIAL.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } + + size_t i = 0; + DWIN_Byte(i, 0x00); + DWIN_Send(i); + + while (LCD_SERIAL.available() > 0 && recnum < (signed)sizeof(databuf)) { + databuf[recnum] = LCD_SERIAL.read(); + // ignore the invalid data + if (databuf[0] != FHONE) { // prevent the program from running. + if (recnum > 0) { + recnum = 0; + ZERO(databuf); + } + continue; + } + delay(10); + recnum++; + } + + return ( recnum >= 3 + && databuf[0] == FHONE + && databuf[1] == '\0' + && databuf[2] == 'O' + && databuf[3] == 'K' ); +} + +#if HAS_LCD_BRIGHTNESS + // Set LCD backlight (from DWIN Enhanced) + // brightness: 0x00-0xFF + void DWIN_LCD_Brightness(const uint8_t brightness) { + size_t i = 0; + DWIN_Byte(i, 0x30); + DWIN_Byte(i, brightness); + DWIN_Send(i); + } +#endif + +// Get font character width +uint8_t fontWidth(uint8_t cfont) { + switch (cfont) { + case font6x12 : return 6; + case font8x16 : return 8; + case font10x20: return 10; + case font12x24: return 12; + case font14x28: return 14; + case font16x32: return 16; + case font20x40: return 20; + case font24x48: return 24; + case font28x56: return 28; + case font32x64: return 32; + default: return 0; + } +} + +// Get font character height +uint8_t fontHeight(uint8_t cfont) { + switch (cfont) { + case font6x12 : return 12; + case font8x16 : return 16; + case font10x20: return 20; + case font12x24: return 24; + case font14x28: return 28; + case font16x32: return 32; + case font20x40: return 40; + case font24x48: return 48; + case font28x56: return 56; + case font32x64: return 64; + default: return 0; + } +} + +// Set screen display direction +// dir: 0=0°, 1=90°, 2=180°, 3=270° +void DWIN_Frame_SetDir(uint8_t dir) { + size_t i = 0; + DWIN_Byte(i, 0x34); + DWIN_Byte(i, 0x5A); + DWIN_Byte(i, 0xA5); + DWIN_Byte(i, dir); + DWIN_Send(i); +} + +// Update display +void DWIN_UpdateLCD() { + size_t i = 0; + DWIN_Byte(i, 0x3D); + DWIN_Send(i); +} + +/*---------------------------------------- Drawing functions ----------------------------------------*/ + +// Clear screen +// color: Clear screen color +void DWIN_Frame_Clear(const uint16_t color) { + size_t i = 0; + DWIN_Byte(i, 0x01); + DWIN_Word(i, color); + DWIN_Send(i); +} + +// Draw a point +// color: point color +// width: point width 0x01-0x0F +// height: point height 0x01-0x0F +// x,y: upper left point +void DWIN_Draw_Point(uint16_t color, uint8_t width, uint8_t height, uint16_t x, uint16_t y) { + size_t i = 0; + DWIN_Byte(i, 0x02); + DWIN_Word(i, color); + DWIN_Byte(i, width); + DWIN_Byte(i, height); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Send(i); +} + +// Draw a line +// color: Line segment color +// xStart/yStart: Start point +// xEnd/yEnd: End point +void DWIN_Draw_Line(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) { + size_t i = 0; + DWIN_Byte(i, 0x03); + DWIN_Word(i, color); + DWIN_Word(i, xStart); + DWIN_Word(i, yStart); + DWIN_Word(i, xEnd); + DWIN_Word(i, yEnd); + DWIN_Send(i); +} + +// Draw a rectangle +// mode: 0=frame, 1=fill, 2=XOR fill +// color: Rectangle color +// xStart/yStart: upper left point +// xEnd/yEnd: lower right point +void DWIN_Draw_Rectangle(uint8_t mode, uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) { + size_t i = 0; + DWIN_Byte(i, 0x05); + DWIN_Byte(i, mode); + DWIN_Word(i, color); + DWIN_Word(i, xStart); + DWIN_Word(i, yStart); + DWIN_Word(i, xEnd); + DWIN_Word(i, yEnd); + DWIN_Send(i); +} + +// Move a screen area +// mode: 0, circle shift; 1, translation +// dir: 0=left, 1=right, 2=up, 3=down +// dis: Distance +// color: Fill color +// xStart/yStart: upper left point +// xEnd/yEnd: bottom right point +void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis, + uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) { + size_t i = 0; + DWIN_Byte(i, 0x09); + DWIN_Byte(i, (mode << 7) | dir); + DWIN_Word(i, dis); + DWIN_Word(i, color); + DWIN_Word(i, xStart); + DWIN_Word(i, yStart); + DWIN_Word(i, xEnd); + DWIN_Word(i, yEnd); + DWIN_Send(i); +} + +/*---------------------------------------- Text related functions ----------------------------------------*/ + +// Draw a string +// widthAdjust: true=self-adjust character width; false=no adjustment +// bShow: true=display background color; false=don't display background color +// size: Font size +// color: Character color +// bColor: Background color +// x/y: Upper-left coordinate of the string +// *string: The string +// rlimit: To limit the drawn string length +void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit/*=0xFFFF*/) { + #if DISABLED(DWIN_LCD_PROUI) + DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size)); + #endif + constexpr uint8_t widthAdjust = 0; + size_t i = 0; + DWIN_Byte(i, 0x11); + // Bit 7: widthAdjust + // Bit 6: bShow + // Bit 5-4: Unused (0) + // Bit 3-0: size + DWIN_Byte(i, (widthAdjust * 0x80) | (bShow * 0x40) | size); + DWIN_Word(i, color); + DWIN_Word(i, bColor); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Text(i, string, rlimit); + DWIN_Send(i); +} + +// Draw a positive integer +// bShow: true=display background color; false=don't display background color +// zeroFill: true=zero fill; false=no zero fill +// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space +// size: Font size +// color: Character color +// bColor: Background color +// iNum: Number of digits +// x/y: Upper-left coordinate +// value: Integer value +void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint32_t value) { + size_t i = 0; + DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * iNum + 1, y + fontHeight(size)); + DWIN_Byte(i, 0x14); + // Bit 7: bshow + // Bit 6: 1 = signed; 0 = unsigned number; + // Bit 5: zeroFill + // Bit 4: zeroMode + // Bit 3-0: size + DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size); + DWIN_Word(i, color); + DWIN_Word(i, bColor); + DWIN_Byte(i, iNum); + DWIN_Byte(i, 0); // fNum + DWIN_Word(i, x); + DWIN_Word(i, y); + #if 0 + for (char count = 0; count < 8; count++) { + DWIN_Byte(i, value); + value >>= 8; + if (!(value & 0xFF)) break; + } + #else + // Write a big-endian 64 bit integer + const size_t p = i + 1; + for (char count = 8; count--;) { // 7..0 + ++i; + DWIN_SendBuf[p + count] = value; + value >>= 8; + } + #endif + + DWIN_Send(i); +} + +// Draw a floating point number +// bShow: true=display background color; false=don't display background color +// zeroFill: true=zero fill; false=no zero fill +// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space +// size: Font size +// color: Character color +// bColor: Background color +// iNum: Number of whole digits +// fNum: Number of decimal digits +// x/y: Upper-left point +// value: Float value +void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) { + //uint8_t *fvalue = (uint8_t*)&value; + size_t i = 0; + DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * (iNum+fNum+1), y + fontHeight(size)); + DWIN_Byte(i, 0x14); + DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size); + DWIN_Word(i, color); + DWIN_Word(i, bColor); + DWIN_Byte(i, iNum); + DWIN_Byte(i, fNum); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Long(i, value); + /* + DWIN_Byte(i, fvalue[3]); + DWIN_Byte(i, fvalue[2]); + DWIN_Byte(i, fvalue[1]); + DWIN_Byte(i, fvalue[0]); + */ + DWIN_Send(i); +} + +// Draw a floating point number +// value: positive unscaled float value +void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + const int32_t val = round(value * POW(10, fNum)); + DWIN_Draw_FloatValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, val); +} + +/*---------------------------------------- Picture related functions ----------------------------------------*/ + +// Draw JPG and cached in #0 virtual display area +// id: Picture ID +void DWIN_JPG_ShowAndCache(const uint8_t id) { + size_t i = 0; + DWIN_Word(i, 0x2200); + DWIN_Byte(i, id); + DWIN_Send(i); // AA 23 00 00 00 00 08 00 01 02 03 CC 33 C3 3C +} + +// Draw an Icon +// IBD: The icon background display: 0=Background filtering is not displayed, 1=Background display \\When setting the background filtering not to display, the background must be pure black +// BIR: Background image restoration: 0=Background image is not restored, 1=Automatically use virtual display area image for background restoration +// BFI: Background filtering strength: 0=normal, 1=enhanced, (only valid when the icon background display=0) +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(bool IBD, bool BIR, bool BFI, uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + NOMORE(x, DWIN_WIDTH - 1); + NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl + size_t i = 0; + DWIN_Byte(i, 0x23); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Byte(i, (IBD << 7) | (BIR << 6) | (BFI << 5) | libID); + DWIN_Byte(i, picID); + DWIN_Send(i); +} + +// Draw an Icon from SRAM +// IBD: The icon background display: 0=Background filtering is not displayed, 1=Background display \\When setting the background filtering not to display, the background must be pure black +// BIR: Background image restoration: 0=Background image is not restored, 1=Automatically use virtual display area image for background restoration +// BFI: Background filtering strength: 0=normal, 1=enhanced, (only valid when the icon background display=0) +// x/y: Upper-left point +// addr: SRAM address +void DWIN_ICON_Show(bool IBD, bool BIR, bool BFI, uint16_t x, uint16_t y, uint16_t addr) { + NOMORE(x, DWIN_WIDTH - 1); + NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl + size_t i = 0; + DWIN_Byte(i, 0x24); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Byte(i, (IBD << 7) | (BIR << 6) | (BFI << 5) | 0x00); + DWIN_Word(i, addr); + DWIN_Send(i); +} + +// Unzip the JPG picture to a virtual display area +// n: Cache index +// id: Picture ID +void DWIN_JPG_CacheToN(uint8_t n, uint8_t id) { + size_t i = 0; + DWIN_Byte(i, 0x25); + DWIN_Byte(i, n); + DWIN_Byte(i, id); + DWIN_Send(i); +} + +// Animate a series of icons +// animID: Animation ID; 0x00-0x0F +// animate: true on; false off; +// libID: Icon library ID +// picIDs: Icon starting ID +// picIDe: Icon ending ID +// x/y: Upper-left point +// interval: Display time interval, unit 10mS +void DWIN_ICON_Animation(uint8_t animID, bool animate, uint8_t libID, uint8_t picIDs, uint8_t picIDe, uint16_t x, uint16_t y, uint16_t interval) { + NOMORE(x, DWIN_WIDTH - 1); + NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl + size_t i = 0; + DWIN_Byte(i, 0x28); + DWIN_Word(i, x); + DWIN_Word(i, y); + // Bit 7: animation on or off + // Bit 6: start from begin or end + // Bit 5-4: unused (0) + // Bit 3-0: animID + DWIN_Byte(i, (animate * 0x80) | 0x40 | animID); + DWIN_Byte(i, libID); + DWIN_Byte(i, picIDs); + DWIN_Byte(i, picIDe); + DWIN_Byte(i, interval); + DWIN_Send(i); +} + +// Animation Control +// state: 16 bits, each bit is the state of an animation id +void DWIN_ICON_AnimationControl(uint16_t state) { + size_t i = 0; + DWIN_Byte(i, 0x29); + DWIN_Word(i, state); + DWIN_Send(i); +} + +/*---------------------------------------- Memory functions ----------------------------------------*/ +// The LCD has an additional 32KB SRAM and 16KB Flash +// Data can be written to the SRAM and saved to one of the jpeg page files + +// Write Data Memory +// command 0x31 +// Type: Write memory selection; 0x5A=SRAM; 0xA5=Flash +// Address: Write data memory address; 0x000-0x7FFF for SRAM; 0x000-0x3FFF for Flash +// Data: data +// +// Flash writing returns 0xA5 0x4F 0x4B + +// Read Data Memory +// command 0x32 +// Type: Read memory selection; 0x5A=SRAM; 0xA5=Flash +// Address: Read data memory address; 0x000-0x7FFF for SRAM; 0x000-0x3FFF for Flash +// Length: leangth of data to read; 0x01-0xF0 +// +// Response: +// Type, Address, Length, Data + +// Write Picture Memory +// Write the contents of the 32KB SRAM data memory into the designated image memory space +// Issued: 0x5A, 0xA5, PIC_ID +// Response: 0xA5 0x4F 0x4B +// +// command 0x33 +// 0x5A, 0xA5 +// PicId: Picture Memory location, 0x00-0x0F +// +// Flash writing returns 0xA5 0x4F 0x4B + +#endif // HAS_DWIN_E3V2 || IS_DWIN_MARLINUI diff --git a/src/lcd/e3v2/common/dwin_api.h b/src/lcd/e3v2/common/dwin_api.h new file mode 100644 index 0000000..dc97ef2 --- /dev/null +++ b/src/lcd/e3v2/common/dwin_api.h @@ -0,0 +1,270 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 "../../../inc/MarlinConfig.h" + +#if ENABLED(DWIN_MARLINUI_LANDSCAPE) + #define DWIN_WIDTH 480 + #define DWIN_HEIGHT 272 +#else + #define DWIN_WIDTH 272 + #define DWIN_HEIGHT 480 +#endif + +#define RECEIVED_NO_DATA 0x00 +#define RECEIVED_SHAKE_HAND_ACK 0x01 + +#define FHONE 0xAA + +#define DWIN_SCROLL_UP 2 +#define DWIN_SCROLL_DOWN 3 + +// Make sure DWIN_SendBuf is large enough to hold the largest string plus draw command and tail. +// Assume the narrowest (6 pixel) font and 2-byte gb2312-encoded characters. +extern uint8_t DWIN_SendBuf[11 + DWIN_WIDTH / 6 * 2]; +extern uint8_t DWIN_BufTail[4]; +extern uint8_t databuf[26]; + +inline void DWIN_Byte(size_t &i, const uint16_t bval) { + DWIN_SendBuf[++i] = bval; +} + +inline void DWIN_Word(size_t &i, const uint16_t wval) { + DWIN_SendBuf[++i] = wval >> 8; + DWIN_SendBuf[++i] = wval & 0xFF; +} + +inline void DWIN_Long(size_t &i, const uint32_t lval) { + DWIN_SendBuf[++i] = (lval >> 24) & 0xFF; + DWIN_SendBuf[++i] = (lval >> 16) & 0xFF; + DWIN_SendBuf[++i] = (lval >> 8) & 0xFF; + DWIN_SendBuf[++i] = lval & 0xFF; +} + +// Send the data in the buffer plus the packet tail +void DWIN_Send(size_t &i); + +inline void DWIN_Text(size_t &i, const char * const string, uint16_t rlimit=0xFFFF) { + if (!string) return; + const size_t len = _MIN(sizeof(DWIN_SendBuf) - i, _MIN(strlen(string), rlimit)); + if (len == 0) return; + memcpy(&DWIN_SendBuf[i+1], string, len); + i += len; +} + +inline void DWIN_Text(size_t &i, FSTR_P string, uint16_t rlimit=0xFFFF) { + if (!string) return; + const size_t len = _MIN(sizeof(DWIN_SendBuf) - i, _MIN(rlimit, strlen_P(FTOP(string)))); + if (len == 0) return; + memcpy_P(&DWIN_SendBuf[i+1], string, len); + i += len; +} + +/*-------------------------------------- System variable function --------------------------------------*/ + +// Handshake (1: Success, 0: Fail) +bool DWIN_Handshake(); + +// DWIN startup +void DWIN_Startup(); + +#if HAS_LCD_BRIGHTNESS + // Set the backlight brightness + // brightness: (0x00-0xFF) + void DWIN_LCD_Brightness(const uint8_t brightness); +#endif + +// Set screen display direction +// dir: 0=0°, 1=90°, 2=180°, 3=270° +void DWIN_Frame_SetDir(uint8_t dir); + +// Update display +void DWIN_UpdateLCD(); + +/*---------------------------------------- Drawing functions ----------------------------------------*/ + +// Clear screen +// color: Clear screen color +void DWIN_Frame_Clear(const uint16_t color); + +// Draw a point +// color: point color +// width: point width 0x01-0x0F +// height: point height 0x01-0x0F +// x,y: upper left point +void DWIN_Draw_Point(uint16_t color, uint8_t width, uint8_t height, uint16_t x, uint16_t y); + +// Draw a line +// color: Line segment color +// xStart/yStart: Start point +// xEnd/yEnd: End point +void DWIN_Draw_Line(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd); + +// Draw a Horizontal line +// color: Line segment color +// xStart/yStart: Start point +// xLength: Line Length +inline void DWIN_Draw_HLine(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xLength) { + DWIN_Draw_Line(color, xStart, yStart, xStart + xLength - 1, yStart); +} + +// Draw a Vertical line +// color: Line segment color +// xStart/yStart: Start point +// yLength: Line Length +inline void DWIN_Draw_VLine(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t yLength) { + DWIN_Draw_Line(color, xStart, yStart, xStart, yStart + yLength - 1); +} + +// Draw a rectangle +// mode: 0=frame, 1=fill, 2=XOR fill +// color: Rectangle color +// xStart/yStart: upper left point +// xEnd/yEnd: lower right point +void DWIN_Draw_Rectangle(uint8_t mode, uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd); + +// Draw a box +// mode: 0=frame, 1=fill, 2=XOR fill +// color: Rectangle color +// xStart/yStart: upper left point +// xSize/ySize: box size +inline void DWIN_Draw_Box(uint8_t mode, uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xSize, uint16_t ySize) { + DWIN_Draw_Rectangle(mode, color, xStart, yStart, xStart + xSize - 1, yStart + ySize - 1); +} + +// Move a screen area +// mode: 0, circle shift; 1, translation +// dir: 0=left, 1=right, 2=up, 3=down +// dis: Distance +// color: Fill color +// xStart/yStart: upper left point +// xEnd/yEnd: bottom right point +void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis, + uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd); + + +/*---------------------------------------- Text related functions ----------------------------------------*/ + +// Draw a string +// bShow: true=display background color; false=don't display background color +// size: Font size +// color: Character color +// bColor: Background color +// x/y: Upper-left coordinate of the string +// *string: The string +// rlimit: For draw less chars than string length use rlimit +void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit=0xFFFF); + +inline void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, FSTR_P const ftitle) { + #ifdef __AVR__ + char ctitle[strlen_P(FTOP(ftitle)) + 1]; + strcpy_P(ctitle, FTOP(ftitle)); + DWIN_Draw_String(bShow, size, color, bColor, x, y, ctitle); + #else + DWIN_Draw_String(bShow, size, color, bColor, x, y, FTOP(ftitle)); + #endif +} + +// Draw a positive integer +// bShow: true=display background color; false=don't display background color +// zeroFill: true=zero fill; false=no zero fill +// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space +// size: Font size +// color: Character color +// bColor: Background color +// iNum: Number of digits +// x/y: Upper-left coordinate +// value: Integer value +void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint32_t value); + +// Draw a floating point number +// bShow: true=display background color; false=don't display background color +// zeroFill: true=zero fill; false=no zero fill +// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space +// size: Font size +// color: Character color +// bColor: Background color +// iNum: Number of whole digits +// fNum: Number of decimal digits +// x/y: Upper-left point +// value: Float value +void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value); + +// Draw a floating point number +// value: positive unscaled float value +void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value); + +/*---------------------------------------- Picture related functions ----------------------------------------*/ + +// Draw JPG and cached in #0 virtual display area +// id: Picture ID +void DWIN_JPG_ShowAndCache(const uint8_t id); + +// Draw an Icon +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y); + +// Draw an Icon +// IBD: The icon background display: 0=Background filtering is not displayed, 1=Background display \\When setting the background filtering not to display, the background must be pure black +// BIR: Background image restoration: 0=Background image is not restored, 1=Automatically use virtual display area image for background restoration +// BFI: Background filtering strength: 0=normal, 1=enhanced, (only valid when the icon background display=0) +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(bool IBD, bool BIR, bool BFI, uint8_t libID, uint8_t picID, uint16_t x, uint16_t y); + +// Draw an Icon from SRAM +// IBD: The icon background display: 0=Background filtering is not displayed, 1=Background display \\When setting the background filtering not to display, the background must be pure black +// BIR: Background image restoration: 0=Background image is not restored, 1=Automatically use virtual display area image for background restoration +// BFI: Background filtering strength: 0=normal, 1=enhanced, (only valid when the icon background display=0) +// x/y: Upper-left point +// addr: SRAM address +void DWIN_ICON_Show(bool IBD, bool BIR, bool BFI, uint16_t x, uint16_t y, uint16_t addr); + +// Unzip the JPG picture to a virtual display area +// n: Cache index +// id: Picture ID +void DWIN_JPG_CacheToN(uint8_t n, uint8_t id); + +// Unzip the JPG picture to virtual display area #1 +// id: Picture ID +inline void DWIN_JPG_CacheTo1(uint8_t id) { DWIN_JPG_CacheToN(1, id); } + +// Animate a series of icons +// animID: Animation ID up to 16 +// animate: animation on or off +// libID: Icon library ID +// picIDs: Icon starting ID +// picIDe: Icon ending ID +// x/y: Upper-left point +// interval: Display time interval, unit 10mS +void DWIN_ICON_Animation(uint8_t animID, bool animate, uint8_t libID, uint8_t picIDs, uint8_t picIDe, uint16_t x, uint16_t y, uint16_t interval); + +// Animation Control +// state: 16 bits, each bit is the state of an animation id +void DWIN_ICON_AnimationControl(uint16_t state); diff --git a/src/lcd/e3v2/common/dwin_color.h b/src/lcd/e3v2/common/dwin_color.h new file mode 100644 index 0000000..d327f21 --- /dev/null +++ b/src/lcd/e3v2/common/dwin_color.h @@ -0,0 +1,44 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +// Extended and default UI Colors +#define RGB(R,G,B) (R << 11) | (G << 5) | (B) // R,B: 0..31; G: 0..63 +#define GetRColor(color) ((color >> 11) & 0x1F) +#define GetGColor(color) ((color >> 5) & 0x3F) +#define GetBColor(color) ((color >> 0) & 0x1F) + +#define Color_White 0xFFFF +#define Color_Yellow RGB(0x1F,0x3F,0x00) +#define Color_Red RGB(0x1F,0x00,0x00) +#define Color_Error_Red 0xB000 // Error! +#define Color_Bg_Red 0xF00F // Red background color +#define Color_Bg_Window 0x31E8 // Popup background color +#define Color_Bg_Blue 0x1125 // Dark blue background color +#define Color_Bg_Black 0x0841 // Black background color +#define Color_IconBlue 0x45FA // Lighter blue that matches icons/accents +#define Popup_Text_Color 0xD6BA // Popup font background color +#define Line_Color 0x3A6A // Split line color +#define Rectangle_Color 0xEE2F // Blue square cursor color +#define Percent_Color 0xFE29 // Percentage color +#define BarFill_Color 0x10E4 // Fill color of progress bar +#define Select_Color 0x33BB // Selected color diff --git a/src/lcd/e3v2/common/dwin_font.h b/src/lcd/e3v2/common/dwin_font.h new file mode 100644 index 0000000..10bb104 --- /dev/null +++ b/src/lcd/e3v2/common/dwin_font.h @@ -0,0 +1,40 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +typedef uint8_t fontid_t; + +/** + * 3-.0:The font size, 0x00-0x09, corresponds to the font size below: + * 0x00=6*12 0x01=8*16 0x02=10*20 0x03=12*24 0x04=14*28 + * 0x05=16*32 0x06=20*40 0x07=24*48 0x08=28*56 0x09=32*64 + */ +#define font6x12 0x00 +#define font8x16 0x01 +#define font10x20 0x02 +#define font12x24 0x03 +#define font14x28 0x04 +#define font16x32 0x05 +#define font20x40 0x06 +#define font24x48 0x07 +#define font28x56 0x08 +#define font32x64 0x09 diff --git a/src/lcd/e3v2/common/dwin_set.h b/src/lcd/e3v2/common/dwin_set.h new file mode 100644 index 0000000..7f44386 --- /dev/null +++ b/src/lcd/e3v2/common/dwin_set.h @@ -0,0 +1,147 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +// Picture ID +#define Language_English 1 +#define Language_Chinese 2 + +//#define USE_STOCK_DWIN_SET // Use the Creality stock DWIN_SET instead of Marlin's unified DWIN_SET by The-EG & thinkyhead +#ifdef USE_STOCK_DWIN_SET + #define ICON 9 // 9.ICO +#else + #define ICON 7 // 7.ICO +#endif + +#ifndef CORP_WEBSITE + #define CORP_WEBSITE WEBSITE_URL +#endif + +#define ICON_LOGO 0 +#define ICON_Print_0 1 +#define ICON_Print_1 2 +#define ICON_Prepare_0 3 +#define ICON_Prepare_1 4 +#define ICON_Control_0 5 +#define ICON_Control_1 6 +#define ICON_Leveling_0 7 +#define ICON_Leveling_1 8 +#define ICON_HotendTemp 9 +#define ICON_BedTemp 10 +#define ICON_Speed 11 +#define ICON_Zoffset 12 +#define ICON_Back 13 +#define ICON_File 14 +#define ICON_PrintTime 15 +#define ICON_RemainTime 16 +#define ICON_Setup_0 17 +#define ICON_Setup_1 18 +#define ICON_Pause_0 19 +#define ICON_Pause_1 20 +#define ICON_Continue_0 21 +#define ICON_Continue_1 22 +#define ICON_Stop_0 23 +#define ICON_Stop_1 24 +#define ICON_Bar 25 +#define ICON_More 26 + +#define ICON_Axis 27 +#define ICON_CloseMotor 28 +#define ICON_Homing 29 +#define ICON_SetHome 30 +#define ICON_PLAPreheat 31 +#define ICON_ABSPreheat 32 +#define ICON_Cool 33 +#define ICON_Language 34 + +#define ICON_MoveX 35 +#define ICON_MoveY 36 +#define ICON_MoveZ 37 +#define ICON_Extruder 38 + +#define ICON_Temperature 40 +#define ICON_Motion 41 +#define ICON_WriteEEPROM 42 +#define ICON_ReadEEPROM 43 +#define ICON_ResumeEEPROM 44 +#define ICON_Info 45 + +#define ICON_SetEndTemp 46 +#define ICON_SetBedTemp 47 +#define ICON_FanSpeed 48 +#define ICON_SetPLAPreheat 49 +#define ICON_SetABSPreheat 50 + +#define ICON_MaxSpeed 51 +#define ICON_MaxAccelerated 52 +#define ICON_MaxJerk 53 +#define ICON_Step 54 +#define ICON_PrintSize 55 +#define ICON_Version 56 +#define ICON_Contact 57 +#define ICON_StockConfiguration 58 +#define ICON_MaxSpeedX 59 +#define ICON_MaxSpeedY 60 +#define ICON_MaxSpeedZ 61 +#define ICON_MaxSpeedE 62 +#define ICON_MaxAccX 63 +#define ICON_MaxAccY 64 +#define ICON_MaxAccZ 65 +#define ICON_MaxAccE 66 +#define ICON_MaxSpeedJerkX 67 +#define ICON_MaxSpeedJerkY 68 +#define ICON_MaxSpeedJerkZ 69 +#define ICON_MaxSpeedJerkE 70 +#define ICON_StepX 71 +#define ICON_StepY 72 +#define ICON_StepZ 73 +#define ICON_StepE 74 +#define ICON_Setspeed 75 +#define ICON_SetZOffset 76 +#define ICON_Rectangle 77 +#define ICON_BLTouch 78 +#define ICON_TempTooLow 79 +#define ICON_AutoLeveling 80 +#define ICON_TempTooHigh 81 +#define ICON_NoTips_C 82 +#define ICON_NoTips_E 83 +#define ICON_Continue_C 84 +#define ICON_Continue_E 85 +#define ICON_Cancel_C 86 +#define ICON_Cancel_E 87 +#define ICON_Confirm_C 88 +#define ICON_Confirm_E 89 +#define ICON_Info_0 90 +#define ICON_Info_1 91 + +#define ICON_Folder ICON_More +#define ICON_AdvSet ICON_Language +#define ICON_HomeOffset ICON_AdvSet +#define ICON_HomeOffsetX ICON_StepX +#define ICON_HomeOffsetY ICON_StepY +#define ICON_HomeOffsetZ ICON_StepZ +#define ICON_ProbeOffset ICON_AdvSet +#define ICON_ProbeOffsetX ICON_StepX +#define ICON_ProbeOffsetY ICON_StepY +#define ICON_ProbeOffsetZ ICON_StepZ +#define ICON_PIDNozzle ICON_SetEndTemp +#define ICON_PIDbed ICON_SetBedTemp diff --git a/src/lcd/e3v2/common/encoder.cpp b/src/lcd/e3v2/common/encoder.cpp new file mode 100644 index 0000000..f14d63e --- /dev/null +++ b/src/lcd/e3v2/common/encoder.cpp @@ -0,0 +1,253 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/***************************************************************************** + * @file lcd/e3v2/common/encoder.cpp + * @brief Rotary encoder functions + *****************************************************************************/ + +#include "../../../inc/MarlinConfigPre.h" + +#if HAS_DWIN_E3V2 + +#include "encoder.h" +#include "../../buttons.h" + +#include "../../../MarlinCore.h" +#include "../../marlinui.h" +#include "../../../HAL/shared/Delay.h" + +#if HAS_SOUND + #include "../../../libs/buzzer.h" +#endif + +#include + +#ifndef ENCODER_PULSES_PER_STEP + #define ENCODER_PULSES_PER_STEP 4 +#endif + +ENCODER_Rate EncoderRate; + +// TODO: Replace with ui.quick_feedback +void Encoder_tick() { + TERN_(HAS_BEEPER, if (ui.sound_on) buzzer.click(10)); +} + +// Encoder initialization +void Encoder_Configuration() { + #if BUTTON_EXISTS(EN1) + SET_INPUT_PULLUP(BTN_EN1); + #endif + #if BUTTON_EXISTS(EN2) + SET_INPUT_PULLUP(BTN_EN2); + #endif + #if BUTTON_EXISTS(ENC) + SET_INPUT_PULLUP(BTN_ENC); + #endif + #if HAS_BEEPER + SET_OUTPUT(BEEPER_PIN); // TODO: Use buzzer.h which already inits this + #endif +} + +// Analyze encoder value and return state +EncoderState Encoder_ReceiveAnalyze() { + const millis_t now = millis(); + static uint8_t lastEncoderBits; + uint8_t newbutton = 0; + static signed char temp_diff = 0; + + EncoderState temp_diffState = ENCODER_DIFF_NO; + if (BUTTON_PRESSED(EN1)) newbutton |= EN_A; + if (BUTTON_PRESSED(EN2)) newbutton |= EN_B; + if (BUTTON_PRESSED(ENC)) { + static millis_t next_click_update_ms; + if (ELAPSED(now, next_click_update_ms)) { + next_click_update_ms = millis() + 300; + Encoder_tick(); + #if PIN_EXISTS(LCD_LED) + //LED_Action(); + #endif + if (!ui.backlight) ui.refresh_brightness(); + const bool was_waiting = wait_for_user; + wait_for_user = false; + return was_waiting ? ENCODER_DIFF_NO : ENCODER_DIFF_ENTER; + } + else return ENCODER_DIFF_NO; + } + if (newbutton != lastEncoderBits) { + switch (newbutton) { + case ENCODER_PHASE_0: + if (lastEncoderBits == ENCODER_PHASE_3) temp_diff++; + else if (lastEncoderBits == ENCODER_PHASE_1) temp_diff--; + break; + case ENCODER_PHASE_1: + if (lastEncoderBits == ENCODER_PHASE_0) temp_diff++; + else if (lastEncoderBits == ENCODER_PHASE_2) temp_diff--; + break; + case ENCODER_PHASE_2: + if (lastEncoderBits == ENCODER_PHASE_1) temp_diff++; + else if (lastEncoderBits == ENCODER_PHASE_3) temp_diff--; + break; + case ENCODER_PHASE_3: + if (lastEncoderBits == ENCODER_PHASE_2) temp_diff++; + else if (lastEncoderBits == ENCODER_PHASE_0) temp_diff--; + break; + } + lastEncoderBits = newbutton; + } + + if (ABS(temp_diff) >= ENCODER_PULSES_PER_STEP) { + if (temp_diff > 0) temp_diffState = TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CCW, ENCODER_DIFF_CW); + else temp_diffState = TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CW, ENCODER_DIFF_CCW); + + #if ENABLED(ENCODER_RATE_MULTIPLIER) + + millis_t ms = millis(); + int32_t encoderMultiplier = 1; + + // if must encoder rati multiplier + if (EncoderRate.enabled) { + const float abs_diff = ABS(temp_diff), + encoderMovementSteps = abs_diff / (ENCODER_PULSES_PER_STEP); + if (EncoderRate.lastEncoderTime) { + // Note that the rate is always calculated between two passes through the + // loop and that the abs of the temp_diff value is tracked. + const float encoderStepRate = encoderMovementSteps / float(ms - EncoderRate.lastEncoderTime) * 1000; + if (encoderStepRate >= ENCODER_100X_STEPS_PER_SEC) encoderMultiplier = 100; + else if (encoderStepRate >= ENCODER_10X_STEPS_PER_SEC) encoderMultiplier = 10; + #if ENCODER_5X_STEPS_PER_SEC + else if (encoderStepRate >= ENCODER_5X_STEPS_PER_SEC) encoderMultiplier = 5; + #endif + } + EncoderRate.lastEncoderTime = ms; + } + + #else + + constexpr int32_t encoderMultiplier = 1; + + #endif + + // EncoderRate.encoderMoveValue += (temp_diff * encoderMultiplier) / (ENCODER_PULSES_PER_STEP); + EncoderRate.encoderMoveValue = (temp_diff * encoderMultiplier) / (ENCODER_PULSES_PER_STEP); + if (EncoderRate.encoderMoveValue < 0) EncoderRate.encoderMoveValue = -EncoderRate.encoderMoveValue; + + temp_diff = 0; + } + return temp_diffState; +} + +#if PIN_EXISTS(LCD_LED) + + // Take the low 24 valid bits 24Bit: G7 G6 G5 G4 G3 G2 G1 G0 R7 R6 R5 R4 R3 R2 R1 R0 B7 B6 B5 B4 B3 B2 B1 B0 + uint16_t LED_DataArray[LED_NUM]; + + // LED light operation + void LED_Action() { + LED_Control(RGB_SCALE_WARM_WHITE,0x0F); + delay(30); + LED_Control(RGB_SCALE_WARM_WHITE,0x00); + } + + // LED initialization + void LED_Configuration() { + SET_OUTPUT(LCD_LED_PIN); + } + + // LED write data + void LED_WriteData() { + uint8_t tempCounter_LED, tempCounter_Bit; + for (tempCounter_LED = 0; tempCounter_LED < LED_NUM; tempCounter_LED++) { + for (tempCounter_Bit = 0; tempCounter_Bit < 24; tempCounter_Bit++) { + if (LED_DataArray[tempCounter_LED] & (0x800000 >> tempCounter_Bit)) { + LED_DATA_HIGH; + DELAY_NS(300); + LED_DATA_LOW; + DELAY_NS(200); + } + else { + LED_DATA_HIGH; + LED_DATA_LOW; + DELAY_NS(200); + } + } + } + } + + // LED control + // RGB_Scale: RGB color ratio + // luminance: brightness (0~0xFF) + void LED_Control(const uint8_t RGB_Scale, const uint8_t luminance) { + for (uint8_t i = 0; i < LED_NUM; i++) { + LED_DataArray[i] = 0; + switch (RGB_Scale) { + case RGB_SCALE_R10_G7_B5: LED_DataArray[i] = (luminance * 10/10) << 8 | (luminance * 7/10) << 16 | luminance * 5/10; break; + case RGB_SCALE_R10_G7_B4: LED_DataArray[i] = (luminance * 10/10) << 8 | (luminance * 7/10) << 16 | luminance * 4/10; break; + case RGB_SCALE_R10_G8_B7: LED_DataArray[i] = (luminance * 10/10) << 8 | (luminance * 8/10) << 16 | luminance * 7/10; break; + } + } + LED_WriteData(); + } + + // LED gradient control + // RGB_Scale: RGB color ratio + // luminance: brightness (0~0xFF) + // change_Time: gradient time (ms) + void LED_GraduallyControl(const uint8_t RGB_Scale, const uint8_t luminance, const uint16_t change_Interval) { + struct { uint8_t g, r, b; } led_data[LED_NUM]; + for (uint8_t i = 0; i < LED_NUM; i++) { + switch (RGB_Scale) { + case RGB_SCALE_R10_G7_B5: + led_data[i] = { luminance * 7/10, luminance * 10/10, luminance * 5/10 }; + break; + case RGB_SCALE_R10_G7_B4: + led_data[i] = { luminance * 7/10, luminance * 10/10, luminance * 4/10 }; + break; + case RGB_SCALE_R10_G8_B7: + led_data[i] = { luminance * 8/10, luminance * 10/10, luminance * 7/10 }; + break; + } + } + + struct { bool g, r, b; } led_flag = { false, false, false }; + for (uint8_t i = 0; i < LED_NUM; i++) { + while (1) { + const uint8_t g = uint8_t(LED_DataArray[i] >> 16), + r = uint8_t(LED_DataArray[i] >> 8), + b = uint8_t(LED_DataArray[i]); + if (g == led_data[i].g) led_flag.g = true; + else LED_DataArray[i] += (g > led_data[i].g) ? -0x010000 : 0x010000; + if (r == led_data[i].r) led_flag.r = true; + else LED_DataArray[i] += (r > led_data[i].r) ? -0x000100 : 0x000100; + if (b == led_data[i].b) led_flag.b = true; + else LED_DataArray[i] += (b > led_data[i].b) ? -0x000001 : 0x000001; + LED_WriteData(); + if (led_flag.r && led_flag.g && led_flag.b) break; + delay(change_Interval); + } + } + } + +#endif // LCD_LED + +#endif // HAS_DWIN_E3V2 diff --git a/src/lcd/e3v2/common/encoder.h b/src/lcd/e3v2/common/encoder.h new file mode 100644 index 0000000..3ab8c3b --- /dev/null +++ b/src/lcd/e3v2/common/encoder.h @@ -0,0 +1,111 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/***************************************************************************** + * @file lcd/e3v2/common/encoder.h + * @brief Rotary encoder functions + ****************************************************************************/ + +#include "../../../inc/MarlinConfig.h" + +/*********************** Encoder Set ***********************/ + +typedef struct { + bool enabled = false; + int encoderMoveValue = 0; + millis_t lastEncoderTime = 0; +} ENCODER_Rate; + +extern ENCODER_Rate EncoderRate; + +typedef enum { + ENCODER_DIFF_NO = 0, // no state + ENCODER_DIFF_CW = 1, // clockwise rotation + ENCODER_DIFF_CCW = 2, // counterclockwise rotation + ENCODER_DIFF_ENTER = 3 // click +} EncoderState; + +#define ENCODER_WAIT_MS 20 + +// Encoder initialization +void Encoder_Configuration(); + +// Analyze encoder value and return state +EncoderState Encoder_ReceiveAnalyze(); + +inline EncoderState get_encoder_state() { + static millis_t Encoder_ms = 0; + const millis_t ms = millis(); + if (PENDING(ms, Encoder_ms)) return ENCODER_DIFF_NO; + const EncoderState state = Encoder_ReceiveAnalyze(); + if (state != ENCODER_DIFF_NO) Encoder_ms = ms + ENCODER_WAIT_MS; + return state; +} + +template +inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) { + if (encoder_diffState == ENCODER_DIFF_CW) + valref += EncoderRate.encoderMoveValue; + else if (encoder_diffState == ENCODER_DIFF_CCW) + valref -= EncoderRate.encoderMoveValue; + return encoder_diffState == ENCODER_DIFF_ENTER; +} + +/*********************** Encoder LED ***********************/ + +#if PIN_EXISTS(LCD_LED) + + #define LED_NUM 4 + #define LED_DATA_HIGH WRITE(LCD_LED_PIN, 1) + #define LED_DATA_LOW WRITE(LCD_LED_PIN, 0) + + #define RGB_SCALE_R10_G7_B5 1 + #define RGB_SCALE_R10_G7_B4 2 + #define RGB_SCALE_R10_G8_B7 3 + #define RGB_SCALE_NEUTRAL_WHITE RGB_SCALE_R10_G7_B5 + #define RGB_SCALE_WARM_WHITE RGB_SCALE_R10_G7_B4 + #define RGB_SCALE_COOL_WHITE RGB_SCALE_R10_G8_B7 + + extern unsigned int LED_DataArray[LED_NUM]; + + // LED light operation + void LED_Action(); + + // LED initialization + void LED_Configuration(); + + // LED write data + void LED_WriteData(); + + // LED control + // RGB_Scale: RGB color ratio + // luminance: brightness (0~0xFF) + void LED_Control(const uint8_t RGB_Scale, const uint8_t luminance); + + // LED gradient control + // RGB_Scale: RGB color ratio + // luminance: brightness (0~0xFF) + // change_Time: gradient time (ms) + void LED_GraduallyControl(const uint8_t RGB_Scale, const uint8_t luminance, const uint16_t change_Interval); + +#endif // LCD_LED diff --git a/src/lcd/e3v2/creality/dwin.cpp b/src/lcd/e3v2/creality/dwin.cpp new file mode 100644 index 0000000..1232c8e --- /dev/null +++ b/src/lcd/e3v2/creality/dwin.cpp @@ -0,0 +1,4317 @@ +/** + * 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 . + * + */ + +/** + * DWIN by Creality3D + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_CREALITY_LCD) + +#include "dwin.h" + +//#define USE_STRING_HEADINGS +//#define USE_STRING_TITLES + +#if DISABLED(PROBE_MANUALLY) && ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT) + #define HAS_ONESTEP_LEVELING 1 +#endif + +#if ANY(BABYSTEPPING, HAS_BED_PROBE, HAS_WORKSPACE_OFFSET) + #define HAS_ZOFFSET_ITEM 1 +#endif + +#if !HAS_BED_PROBE && ENABLED(BABYSTEPPING) + #define JUST_BABYSTEP 1 +#endif + +#include "../../fontutils.h" +#include "../../marlinui.h" + +#include "../../../sd/cardreader.h" + +#include "../../../MarlinCore.h" +#include "../../../core/serial.h" +#include "../../../core/macros.h" +#include "../../../gcode/queue.h" + +#include "../../../module/temperature.h" +#include "../../../module/printcounter.h" +#include "../../../module/motion.h" +#include "../../../module/planner.h" + +#if ENABLED(EEPROM_SETTINGS) + #include "../../../module/settings.h" +#endif + +#if ENABLED(HOST_ACTION_COMMANDS) + #include "../../../feature/host_actions.h" +#endif + +#if HAS_ONESTEP_LEVELING + #include "../../../feature/bedlevel/bedlevel.h" +#endif + +#if HAS_BED_PROBE + #include "../../../module/probe.h" +#endif + +#if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + #include "../../../feature/babystep.h" +#endif + +#if ENABLED(POWER_LOSS_RECOVERY) + #include "../../../feature/powerloss.h" +#endif + +#include +#include +#include + +#ifndef MACHINE_SIZE + #define MACHINE_SIZE STRINGIFY(X_BED_SIZE) "x" STRINGIFY(Y_BED_SIZE) "x" STRINGIFY(Z_MAX_POS) +#endif + +#define PAUSE_HEAT + +#define MENU_CHAR_LIMIT 24 +#define STATUS_Y 354 + +// Print speed limit +#define MIN_PRINT_SPEED 10 +#define MAX_PRINT_SPEED 999 + +// Feedspeed limit (max feedspeed = DEFAULT_MAX_FEEDRATE * 2) +#define MIN_MAXFEEDSPEED 1 +#define MIN_MAXACCELERATION 1 +#define MIN_MAXJERK 0.1 +#define MIN_STEP 1 + +#define FEEDRATE_E (60) + +// Minimum unit (0.1) : multiple (10) +#define UNITFDIGITS 1 +#define MINUNITMULT pow(10, UNITFDIGITS) + +#define ENCODER_WAIT_MS 20 +#define DWIN_VAR_UPDATE_INTERVAL 1024 +#define DWIN_SCROLL_UPDATE_INTERVAL SEC_TO_MS(2) +#define DWIN_REMAIN_TIME_UPDATE_INTERVAL SEC_TO_MS(20) + +#define TROWS 6 // Total rows +constexpr uint16_t MROWS = TROWS - 1, // Last Row Index + TITLE_HEIGHT = 30, // Title bar height + MLINE = 53, // Menu line height + LBLX = 60, // Menu item label X + MENU_CHR_W = 8, STAT_CHR_W = 10; + +#define MBASE(L) (49 + MLINE * (L)) +#define EBASE(L) (MBASE(L) - 2 * DISABLED(USE_STRING_TITLES)) + +#define BABY_Z_VAR TERN(HAS_BED_PROBE, probe.offset.z, dwin_zoffset) + +#define DWIN_BOTTOM (DWIN_HEIGHT-1) +#define DWIN_RIGHT (DWIN_WIDTH-1) + +// Value Init +HMI_value_t HMI_ValueStruct; +HMI_flag_t HMI_flag{0}; + +millis_t dwin_heat_time = 0; + +uint8_t checkkey = 0; + +enum SelectItem : uint8_t { + PAGE_PRINT = 0, + PAGE_PREPARE, + PAGE_CONTROL, + PAGE_INFO_LEVELING, + + PRINT_SETUP = 0, + PRINT_PAUSE_RESUME, + PRINT_STOP +}; + +typedef struct { + uint8_t now, last; + void set(uint8_t v) { now = last = v; } + void reset() { set(0); } + bool changed() { bool c = (now != last); if (c) last = now; return c; } + bool dec() { if (now) now--; return changed(); } + bool inc(uint8_t v) { if (now < (v - 1)) now++; else now = (v - 1); return changed(); } +} select_t; + +select_t select_page{0}, select_file{0}, select_print{0}, select_prepare{0} + , select_control{0}, select_axis{0}, select_temp{0}, select_motion{0}, select_tune{0} + , select_advset{0}, select_speed{0}, select_acc{0}, select_jerk{0}, select_step{0}, select_item{0}; + +#if HAS_PREHEAT + select_t select_PLA{0}; + #if PREHEAT_COUNT > 1 + select_t select_ABS{0}; + #endif +#endif + +uint8_t index_file = MROWS, + index_prepare = MROWS, + index_control = MROWS, + index_leveling = MROWS, + index_tune = MROWS, + index_advset = MROWS; + +bool dwin_abort_flag = false; // Flag to reset feedrate, return to Home + +constexpr float default_max_feedrate[] = DEFAULT_MAX_FEEDRATE; +constexpr float default_max_acceleration[] = DEFAULT_MAX_ACCELERATION; + +#if HAS_CLASSIC_JERK + constexpr float default_max_jerk[] = { DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_EJERK }; +#endif + +static uint8_t _card_percent = 0; +static uint16_t _remain_time = 0; + +#if ENABLED(PAUSE_HEAT) + #if HAS_HOTEND + uint16_t resume_hotend_temp = 0; + #endif + #if HAS_HEATED_BED + uint16_t resume_bed_temp = 0; + #endif +#endif + +#if HAS_ZOFFSET_ITEM + float dwin_zoffset = 0, last_zoffset = 0; +#endif + +#define DWIN_LANGUAGE_EEPROM_ADDRESS 0x01 // Between 0x01 and 0x63 (EEPROM_OFFSET-1) + // BL24CXX::check() uses 0x00 + +inline bool HMI_IsChinese() { return HMI_flag.language == DWIN_CHINESE; } + +void HMI_SetLanguageCache() { + DWIN_JPG_CacheTo1(HMI_IsChinese() ? Language_Chinese : Language_English); +} + +void HMI_SetLanguage() { + #if BOTH(EEPROM_SETTINGS, IIC_BL24CXX_EEPROM) + BL24CXX::read(DWIN_LANGUAGE_EEPROM_ADDRESS, (uint8_t*)&HMI_flag.language, sizeof(HMI_flag.language)); + #endif + HMI_SetLanguageCache(); +} + +void HMI_ToggleLanguage() { + HMI_flag.language = HMI_IsChinese() ? DWIN_ENGLISH : DWIN_CHINESE; + HMI_SetLanguageCache(); + #if BOTH(EEPROM_SETTINGS, IIC_BL24CXX_EEPROM) + BL24CXX::write(DWIN_LANGUAGE_EEPROM_ADDRESS, (uint8_t*)&HMI_flag.language, sizeof(HMI_flag.language)); + #endif +} + +typedef struct { uint16_t x, y, w, h; } icon_info_t; +typedef struct { uint16_t x, y[2], w, h; } text_info_t; + +void ICON_Button(const bool here, const int iconid, const icon_info_t &ico, const text_info_t (&txt)[2]) { + const bool cn = HMI_IsChinese(); + DWIN_ICON_Show(ICON, iconid + here, ico.x, ico.y); + if (here) DWIN_Draw_Rectangle(0, Color_White, ico.x, ico.y, ico.x + ico.w - 1, ico.y + ico.h - 1); + DWIN_Frame_AreaCopy(1, txt[cn].x, txt[cn].y[here], txt[cn].x + txt[cn].w - 1, txt[cn].y[here] + txt[cn].h - 1, ico.x + (ico.w - txt[cn].w) / 2, (ico.y + ico.h - 28) - txt[cn].h/2); +} + +// +// Main Menu: "Print" +// +void ICON_Print() { + constexpr icon_info_t ico = { 17, 110, 110, 100 }; + constexpr text_info_t txt[2] = { + { 1, { 417, 449 }, 30, 14 }, + { 1, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_page.now == PAGE_PRINT, ICON_Print_0, ico, txt); +} + +// +// Main Menu: "Prepare" +// +void ICON_Prepare() { + constexpr icon_info_t ico = { 145, 110, 110, 100 }; + constexpr text_info_t txt[2] = { + { 33, { 417, 449 }, 51, 14 }, + { 31, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_page.now == PAGE_PREPARE, ICON_Prepare_0, ico, txt); +} + +// +// Main Menu: "Control" +// +void ICON_Control() { + constexpr icon_info_t ico = { 17, 226, 110, 100 }; + constexpr text_info_t txt[2] = { + { 85, { 417, 449 }, 46, 14 }, + { 61, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_page.now == PAGE_CONTROL, ICON_Control_0, ico, txt); +} + +// +// Main Menu: "Info" +// +void ICON_StartInfo() { + constexpr icon_info_t ico = { 145, 226, 110, 100 }; + constexpr text_info_t txt[2] = { + { 133, { 417, 449 }, 23, 14 }, + { 91, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_page.now == PAGE_INFO_LEVELING, ICON_Info_0, ico, txt); +} + +// +// Main Menu: "Level" +// +void ICON_Leveling() { + constexpr icon_info_t ico = { 145, 226, 110, 100 }; + constexpr text_info_t txt[2] = { + { 88, { 433, 464 }, 36, 14 }, + { 211, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_page.now == PAGE_INFO_LEVELING, ICON_Leveling_0, ico, txt); +} + +// +// Printing: "Tune" +// +void ICON_Tune() { + constexpr icon_info_t ico = { 8, 232, 80, 100 }; + constexpr text_info_t txt[2] = { + { 0, { 433, 464 }, 32, 14 }, + { 121, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_print.now == PRINT_SETUP, ICON_Setup_0, ico, txt); +} + +// +// Printing: "Pause" +// +void ICON_Pause() { + constexpr icon_info_t ico = { 96, 232, 80, 100 }; + constexpr text_info_t txt[2] = { + { 157, { 417, 449 }, 39, 14 }, + { 181, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_print.now == PRINT_PAUSE_RESUME, ICON_Pause_0, ico, txt); +} + +// +// Printing: "Resume" +// +void ICON_Resume() { + constexpr icon_info_t ico = { 96, 232, 80, 100 }; + constexpr text_info_t txt[2] = { + { 33, { 433, 464 }, 53, 14 }, + { 1, { 405, 447 }, 27, 15 } + }; + ICON_Button(select_print.now == PRINT_PAUSE_RESUME, ICON_Continue_0, ico, txt); +} + +void ICON_ResumeOrPause() { + if (printingIsPaused() || HMI_flag.pause_flag || HMI_flag.pause_action) + ICON_Resume(); + else + ICON_Pause(); +} + +// +// Printing: "Stop" +// +void ICON_Stop() { + constexpr icon_info_t ico = { 184, 232, 80, 100 }; + constexpr text_info_t txt[2] = { + { 196, { 417, 449 }, 29, 14 }, + { 151, { 405, 447 }, 27, 12 } + }; + ICON_Button(select_print.now == PRINT_STOP, ICON_Stop_0, ico, txt); +} + +inline void Clear_Title_Bar() { + DWIN_Draw_Box(1, Color_Bg_Blue, 0, 0, DWIN_WIDTH, TITLE_HEIGHT); +} + +void Draw_Title(FSTR_P ftitle) { + DWIN_Draw_String(false, DWIN_FONT_HEAD, Color_White, Color_Bg_Blue, 14, 4, ftitle); +} + +inline void Clear_Menu_Area() { + DWIN_Draw_Box(1, Color_Bg_Black, 0, TITLE_HEIGHT, DWIN_WIDTH, STATUS_Y - TITLE_HEIGHT); +} + +void Clear_Main_Window() { + Clear_Title_Bar(); + Clear_Menu_Area(); +} + +void Clear_Popup_Area() { + Clear_Title_Bar(); + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, 31, DWIN_WIDTH, DWIN_HEIGHT); +} + +void Draw_Popup_Bkgd_105() { + DWIN_Draw_Rectangle(1, Color_Bg_Window, 14, 105, 258, 374); +} + +void Draw_More_Icon(const uint8_t line) { + DWIN_ICON_Show(ICON, ICON_More, 226, MBASE(line) - 3); +} + +void Draw_Menu_Cursor(const uint8_t line) { + //DWIN_ICON_Show(ICON, ICON_Rectangle, 0, MBASE(line) - 18); + DWIN_Draw_Rectangle(1, Rectangle_Color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20); +} + +void Erase_Menu_Cursor(const uint8_t line) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20); +} + +void Move_Highlight(const int16_t from, const uint16_t newline) { + Erase_Menu_Cursor(newline - from); + Draw_Menu_Cursor(newline); +} + +void Add_Menu_Line() { + Move_Highlight(1, MROWS); + DWIN_Draw_Line(Line_Color, 16, MBASE(MROWS + 1) - 20, 256, MBASE(MROWS + 1) - 19); +} + +void Scroll_Menu(const uint8_t dir) { + DWIN_Frame_AreaMove(1, dir, MLINE, Color_Bg_Black, 0, 31, DWIN_WIDTH, 349); + switch (dir) { + case DWIN_SCROLL_DOWN: Move_Highlight(-1, 0); break; + case DWIN_SCROLL_UP: Add_Menu_Line(); break; + } +} + +inline uint16_t nr_sd_menu_items() { + return card.get_num_Files() + !card.flag.workDirIsRoot; +} + +void Erase_Menu_Text(const uint8_t line) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(line) - 14, 271, MBASE(line) + 28); +} + +void Draw_Menu_Icon(const uint8_t line, const uint8_t icon) { + DWIN_ICON_Show(ICON, icon, 26, MBASE(line) - 3); +} + +void _Decorate_Menu_Item(const uint8_t line, const uint8_t icon, bool more) { + if (icon) Draw_Menu_Icon(line, icon); + if (more) Draw_More_Icon(line); +} +void Draw_Menu_Item(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false) { + if (label) DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, LBLX, MBASE(line) - 1, (char*)label); + _Decorate_Menu_Item(line, icon, more); +} +void Draw_Menu_Item(const uint8_t line, const uint8_t icon=0, FSTR_P const flabel=nullptr, bool more=false) { + if (flabel) DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, LBLX, MBASE(line) - 1, flabel); + _Decorate_Menu_Item(line, icon, more); +} + +void Draw_Menu_Line(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false) { + Draw_Menu_Item(line, icon, label, more); + DWIN_Draw_Line(Line_Color, 16, MBASE(line) + 33, 256, MBASE(line) + 34); +} + +void Draw_Menu_Line(const uint8_t line, const uint8_t icon, FSTR_P const flabel, bool more=false) { + Draw_Menu_Item(line, icon, flabel, more); + DWIN_Draw_Line(Line_Color, 16, MBASE(line) + 33, 256, MBASE(line) + 34); +} + +void Draw_Checkbox_Line(const uint8_t line, const bool ison) { + const uint16_t x = 225, y = EBASE(line) - 2; + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x + 5, y, ison ? F("X") : F(" ")); + DWIN_Draw_Rectangle(0, Color_White, x + 2, y + 2, x + 16, y + 16); +} + +// AreaCopy for a Menu Item +void Item_AreaCopy(const uint16_t x1, const uint16_t y1, const uint16_t x2, const uint16_t y2, const uint8_t row=0, const uint16_t inset=0, const uint16_t yadd=0) { + DWIN_Frame_AreaCopy(1, x1, y1, x2, y2, LBLX + inset, MBASE(row) + yadd); +} + +// AreaCopy for a Screen Title +void DWIN_Frame_TitleCopy(const uint16_t x1, const uint16_t y1, const uint16_t w, const uint16_t h) { + DWIN_Frame_AreaCopy(1, x1, y1, x1 + w - 1, y1 + h - 1, (DWIN_WIDTH - w) / 2, (TITLE_HEIGHT - h) / 2); +} + +// Draw "Back" line at the top +void Draw_Back_First(const bool is_sel=true) { + Draw_Menu_Line(0, ICON_Back); + if (HMI_IsChinese()) + Item_AreaCopy(129, 72, 156, 84); + else + Item_AreaCopy(223, 179, 254, 189); + if (is_sel) Draw_Menu_Cursor(0); +} + +// +// Draw Menus +// +#define CASE_BACK 0 + +#define MOTION_CASE_RATE 1 +#define MOTION_CASE_ACCEL 2 +#define MOTION_CASE_JERK (MOTION_CASE_ACCEL + ENABLED(HAS_CLASSIC_JERK)) +#define MOTION_CASE_STEPS (MOTION_CASE_JERK + 1) +#define MOTION_CASE_TOTAL MOTION_CASE_STEPS + +#define PREPARE_CASE_MOVE 1 +#define PREPARE_CASE_DISA 2 +#define PREPARE_CASE_HOME 3 +#define PREPARE_CASE_ZOFF (PREPARE_CASE_HOME + ENABLED(HAS_ZOFFSET_ITEM)) +#define PREPARE_CASE_PLA (PREPARE_CASE_ZOFF + ENABLED(HAS_PREHEAT)) +#define PREPARE_CASE_ABS (PREPARE_CASE_PLA + (TERN0(HAS_PREHEAT, PREHEAT_COUNT > 1))) +#define PREPARE_CASE_COOL (PREPARE_CASE_ABS + EITHER(HAS_HOTEND, HAS_HEATED_BED)) +#define PREPARE_CASE_LANG (PREPARE_CASE_COOL + 1) +#define PREPARE_CASE_TOTAL PREPARE_CASE_LANG + +#define CONTROL_CASE_TEMP 1 +#define CONTROL_CASE_MOVE (CONTROL_CASE_TEMP + 1) +#define CONTROL_CASE_SAVE (CONTROL_CASE_MOVE + ENABLED(EEPROM_SETTINGS)) +#define CONTROL_CASE_LOAD (CONTROL_CASE_SAVE + ENABLED(EEPROM_SETTINGS)) +#define CONTROL_CASE_RESET (CONTROL_CASE_LOAD + ENABLED(EEPROM_SETTINGS)) +#define CONTROL_CASE_ADVSET (CONTROL_CASE_RESET + 1) +#define CONTROL_CASE_INFO (CONTROL_CASE_ADVSET + 1) +#define CONTROL_CASE_TOTAL CONTROL_CASE_INFO + +#define TUNE_CASE_SPEED 1 +#define TUNE_CASE_TEMP (TUNE_CASE_SPEED + ENABLED(HAS_HOTEND)) +#define TUNE_CASE_BED (TUNE_CASE_TEMP + ENABLED(HAS_HEATED_BED)) +#define TUNE_CASE_FAN (TUNE_CASE_BED + ENABLED(HAS_FAN)) +#define TUNE_CASE_ZOFF (TUNE_CASE_FAN + ENABLED(HAS_ZOFFSET_ITEM)) +#define TUNE_CASE_TOTAL TUNE_CASE_ZOFF + +#define TEMP_CASE_TEMP (0 + ENABLED(HAS_HOTEND)) +#define TEMP_CASE_BED (TEMP_CASE_TEMP + ENABLED(HAS_HEATED_BED)) +#define TEMP_CASE_FAN (TEMP_CASE_BED + ENABLED(HAS_FAN)) +#define TEMP_CASE_PLA (TEMP_CASE_FAN + ENABLED(HAS_PREHEAT)) +#define TEMP_CASE_ABS (TEMP_CASE_PLA + (TERN0(HAS_PREHEAT, PREHEAT_COUNT > 1))) +#define TEMP_CASE_TOTAL TEMP_CASE_ABS + +#define PREHEAT_CASE_TEMP (0 + ENABLED(HAS_HOTEND)) +#define PREHEAT_CASE_BED (PREHEAT_CASE_TEMP + ENABLED(HAS_HEATED_BED)) +#define PREHEAT_CASE_FAN (PREHEAT_CASE_BED + ENABLED(HAS_FAN)) +#define PREHEAT_CASE_SAVE (PREHEAT_CASE_FAN + ENABLED(EEPROM_SETTINGS)) +#define PREHEAT_CASE_TOTAL PREHEAT_CASE_SAVE + +#define ADVSET_CASE_HOMEOFF 1 +#define ADVSET_CASE_PROBEOFF (ADVSET_CASE_HOMEOFF + ENABLED(HAS_ONESTEP_LEVELING)) +#define ADVSET_CASE_HEPID (ADVSET_CASE_PROBEOFF + ENABLED(HAS_HOTEND)) +#define ADVSET_CASE_BEDPID (ADVSET_CASE_HEPID + ENABLED(HAS_HEATED_BED)) +#define ADVSET_CASE_PWRLOSSR (ADVSET_CASE_BEDPID + ENABLED(POWER_LOSS_RECOVERY)) +#define ADVSET_CASE_TOTAL ADVSET_CASE_PWRLOSSR + +// +// Draw Menus +// + +void say_move_en(const uint8_t row) { + Item_AreaCopy( 69, 61, 102, 71, row); // "Move" +} +void say_max_en(const uint8_t row) { + Item_AreaCopy( 75, 119, 100, 129, row); // "Max" +} +void say_jerk_en(const uint8_t row) { + Item_AreaCopy(104, 119, 128, 129, row, 30); // "Jerk" +} +void say_speed_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(133, 119, 172, 132, row, inset); // "Speed" +} +void say_max_accel_en(const uint8_t row) { + say_max_en(row); // "Max" + Item_AreaCopy( 0, 135, 79, 145, row, 30); // "Acceleration" +} +void say_max_jerk_speed_en(const uint8_t row) { + Item_AreaCopy( 75, 119, 172, 132, row); // "Max Jerk Speed" +} +void say_x_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(175, 119, 184, 129, row, inset); // "X" +} +void say_y_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(184, 119, 192, 129, row, inset); // "Y" +} +void say_z_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(193, 119, 201, 129, row, inset); // "Z" +} +void say_e_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(201, 119, 209, 129, row, inset); // "E" +} +void say_pla_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(131, 164, 153, 174, row, inset); // "PLA" +} +void say_abs_en(const uint16_t inset, const uint8_t row) { + Item_AreaCopy(157, 76, 181, 86, row, inset); // "ABS" +} +void say_home_offs_en(const uint8_t row) { + Item_AreaCopy(153, 193, 225, 203, row); // "Home Offset" +} +void say_probe_offs_en(const uint8_t row) { + Item_AreaCopy(153, 205, 225, 215, row); // "Probe Offset" +} +void say_steps_per_mm_en(const uint8_t row) { + Item_AreaCopy( 1, 151, 91, 161, row); // "Steps-per-mm" +} + +void DWIN_Draw_Label(const uint8_t row, char *string) { + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, LBLX, MBASE(row), string); +} +void DWIN_Draw_Label(const uint8_t row, FSTR_P title) { + DWIN_Draw_Label(row, (char*)title); +} + +void DWIN_Draw_Signed_Float(uint8_t size, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) { + DWIN_Draw_String(true, size, Color_White, bColor, x - 8, y, value < 0 ? F("-") : F(" ")); + DWIN_Draw_FloatValue(true, true, 0, size, Color_White, bColor, iNum, fNum, x, y, value < 0 ? -value : value); +} + +void Draw_Edit_Integer3(const uint8_t row, const uint16_t value, const bool active=false) { + DWIN_Draw_IntValue(true, true, 0, font8x16, Color_White, active ? Select_Color : Color_Bg_Black, 3, 220, EBASE(row), value); +} + +void Draw_Edit_Integer4(const uint8_t row, const uint16_t value, const bool active=false) { + DWIN_Draw_IntValue(true, true, 0, font8x16, Color_White, active ? Select_Color : Color_Bg_Black, 4, 220 - 1 * 8, EBASE(row), value); +} + +void Draw_Edit_Float3(const uint8_t row, const uint16_t value, const bool active=false) { + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, active ? Select_Color : Color_Bg_Black, 3, UNITFDIGITS, 220 - UNITFDIGITS * 8, EBASE(row), (int32_t)value); +} + +void Draw_Edit_Signed_Float2(const uint8_t row, const float value, const bool active=false) { + DWIN_Draw_Signed_Float(font8x16, active ? Select_Color : Color_Bg_Black, 2, UNITFDIGITS + 1, 220 + 8 - UNITFDIGITS * 8, EBASE(row), value); +} + +void Draw_Edit_Signed_Float3(const uint8_t row, const float value, const bool active=false) { + DWIN_Draw_Signed_Float(font8x16, active ? Select_Color : Color_Bg_Black, 3, UNITFDIGITS, 220 - UNITFDIGITS * 8, EBASE(row), value); +} + +void Draw_Stat_Int(const uint16_t xpos, const uint16_t ypos, const uint16_t value) { + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, Color_White, Color_Bg_Black, 3, xpos, ypos, value); +} + +void Draw_Stat_Float(const uint16_t xpos, const uint16_t ypos, const float value) { + DWIN_Draw_FloatValue(true, true, 0, DWIN_FONT_STAT, Color_White, Color_Bg_Black, 2, 2, xpos, ypos, value); +} + +// +// Prepare Menu +// + +void Item_Prepare_Move(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(159, 70, 200, 84, row); + else + say_move_en(row); // "Move" + Draw_Menu_Line(row, ICON_Axis); + Draw_More_Icon(row); +} + +void Item_Prepare_Disable(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(204, 70, 259, 82, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_DISABLE_STEPPERS)); + #else + Item_AreaCopy(104, 61, 191, 74, row); // "Disable Stepper" + #endif + } + Draw_Menu_Line(row, ICON_CloseMotor); +} + +void Item_Prepare_Home(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(0, 89, 41, 101, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_AUTO_HOME)); + #else + Item_AreaCopy(202, 61, 271, 71, row); // "Auto Home" + #endif + } + Draw_Menu_Line(row, ICON_Homing); +} + +#if HAS_ZOFFSET_ITEM + + void Item_Prepare_Offset(const uint8_t row) { + if (HMI_IsChinese()) { + #if HAS_BED_PROBE + Item_AreaCopy(174, 164, 223, 177, row); + #else + Item_AreaCopy(43, 89, 98, 101, row); + #endif + } + else { + #if HAS_BED_PROBE + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_ZPROBE_ZOFFSET)); + #else + Item_AreaCopy( 94, 179, 143, 190, row); // "Z-Offset" + #endif + #else + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_SET_HOME_OFFSETS)); + #else + Item_AreaCopy( 1, 76, 103, 87, row); // "Set home offsets" + #endif + #endif + } + Draw_Edit_Signed_Float2(row, BABY_Z_VAR * 100); + Draw_Menu_Line(row, ICON_SetHome); + } + +#endif + +#if HAS_PREHEAT + void Item_Prepare_PLA(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(100, 89, 151, 101, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_PREHEAT_1)); + #else + Item_AreaCopy(108, 76, 155, 87, row); // "Preheat" + say_pla_en(52, row); // "PLA" + #endif + } + Draw_Menu_Line(row, ICON_PLAPreheat); + } + + #if PREHEAT_COUNT > 1 + void Item_Prepare_ABS(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(180, 89, 233, 100, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, F("Preheat " PREHEAT_2_LABEL)); + #else + Item_AreaCopy(108, 76, 155, 87, row); // "Preheat" + say_abs_en(52, row); // "ABS" + #endif + } + Draw_Menu_Line(row, ICON_ABSPreheat); + } + #endif + + void Item_Prepare_Cool(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(1, 104, 56, 117, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_COOLDOWN)); + #else + Item_AreaCopy(200, 76, 264, 86, row); // "Cooldown" + #endif + } + Draw_Menu_Line(row, ICON_Cool); + } +#endif + +void Item_Prepare_Lang(const uint8_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(239, 134, 266, 146, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, F("UI Language")); + #else + Item_AreaCopy(1, 194, 96, 206, row); // "LCD Language" + #endif + } + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, 226, EBASE(row), HMI_IsChinese() ? F("CN") : F("EN")); + Draw_Menu_Icon(row, ICON_Language); +} + +#define VISI(T,L,S) (WITHIN(L, T - MROWS, MROWS) || WITHIN(S, 0, MROWS)) + +void Draw_Prepare_Menu() { + Clear_Main_Window(); + + const int16_t scroll = MROWS - index_prepare; // Scrolled-up lines + #define PSCROL(L) (scroll + (L)) + #define PVISI(L) VISI(PREPARE_CASE_TOTAL, L, PSCROL(L)) + + if (HMI_IsChinese()) + DWIN_Frame_TitleCopy(133, 1, 28, 13); // "Prepare" + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_PREPARE)); + #else + DWIN_Frame_TitleCopy(179, 0, 48, 14); // "Prepare" + #endif + } + + if (PVISI(0)) Draw_Back_First(select_prepare.now == CASE_BACK); // < Back + if (PVISI(PREPARE_CASE_MOVE)) Item_Prepare_Move(PSCROL(PREPARE_CASE_MOVE)); // Move > + if (PVISI(PREPARE_CASE_DISA)) Item_Prepare_Disable(PSCROL(PREPARE_CASE_DISA)); // Disable Stepper + if (PVISI(PREPARE_CASE_HOME)) Item_Prepare_Home(PSCROL(PREPARE_CASE_HOME)); // Auto Home + #if HAS_ZOFFSET_ITEM + if (PVISI(PREPARE_CASE_ZOFF)) Item_Prepare_Offset(PSCROL(PREPARE_CASE_ZOFF)); // Edit Z-Offset / Babystep / Set Home Offset + #endif + #if HAS_PREHEAT + if (PVISI(PREPARE_CASE_PLA)) Item_Prepare_PLA(PSCROL(PREPARE_CASE_PLA)); // Preheat PLA + #if PREHEAT_COUNT > 1 + if (PVISI(PREPARE_CASE_ABS)) Item_Prepare_ABS(PSCROL(PREPARE_CASE_ABS)); // Preheat ABS + #endif + #endif + #if HAS_HOTEND || HAS_HEATED_BED + if (PVISI(PREPARE_CASE_COOL)) Item_Prepare_Cool(PSCROL(PREPARE_CASE_COOL)); // Cooldown + #endif + if (PVISI(PREPARE_CASE_LANG)) Item_Prepare_Lang(PSCROL(PREPARE_CASE_LANG)); // Language CN/EN + + if (select_prepare.now != CASE_BACK) Draw_Menu_Cursor(PSCROL(select_prepare.now)); +} + +// +// Control Menu +// + +void Item_Control_Temp(const uint16_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(57, 104, 84, 116, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_TEMPERATURE)); + #else + Item_AreaCopy(1, 89, 83, 101, row); + #endif + } + Draw_Menu_Line(row, ICON_Temperature); + Draw_More_Icon(row); +} + +void Item_Control_Motion(const uint16_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(87, 104, 114, 116, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_MOTION)); + #else + Item_AreaCopy(84, 89, 128, 99, row); + #endif + } + Draw_Menu_Line(row, ICON_Motion); + Draw_More_Icon(row); +} + +void Item_Control_Advanced(const uint16_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(62, 180, 120, 192, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_ADVANCED_SETTINGS)); + #else + Item_AreaCopy(82, 135, 200, 149, row); + #endif + } + Draw_Menu_Line(row, ICON_AdvSet); + Draw_More_Icon(row); +} + +void Item_Control_Info(const uint16_t row) { + if (HMI_IsChinese()) + Item_AreaCopy(231, 104, 258, 116, row); + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_INFO_SCREEN)); + #else + Item_AreaCopy(0, 104, 24, 114, row); + #endif + } + Draw_Menu_Line(row, ICON_Info); + Draw_More_Icon(row); +} + +void Draw_Control_Menu() { + Clear_Main_Window(); + + #if CONTROL_CASE_TOTAL >= TROWS + const int16_t scroll = MROWS - index_control; // Scrolled-up lines + #else + constexpr int16_t scroll = 0; + #endif + #define CSCROL(L) (scroll + (L)) + #define CLINE(L) MBASE(CSCROL(L)) + #define CVISI(L) VISI(CONTROL_CASE_TOTAL, L, CSCROL(L)) + + if (HMI_IsChinese()) + DWIN_Frame_TitleCopy(103, 1, 28, 14); // "Control" + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_CONTROL)); + #else + DWIN_Frame_TitleCopy(128, 2, 49, 11); // "Control" + #endif + } + + if (CVISI(0)) Draw_Back_First(select_control.now == CASE_BACK); // < Back + if (CVISI(CONTROL_CASE_TEMP)) Item_Control_Temp(CSCROL(CONTROL_CASE_TEMP)); // Temperature > + if (CVISI(CONTROL_CASE_MOVE)) Item_Control_Motion(CSCROL(CONTROL_CASE_MOVE)); // Motion > + + if (HMI_IsChinese()) { + #if ENABLED(EEPROM_SETTINGS) + Item_AreaCopy(117, 104, 172, 116, CSCROL(CONTROL_CASE_SAVE)); // "Store Configuration" + Item_AreaCopy(174, 103, 229, 116, CSCROL(CONTROL_CASE_LOAD)); // "Read Configuration" + Item_AreaCopy( 1, 118, 56, 131, CSCROL(CONTROL_CASE_RESET)); // "Reset Configuration" + #endif + } + else { + #ifdef USE_STRING_TITLES + #if ENABLED(EEPROM_SETTINGS) + if (CVISI(CONTROL_CASE_SAVE)) DWIN_Draw_Label(CSCROL(CONTROL_CASE_SAVE), GET_TEXT_F(MSG_STORE_EEPROM)); // "Store Configuration" + if (CVISI(CONTROL_CASE_LOAD)) DWIN_Draw_Label(CSCROL(CONTROL_CASE_LOAD), GET_TEXT_F(MSG_LOAD_EEPROM)); // "Read Configuration" + if (CVISI(CONTROL_CASE_RESET)) DWIN_Draw_Label(CSCROL(CONTROL_CASE_RESET), GET_TEXT_F(MSG_RESTORE_DEFAULTS)); // "Reset Configuration" + #endif + #else + #if ENABLED(EEPROM_SETTINGS) + if (CVISI(CONTROL_CASE_SAVE)) + Item_AreaCopy(150, 89, 263, 102, CSCROL(CONTROL_CASE_SAVE)); // "Store Configuration" + if (CVISI(CONTROL_CASE_LOAD)) { + Item_AreaCopy( 26, 104, 57, 114, CSCROL(CONTROL_CASE_LOAD)); // "Read" + Item_AreaCopy(182, 89, 263, 102, CSCROL(CONTROL_CASE_LOAD), 34); // "Configuration" + } + if (CVISI(CONTROL_CASE_RESET)) { + Item_AreaCopy( 59, 104, 93, 114, CSCROL(CONTROL_CASE_RESET)); // "Reset" + Item_AreaCopy(182, 89, 263, 102, CSCROL(CONTROL_CASE_RESET), 37); // "Configuration" + } + #endif + #endif + } + + if (CVISI(CONTROL_CASE_ADVSET)) Item_Control_Advanced(CSCROL(CONTROL_CASE_ADVSET)); + if (CVISI(CONTROL_CASE_INFO)) Item_Control_Info(CSCROL(CONTROL_CASE_INFO)); + + if (select_control.now != CASE_BACK && CVISI(select_control.now)) + Draw_Menu_Cursor(CSCROL(select_control.now)); + + // Draw icons and lines + #define _TEMP_ICON(N, I, M) do { \ + if (CVISI(N)) { \ + Draw_Menu_Line(CSCROL(N), I); \ + if (M) { \ + Draw_More_Icon(CSCROL(N)); \ + } \ + } \ + } while(0) + + #if ENABLED(EEPROM_SETTINGS) + _TEMP_ICON(CONTROL_CASE_SAVE, ICON_WriteEEPROM, false); + _TEMP_ICON(CONTROL_CASE_LOAD, ICON_ReadEEPROM, false); + _TEMP_ICON(CONTROL_CASE_RESET, ICON_ResumeEEPROM, false); + #endif +} + +// +// Tune Menu +// + +void Draw_Tune_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(73, 2, 28, 12); // "Tune" + Item_AreaCopy(116, 164, 171, 176, TUNE_CASE_SPEED); + #if HAS_HOTEND + Item_AreaCopy(1, 134, 56, 146, TUNE_CASE_TEMP); + #endif + #if HAS_HEATED_BED + Item_AreaCopy(58, 134, 113, 146, TUNE_CASE_BED); + #endif + #if HAS_FAN + Item_AreaCopy(115, 134, 170, 146, TUNE_CASE_FAN); + #endif + #if HAS_ZOFFSET_ITEM + Item_AreaCopy(174, 164, 223, 177, TUNE_CASE_ZOFF); + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_TUNE)); + #else + DWIN_Frame_TitleCopy(94, 2, 33, 11); // "Tune" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(TUNE_CASE_SPEED, GET_TEXT_F(MSG_SPEED)); + #if HAS_HOTEND + DWIN_Draw_Label(TUNE_CASE_TEMP, GET_TEXT_F(MSG_UBL_SET_TEMP_HOTEND)); + #endif + #if HAS_HEATED_BED + DWIN_Draw_Label(TUNE_CASE_BED, GET_TEXT_F(MSG_UBL_SET_TEMP_BED)); + #endif + #if HAS_FAN + DWIN_Draw_Label(TUNE_CASE_FAN, GET_TEXT_F(MSG_FAN_SPEED)); + #endif + DWIN_Draw_Label(TUNE_CASE_ZOFF, GET_TEXT_F(MSG_ZPROBE_ZOFFSET)); + #else + Item_AreaCopy(1, 179, 92, 190, TUNE_CASE_SPEED); // "Print speed" + #if HAS_HOTEND + Item_AreaCopy(197, 104, 238, 114, TUNE_CASE_TEMP); // "Hotend" + Item_AreaCopy( 1, 89, 83, 101, TUNE_CASE_TEMP, 44); // "Temperature" + #endif + #if HAS_HEATED_BED + Item_AreaCopy(240, 104, 264, 114, TUNE_CASE_BED); // "Bed" + Item_AreaCopy( 1, 89, 83, 101, TUNE_CASE_BED, 27); // "Temperature" + #endif + #if HAS_FAN + Item_AreaCopy(0, 119, 64, 132, TUNE_CASE_FAN); // "Fan speed" + #endif + #if HAS_ZOFFSET_ITEM + Item_AreaCopy(93, 179, 141, 189, TUNE_CASE_ZOFF); // "Z-offset" + #endif + #endif + } + + Draw_Back_First(select_tune.now == CASE_BACK); + if (select_tune.now != CASE_BACK) Draw_Menu_Cursor(select_tune.now); + + Draw_Menu_Line(TUNE_CASE_SPEED, ICON_Speed); + Draw_Edit_Integer3(TUNE_CASE_SPEED, feedrate_percentage); + + #if HAS_HOTEND + Draw_Menu_Line(TUNE_CASE_TEMP, ICON_HotendTemp); + Draw_Edit_Integer3(TUNE_CASE_TEMP, thermalManager.degTargetHotend(0)); + #endif + #if HAS_HEATED_BED + Draw_Menu_Line(TUNE_CASE_BED, ICON_BedTemp); + Draw_Edit_Integer3(TUNE_CASE_BED, thermalManager.degTargetBed()); + #endif + #if HAS_FAN + Draw_Menu_Line(TUNE_CASE_FAN, ICON_FanSpeed); + Draw_Edit_Integer3(TUNE_CASE_FAN, thermalManager.fan_speed[0]); + #endif + #if HAS_ZOFFSET_ITEM + Draw_Menu_Line(TUNE_CASE_ZOFF, ICON_Zoffset); + Draw_Edit_Signed_Float2(TUNE_CASE_ZOFF, BABY_Z_VAR * 100); + #endif +} + +// +// Motion Menu +// +void Draw_Motion_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(1, 16, 28, 13); // "Motion" + Item_AreaCopy(173, 133, 228, 147, MOTION_CASE_RATE); // Max speed + Item_AreaCopy(173, 133, 200, 147, MOTION_CASE_ACCEL); // Max... + Item_AreaCopy(28, 149, 69, 161, MOTION_CASE_ACCEL, 30, 1); // ...Acceleration + #if HAS_CLASSIC_JERK + Item_AreaCopy(173, 133, 200, 147, MOTION_CASE_JERK); // Max... + Item_AreaCopy(1, 180, 28, 192, MOTION_CASE_JERK, 30, 1); // ... + Item_AreaCopy(202, 133, 228, 147, MOTION_CASE_JERK, 57); // ...Jerk + #endif + Item_AreaCopy(153, 148, 194, 161, MOTION_CASE_STEPS); // Flow ratio + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_MOTION)); + #else + DWIN_Frame_TitleCopy(144, 16, 46, 11); // "Motion" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(MOTION_CASE_RATE, F("Feedrate")); // "Feedrate" + DWIN_Draw_Label(MOTION_CASE_ACCEL, GET_TEXT_F(MSG_ACCELERATION)); // "Acceleration" + #if HAS_CLASSIC_JERK + DWIN_Draw_Label(MOTION_CASE_JERK, GET_TEXT_F(MSG_JERK)); // "Jerk" + #endif + DWIN_Draw_Label(MOTION_CASE_STEPS, GET_TEXT_F(MSG_STEPS_PER_MM)); // "Steps/mm" + #else + say_max_en(MOTION_CASE_RATE); say_speed_en(30, MOTION_CASE_RATE); // "Max Speed" + say_max_accel_en(MOTION_CASE_ACCEL); // "Max Acceleration" + #if HAS_CLASSIC_JERK + say_max_en(MOTION_CASE_JERK); say_jerk_en(MOTION_CASE_JERK); // "Max Jerk" + #endif + say_steps_per_mm_en(MOTION_CASE_STEPS); // "Steps-per-mm" + #endif + } + + Draw_Back_First(select_motion.now == CASE_BACK); + if (select_motion.now != CASE_BACK) Draw_Menu_Cursor(select_motion.now); + + uint8_t i = 0; + #define _MOTION_ICON(N) Draw_Menu_Line(++i, ICON_MaxSpeed + (N) - 1) + _MOTION_ICON(MOTION_CASE_RATE); Draw_More_Icon(i); + _MOTION_ICON(MOTION_CASE_ACCEL); Draw_More_Icon(i); + #if HAS_CLASSIC_JERK + _MOTION_ICON(MOTION_CASE_JERK); Draw_More_Icon(i); + #endif + _MOTION_ICON(MOTION_CASE_STEPS); Draw_More_Icon(i); +} + +// +// Draw Popup Windows +// + +#if HAS_HOTEND || HAS_HEATED_BED + + void DWIN_Popup_Temperature(const bool toohigh) { + Clear_Popup_Area(); + Draw_Popup_Bkgd_105(); + if (toohigh) { + DWIN_ICON_Show(ICON, ICON_TempTooHigh, 102, 165); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 103, 371, 237, 386, 52, 285); // Temp Too High + DWIN_Frame_AreaCopy(1, 151, 389, 185, 402, 187, 285); + DWIN_Frame_AreaCopy(1, 189, 389, 271, 402, 95, 310); + } + else { + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, 36, 300, F("Nozzle or Bed temperature")); + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, 92, 300, F("is too high")); + } + } + else { + DWIN_ICON_Show(ICON, ICON_TempTooLow, 102, 165); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 103, 371, 270, 386, 52, 285); // Tenp Too Low + DWIN_Frame_AreaCopy(1, 189, 389, 271, 402, 95, 310); + } + else { + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, 36, 300, F("Nozzle or Bed temperature")); + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, 92, 300, F("is too low")); + } + } + } + +#endif + +void Draw_Popup_Bkgd_60() { + DWIN_Draw_Rectangle(1, Color_Bg_Window, 14, 60, 258, 330); +} + +#if HAS_HOTEND + + void Popup_Window_ETempTooLow() { + Clear_Main_Window(); + Draw_Popup_Bkgd_60(); + DWIN_ICON_Show(ICON, ICON_TempTooLow, 102, 105); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 103, 371, 136, 386, 69, 240); // Nozzle Too Cold + DWIN_Frame_AreaCopy(1, 170, 371, 270, 386, 69 + 33, 240); + DWIN_ICON_Show(ICON, ICON_Confirm_C, 86, 280); + } + else { + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, 20, 235, F("Nozzle is too cold")); + DWIN_ICON_Show(ICON, ICON_Confirm_E, 86, 280); + } + } + +#endif + +void Popup_Window_Resume() { + Clear_Popup_Area(); + Draw_Popup_Bkgd_105(); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 160, 338, 235, 354, 98, 135); // Resume Interrupted Print + DWIN_Frame_AreaCopy(1, 103, 321, 271, 335, 52, 192); + DWIN_ICON_Show(ICON, ICON_Cancel_C, 26, 307); + DWIN_ICON_Show(ICON, ICON_Continue_C, 146, 307); + } + else { + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 14) / 2, 115, F("Continue Print")); + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 22) / 2, 192, F("It looks like the last")); + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 22) / 2, 212, F("file was interrupted.")); + DWIN_ICON_Show(ICON, ICON_Cancel_E, 26, 307); + DWIN_ICON_Show(ICON, ICON_Continue_E, 146, 307); + } +} + +void Popup_Window_Home(const bool parking/*=false*/) { + Clear_Main_Window(); + Draw_Popup_Bkgd_60(); + DWIN_ICON_Show(ICON, ICON_BLTouch, 101, 105); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 0, 371, 33, 386, 85, 240); // Wait for Move to Complete + DWIN_Frame_AreaCopy(1, 203, 286, 271, 302, 118, 240); + DWIN_Frame_AreaCopy(1, 0, 389, 150, 402, 61, 280); + } + else { + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * (parking ? 7 : 10)) / 2, 230, parking ? F("Parking") : F("Homing XYZ")); + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 23) / 2, 260, F("Please wait until done.")); + } +} + +#if HAS_ONESTEP_LEVELING + + void Popup_Window_Leveling() { + Clear_Main_Window(); + Draw_Popup_Bkgd_60(); + DWIN_ICON_Show(ICON, ICON_AutoLeveling, 101, 105); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 0, 371, 100, 386, 84, 240); // Wait for Leveling + DWIN_Frame_AreaCopy(1, 0, 389, 150, 402, 61, 280); + } + else { + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 13) / 2, 230, GET_TEXT_F(MSG_BED_LEVELING)); + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 23) / 2, 260, F("Please wait until done.")); + } + } + +#endif + +void Draw_Select_Highlight(const bool sel) { + HMI_flag.select_flag = sel; + const uint16_t c1 = sel ? Select_Color : Color_Bg_Window, + c2 = sel ? Color_Bg_Window : Select_Color; + DWIN_Draw_Rectangle(0, c1, 25, 279, 126, 318); + DWIN_Draw_Rectangle(0, c1, 24, 278, 127, 319); + DWIN_Draw_Rectangle(0, c2, 145, 279, 246, 318); + DWIN_Draw_Rectangle(0, c2, 144, 278, 247, 319); +} + +void Popup_window_PauseOrStop() { + Clear_Main_Window(); + Draw_Popup_Bkgd_60(); + if (HMI_IsChinese()) { + if (select_print.now == PRINT_PAUSE_RESUME) DWIN_Frame_AreaCopy(1, 237, 338, 269, 356, 98, 150); // Pause + else if (select_print.now == PRINT_STOP) DWIN_Frame_AreaCopy(1, 221, 320, 253, 336, 98, 150); // Stop + DWIN_Frame_AreaCopy(1, 220, 304, 264, 319, 130, 150); // Print + DWIN_ICON_Show(ICON, ICON_Confirm_C, 26, 280); + DWIN_ICON_Show(ICON, ICON_Cancel_C, 146, 280); + } + else { + if (select_print.now == PRINT_PAUSE_RESUME) DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 11) / 2, 150, GET_TEXT_F(MSG_PAUSE_PRINT)); + else if (select_print.now == PRINT_STOP) DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, (272 - 8 * 10) / 2, 150, GET_TEXT_F(MSG_STOP_PRINT)); + DWIN_ICON_Show(ICON, ICON_Confirm_E, 26, 280); + DWIN_ICON_Show(ICON, ICON_Cancel_E, 146, 280); + } + Draw_Select_Highlight(true); +} + +void Draw_Printing_Screen() { + const uint16_t y = 168; + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(30, 1, 42, 14); // "Printing" + DWIN_Frame_AreaCopy(1, 0, 72, 63, 86, 43, y); // "Printing Time" + DWIN_Frame_AreaCopy(1, 65, 72, 128, 86, 178, y); // "Remain" + } + else { + DWIN_Frame_TitleCopy(42, 0, 47, 14); // "Printing" + DWIN_Frame_AreaCopy(1, 1, 43, 97, 59, 43, y); // "Printing Time" + DWIN_Frame_AreaCopy(1, 100, 43, 152, 56, 178, y); // "Remain" + } +} + +void Draw_Print_ProgressBar() { + constexpr uint16_t y = 93, h = 21; + DWIN_ICON_Show(ICON, ICON_Bar, 15, 93); + DWIN_Draw_Rectangle(1, BarFill_Color, 16 + _card_percent * 240 / 100, y, 256, y + h - 1); + DWIN_Draw_IntValue(true, true, 0, font8x16, Percent_Color, Color_Bg_Black, 2, 117, y + 40, _card_percent); + DWIN_Draw_String(false, font8x16, Percent_Color, Color_Bg_Black, 133, y + 40, F("%")); +} + +void Draw_Print_ProgressElapsed() { + constexpr uint16_t x = 45, y = 192; + duration_t elapsed = print_job_timer.duration(); // print timer + DWIN_Draw_IntValue(true, true, 1, font8x16, Color_White, Color_Bg_Black, 2, x, y, elapsed.value / 3600); + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, x + 8 * 2, y, F(":")); + DWIN_Draw_IntValue(true, true, 1, font8x16, Color_White, Color_Bg_Black, 2, x + 8 * 3, y, (elapsed.value % 3600) / 60); +} + +void Draw_Print_ProgressRemain() { + constexpr uint16_t x = 179, y = 192; + DWIN_Draw_IntValue(true, true, 1, font8x16, Color_White, Color_Bg_Black, 2, x, y, _remain_time / 3600); + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, x + 8 * 2, y, F(":")); + DWIN_Draw_IntValue(true, true, 1, font8x16, Color_White, Color_Bg_Black, 2, x + 8 * 3, y, (_remain_time % 3600) / 60); +} + +void Goto_PrintProcess() { + checkkey = PrintProcess; + + Clear_Main_Window(); + Draw_Printing_Screen(); + + ICON_Tune(); + ICON_ResumeOrPause(); + ICON_Stop(); + + // Copy into filebuf string before entry + char * const name = card.longest_filename(); + const int8_t npos = _MAX(0U, DWIN_WIDTH - strlen(name) * MENU_CHR_W) / 2; + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, npos, 60, name); + + DWIN_ICON_Show(ICON, ICON_PrintTime, 17, 163); + DWIN_ICON_Show(ICON, ICON_RemainTime, 150, 161); + + Draw_Print_ProgressBar(); + Draw_Print_ProgressElapsed(); + Draw_Print_ProgressRemain(); +} + +void Goto_MainMenu() { + checkkey = MainMenu; + + Clear_Main_Window(); + + if (HMI_IsChinese()) + DWIN_Frame_TitleCopy(2, 2, 26, 13); // "Home" etc + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_MAIN)); + #else + DWIN_Frame_TitleCopy(0, 2, 40, 11); // "Home" + #endif + } + + DWIN_ICON_Show(ICON, ICON_LOGO, 71, 52); + + ICON_Print(); + ICON_Prepare(); + ICON_Control(); + TERN(HAS_ONESTEP_LEVELING, ICON_Leveling, ICON_StartInfo)(); +} + +void HMI_Plan_Move(const feedRate_t fr_mm_s) { + if (!planner.is_full()) { + planner.synchronize(); + planner.buffer_line(current_position, fr_mm_s); + DWIN_UpdateLCD(); + } +} + +void HMI_Move_Done(const AxisEnum axis) { + EncoderRate.enabled = false; + planner.synchronize(); + checkkey = AxisMove; + DWIN_UpdateLCD(); +} + +void HMI_Move_X() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Move_X_scaled)) { + Draw_Edit_Float3(1, HMI_ValueStruct.Move_X_scaled); + return HMI_Move_Done(X_AXIS); + } + LIMIT(HMI_ValueStruct.Move_X_scaled, (X_MIN_POS) * MINUNITMULT, (X_MAX_POS) * MINUNITMULT); + current_position.x = HMI_ValueStruct.Move_X_scaled / MINUNITMULT; + Draw_Edit_Float3(1, HMI_ValueStruct.Move_X_scaled, true); + DWIN_UpdateLCD(); + HMI_Plan_Move(homing_feedrate(X_AXIS)); +} + +void HMI_Move_Y() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Move_Y_scaled)) { + Draw_Edit_Float3(2, HMI_ValueStruct.Move_Y_scaled); + return HMI_Move_Done(Y_AXIS); + } + LIMIT(HMI_ValueStruct.Move_Y_scaled, (Y_MIN_POS) * MINUNITMULT, (Y_MAX_POS) * MINUNITMULT); + current_position.y = HMI_ValueStruct.Move_Y_scaled / MINUNITMULT; + Draw_Edit_Float3(2, HMI_ValueStruct.Move_Y_scaled, true); + DWIN_UpdateLCD(); + HMI_Plan_Move(homing_feedrate(Y_AXIS)); +} + +void HMI_Move_Z() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Move_Z_scaled)) { + Draw_Edit_Float3(3, HMI_ValueStruct.Move_Z_scaled); + return HMI_Move_Done(Z_AXIS); + } + LIMIT(HMI_ValueStruct.Move_Z_scaled, (Z_MIN_POS) * MINUNITMULT, (Z_MAX_POS) * MINUNITMULT); + current_position.z = HMI_ValueStruct.Move_Z_scaled / MINUNITMULT; + Draw_Edit_Float3(3, HMI_ValueStruct.Move_Z_scaled, true); + DWIN_UpdateLCD(); + HMI_Plan_Move(homing_feedrate(Z_AXIS)); +} + +#if HAS_HOTEND + + void HMI_Move_E() { + static float last_E_scaled = 0; + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Move_E_scaled)) { + last_E_scaled = HMI_ValueStruct.Move_E_scaled; + Draw_Edit_Signed_Float3(4, last_E_scaled); + return HMI_Move_Done(E_AXIS); + } + LIMIT(HMI_ValueStruct.Move_E_scaled, last_E_scaled - (EXTRUDE_MAXLENGTH) * MINUNITMULT, last_E_scaled + (EXTRUDE_MAXLENGTH) * MINUNITMULT); + current_position.e = HMI_ValueStruct.Move_E_scaled / MINUNITMULT; + Draw_Edit_Signed_Float3(4, HMI_ValueStruct.Move_E_scaled, true); + DWIN_UpdateLCD(); + HMI_Plan_Move(MMM_TO_MMS(FEEDRATE_E)); + } + +#endif + +#if HAS_ZOFFSET_ITEM + + void HMI_Zoffset() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + uint8_t zoff_line; + switch (HMI_ValueStruct.show_mode) { + case -4: zoff_line = PREPARE_CASE_ZOFF + MROWS - index_prepare; break; + default: zoff_line = TUNE_CASE_ZOFF + MROWS - index_tune; + } + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.offset_value)) { + EncoderRate.enabled = false; + #if HAS_BED_PROBE + probe.offset.z = dwin_zoffset; + TERN_(EEPROM_SETTINGS, settings.save()); + #endif + checkkey = HMI_ValueStruct.show_mode == -4 ? Prepare : Tune; + Draw_Edit_Signed_Float2(zoff_line, TERN(HAS_BED_PROBE, BABY_Z_VAR * 100, HMI_ValueStruct.offset_value)); + DWIN_UpdateLCD(); + return; + } + LIMIT(HMI_ValueStruct.offset_value, (Z_PROBE_OFFSET_RANGE_MIN) * 100, (Z_PROBE_OFFSET_RANGE_MAX) * 100); + last_zoffset = dwin_zoffset; + dwin_zoffset = HMI_ValueStruct.offset_value / 100.0f; + #if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + if (BABYSTEP_ALLOWED()) babystep.add_mm(Z_AXIS, dwin_zoffset - last_zoffset); + #endif + Draw_Edit_Signed_Float2(zoff_line, HMI_ValueStruct.offset_value, true); + DWIN_UpdateLCD(); + } + +#endif // HAS_ZOFFSET_ITEM + +#if HAS_HOTEND + + void HMI_ETemp() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + uint8_t temp_line; + switch (HMI_ValueStruct.show_mode) { + case -1: temp_line = TEMP_CASE_TEMP; break; + #if HAS_PREHEAT + case -2: temp_line = PREHEAT_CASE_TEMP; break; + #if PREHEAT_COUNT > 1 + case -3: temp_line = PREHEAT_CASE_TEMP; break; + #endif + #endif + default: temp_line = TUNE_CASE_TEMP + MROWS - index_tune; + } + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.E_Temp)) { + EncoderRate.enabled = false; + #if HAS_PREHEAT + if (HMI_ValueStruct.show_mode == -2) { + checkkey = PLAPreheat; + ui.material_preset[0].hotend_temp = HMI_ValueStruct.E_Temp; + Draw_Edit_Integer3(temp_line, ui.material_preset[0].hotend_temp); + return; + } + #if PREHEAT_COUNT > 1 + if (HMI_ValueStruct.show_mode == -3) { + checkkey = ABSPreheat; + ui.material_preset[1].hotend_temp = HMI_ValueStruct.E_Temp; + Draw_Edit_Integer3(temp_line, ui.material_preset[1].hotend_temp); + return; + } + #endif + #endif + + if (HMI_ValueStruct.show_mode == -1) // Temperature + checkkey = TemperatureID; + else + checkkey = Tune; + Draw_Edit_Integer3(temp_line, HMI_ValueStruct.E_Temp); + thermalManager.setTargetHotend(HMI_ValueStruct.E_Temp, 0); + return; + } + // E_Temp limit + LIMIT(HMI_ValueStruct.E_Temp, HEATER_0_MINTEMP, thermalManager.hotend_max_target(0)); + // E_Temp value + Draw_Edit_Integer3(temp_line, HMI_ValueStruct.E_Temp, true); + } + +#endif // HAS_HOTEND + +#if HAS_HEATED_BED + + void HMI_BedTemp() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + uint8_t bed_line; + switch (HMI_ValueStruct.show_mode) { + case -1: bed_line = TEMP_CASE_BED; break; + #if HAS_PREHEAT + case -2: bed_line = PREHEAT_CASE_BED; break; + #if PREHEAT_COUNT > 1 + case -3: bed_line = PREHEAT_CASE_BED; break; + #endif + #endif + default: bed_line = TUNE_CASE_BED + MROWS - index_tune; + } + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Bed_Temp)) { + EncoderRate.enabled = false; + #if HAS_PREHEAT + if (HMI_ValueStruct.show_mode == -2) { + checkkey = PLAPreheat; + ui.material_preset[0].bed_temp = HMI_ValueStruct.Bed_Temp; + Draw_Edit_Integer3(bed_line, ui.material_preset[0].bed_temp); + return; + } + #if PREHEAT_COUNT > 1 + if (HMI_ValueStruct.show_mode == -3) { + checkkey = ABSPreheat; + ui.material_preset[1].bed_temp = HMI_ValueStruct.Bed_Temp; + Draw_Edit_Integer3(bed_line, ui.material_preset[1].bed_temp); + return; + } + #endif + #endif + checkkey = HMI_ValueStruct.show_mode == -1 ? TemperatureID : Tune; + Draw_Edit_Integer3(bed_line, HMI_ValueStruct.Bed_Temp); + thermalManager.setTargetBed(HMI_ValueStruct.Bed_Temp); + return; + } + // Bed_Temp limit + LIMIT(HMI_ValueStruct.Bed_Temp, BED_MINTEMP, BED_MAX_TARGET); + // Bed_Temp value + Draw_Edit_Integer3(bed_line, HMI_ValueStruct.Bed_Temp, true); + } + +#endif // HAS_HEATED_BED + +#if HAS_PREHEAT && HAS_FAN + + void HMI_FanSpeed() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + uint8_t fan_line; + switch (HMI_ValueStruct.show_mode) { + case -1: fan_line = TEMP_CASE_FAN; break; + case -2: fan_line = PREHEAT_CASE_FAN; break; + case -3: fan_line = PREHEAT_CASE_FAN; break; + default: fan_line = TUNE_CASE_FAN + MROWS - index_tune; + } + + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Fan_speed)) { + EncoderRate.enabled = false; + if (HMI_ValueStruct.show_mode == -2) { + checkkey = PLAPreheat; + ui.material_preset[0].fan_speed = HMI_ValueStruct.Fan_speed; + Draw_Edit_Integer3(fan_line, ui.material_preset[0].fan_speed); + return; + } + #if PREHEAT_COUNT > 1 + if (HMI_ValueStruct.show_mode == -3) { + checkkey = ABSPreheat; + ui.material_preset[1].fan_speed = HMI_ValueStruct.Fan_speed; + Draw_Edit_Integer3(fan_line, ui.material_preset[1].fan_speed); + return; + } + #endif + checkkey = HMI_ValueStruct.show_mode == -1 ? TemperatureID : Tune; + Draw_Edit_Integer3(fan_line, HMI_ValueStruct.Fan_speed); + thermalManager.set_fan_speed(0, HMI_ValueStruct.Fan_speed); + return; + } + // Fan_speed limit + LIMIT(HMI_ValueStruct.Fan_speed, 0, 255); + // Fan_speed value + Draw_Edit_Integer3(fan_line, HMI_ValueStruct.Fan_speed, true); + } + +#endif // HAS_PREHEAT && HAS_FAN + +void HMI_PrintSpeed() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.print_speed)) { + checkkey = Tune; + EncoderRate.enabled = false; + feedrate_percentage = HMI_ValueStruct.print_speed; + Draw_Edit_Integer3(select_tune.now + MROWS - index_tune, HMI_ValueStruct.print_speed); + return; + } + // print_speed limit + LIMIT(HMI_ValueStruct.print_speed, MIN_PRINT_SPEED, MAX_PRINT_SPEED); + // print_speed value + Draw_Edit_Integer3(select_tune.now + MROWS - index_tune, HMI_ValueStruct.print_speed, true); +} + +#define LAST_AXIS TERN(HAS_HOTEND, E_AXIS, Z_AXIS) + +void HMI_MaxFeedspeedXYZE() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Max_Feedspeed)) { + checkkey = MaxSpeed; + EncoderRate.enabled = false; + if (WITHIN(HMI_flag.feedspeed_axis, X_AXIS, LAST_AXIS)) + planner.set_max_feedrate(HMI_flag.feedspeed_axis, HMI_ValueStruct.Max_Feedspeed); + Draw_Edit_Integer4(select_speed.now, HMI_ValueStruct.Max_Feedspeed); + return; + } + // MaxFeedspeed limit + if (WITHIN(HMI_flag.feedspeed_axis, X_AXIS, LAST_AXIS)) + NOMORE(HMI_ValueStruct.Max_Feedspeed, default_max_feedrate[HMI_flag.feedspeed_axis] * 2); + if (HMI_ValueStruct.Max_Feedspeed < MIN_MAXFEEDSPEED) HMI_ValueStruct.Max_Feedspeed = MIN_MAXFEEDSPEED; + // MaxFeedspeed value + Draw_Edit_Integer4(select_speed.now, HMI_ValueStruct.Max_Feedspeed, true); +} + +void HMI_MaxAccelerationXYZE() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Max_Acceleration)) { + checkkey = MaxAcceleration; + EncoderRate.enabled = false; + if (WITHIN(HMI_flag.acc_axis, X_AXIS, LAST_AXIS)) + planner.set_max_acceleration(HMI_flag.acc_axis, HMI_ValueStruct.Max_Acceleration); + Draw_Edit_Integer4(select_acc.now, HMI_ValueStruct.Max_Acceleration); + return; + } + // MaxAcceleration limit + if (WITHIN(HMI_flag.acc_axis, X_AXIS, LAST_AXIS)) + NOMORE(HMI_ValueStruct.Max_Acceleration, default_max_acceleration[HMI_flag.acc_axis] * 2); + if (HMI_ValueStruct.Max_Acceleration < MIN_MAXACCELERATION) HMI_ValueStruct.Max_Acceleration = MIN_MAXACCELERATION; + // MaxAcceleration value + Draw_Edit_Integer4(select_acc.now, HMI_ValueStruct.Max_Acceleration, true); +} + +#if HAS_CLASSIC_JERK + + void HMI_MaxJerkXYZE() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Max_Jerk_scaled)) { + checkkey = MaxJerk; + EncoderRate.enabled = false; + if (WITHIN(HMI_flag.jerk_axis, X_AXIS, LAST_AXIS)) + planner.set_max_jerk(HMI_flag.jerk_axis, HMI_ValueStruct.Max_Jerk_scaled / 10); + Draw_Edit_Float3(select_jerk.now, HMI_ValueStruct.Max_Jerk_scaled); + return; + } + // MaxJerk limit + if (WITHIN(HMI_flag.jerk_axis, X_AXIS, LAST_AXIS)) + NOMORE(HMI_ValueStruct.Max_Jerk_scaled, default_max_jerk[HMI_flag.jerk_axis] * 2 * MINUNITMULT); + NOLESS(HMI_ValueStruct.Max_Jerk_scaled, (MIN_MAXJERK) * MINUNITMULT); + // MaxJerk value + Draw_Edit_Float3(select_jerk.now, HMI_ValueStruct.Max_Jerk_scaled, true); + } + +#endif // HAS_CLASSIC_JERK + +void HMI_StepXYZE() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Max_Step_scaled)) { + checkkey = Step; + EncoderRate.enabled = false; + if (WITHIN(HMI_flag.step_axis, X_AXIS, LAST_AXIS)) + planner.settings.axis_steps_per_mm[HMI_flag.step_axis] = HMI_ValueStruct.Max_Step_scaled / 10; + Draw_Edit_Float3(select_step.now, HMI_ValueStruct.Max_Step_scaled); + return; + } + // Step limit + if (WITHIN(HMI_flag.step_axis, X_AXIS, LAST_AXIS)) + NOMORE(HMI_ValueStruct.Max_Step_scaled, 999.9 * MINUNITMULT); + NOLESS(HMI_ValueStruct.Max_Step_scaled, MIN_STEP); + // Step value + Draw_Edit_Float3(select_step.now, HMI_ValueStruct.Max_Step_scaled, true); +} + +// Draw X, Y, Z and blink if in an un-homed or un-trusted state +void _update_axis_value(const AxisEnum axis, const uint16_t x, const uint16_t y, const bool blink, const bool force) { + const bool draw_qmark = axis_should_home(axis), + draw_empty = NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !draw_qmark && !axis_is_trusted(axis); + + // Check for a position change + static xyz_pos_t oldpos = { -1, -1, -1 }; + const float p = current_position[axis]; + const bool changed = oldpos[axis] != p; + if (changed) oldpos[axis] = p; + + if (force || changed || draw_qmark || draw_empty) { + if (blink && draw_qmark) + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x, y, F("???.?")); + else if (blink && draw_empty) + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x, y, F(" ")); + else + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, x, y, p); + } +} + +void _draw_xyz_position(const bool force) { + //SERIAL_ECHOPGM("Draw XYZ:"); + static bool _blink = false; + const bool blink = !!(millis() & 0x400UL); + if (force || blink != _blink) { + _blink = blink; + //SERIAL_ECHOPGM(" (blink)"); + _update_axis_value(X_AXIS, 35, 459, blink, true); + _update_axis_value(Y_AXIS, 120, 459, blink, true); + _update_axis_value(Z_AXIS, 205, 459, blink, true); + } + //SERIAL_EOL(); +} + +void update_variable() { + #if HAS_HOTEND + static celsius_t _hotendtemp = 0, _hotendtarget = 0; + const celsius_t hc = thermalManager.wholeDegHotend(0), + ht = thermalManager.degTargetHotend(0); + const bool _new_hotend_temp = _hotendtemp != hc, + _new_hotend_target = _hotendtarget != ht; + if (_new_hotend_temp) _hotendtemp = hc; + if (_new_hotend_target) _hotendtarget = ht; + #endif + #if HAS_HEATED_BED + static celsius_t _bedtemp = 0, _bedtarget = 0; + const celsius_t bc = thermalManager.wholeDegBed(), + bt = thermalManager.degTargetBed(); + const bool _new_bed_temp = _bedtemp != bc, + _new_bed_target = _bedtarget != bt; + if (_new_bed_temp) _bedtemp = bc; + if (_new_bed_target) _bedtarget = bt; + #endif + #if HAS_FAN + static uint8_t _fanspeed = 0; + const bool _new_fanspeed = _fanspeed != thermalManager.fan_speed[0]; + if (_new_fanspeed) _fanspeed = thermalManager.fan_speed[0]; + #endif + + if (checkkey == Tune) { + // Tune page temperature update + #if HAS_HOTEND + if (_new_hotend_target) + Draw_Edit_Integer3(TUNE_CASE_TEMP + MROWS - index_tune, _hotendtarget); + #endif + #if HAS_HEATED_BED + if (_new_bed_target) + Draw_Edit_Integer3(TUNE_CASE_BED + MROWS - index_tune, _bedtarget); + #endif + #if HAS_FAN + if (_new_fanspeed) + Draw_Edit_Integer3(TUNE_CASE_FAN + MROWS - index_tune, _fanspeed); + #endif + } + else if (checkkey == TemperatureID) { + // Temperature page temperature update + #if HAS_HOTEND + if (_new_hotend_target) Draw_Edit_Integer3(TEMP_CASE_TEMP, _hotendtarget); + #endif + #if HAS_HEATED_BED + if (_new_bed_target) Draw_Edit_Integer3(TEMP_CASE_BED, _bedtarget); + #endif + #if HAS_FAN + if (_new_fanspeed) Draw_Edit_Integer3(TEMP_CASE_FAN, _fanspeed); + #endif + } + + // Bottom temperature update + + #if HAS_HOTEND + if (_new_hotend_temp) + Draw_Stat_Int(28, 384, _hotendtemp); + if (_new_hotend_target) + Draw_Stat_Int(25 + 4 * STAT_CHR_W + 6, 384, _hotendtarget); + + static int16_t _flow = 0; + if (_flow != planner.flow_percentage[0]) { + _flow = planner.flow_percentage[0]; + Draw_Stat_Int(116 + 2 * STAT_CHR_W, 417, _flow); + } + #endif + + #if HAS_HEATED_BED + if (_new_bed_temp) + Draw_Stat_Int(28, 417, _bedtemp); + if (_new_bed_target) + Draw_Stat_Int(25 + 4 * STAT_CHR_W + 6, 417, _bedtarget); + #endif + + static int16_t _feedrate = 0; + if (_feedrate != feedrate_percentage) { + _feedrate = feedrate_percentage; + Draw_Stat_Int(116 + 2 * STAT_CHR_W, 384, _feedrate); + } + + #if HAS_FAN + if (_new_fanspeed) { + _fanspeed = thermalManager.fan_speed[0]; + Draw_Stat_Int(195 + 2 * STAT_CHR_W, 384, _fanspeed); + } + #endif + + static float _offset = 0; + if (BABY_Z_VAR != _offset) { + _offset = BABY_Z_VAR; + if (BABY_Z_VAR < 0) { + Draw_Stat_Float(207, 417, -_offset); + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F("-")); + } + else { + Draw_Stat_Float(207, 417, _offset); + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F(" ")); + } + } + + _draw_xyz_position(false); +} + +/** + * Read and cache the working directory. + * + * TODO: New code can follow the pattern of menu_media.cpp + * and rely on Marlin caching for performance. No need to + * cache files here. + */ + +#ifndef strcasecmp_P + #define strcasecmp_P(a, b) strcasecmp((a), (b)) +#endif + +void make_name_without_ext(char *dst, char *src, size_t maxlen=MENU_CHAR_LIMIT) { + char * const name = card.longest_filename(); + size_t pos = strlen(name); // index of ending nul + + // For files, remove the extension + // which may be .gcode, .gco, or .g + if (!card.flag.filenameIsDir) + while (pos && src[pos] != '.') pos--; // find last '.' (stop at 0) + + size_t len = pos; // nul or '.' + if (len > maxlen) { // Keep the name short + pos = len = maxlen; // move nul down + dst[--pos] = '.'; // insert dots + dst[--pos] = '.'; + dst[--pos] = '.'; + } + + dst[len] = '\0'; // end it + + // Copy down to 0 + while (pos--) dst[pos] = src[pos]; +} + +void HMI_SDCardInit() { card.cdroot(); } + +// Initialize or re-initialize the LCD +void MarlinUI::init_lcd() { DWIN_Startup(); } + +void MarlinUI::refresh() { /* Nothing to see here */ } + +#if HAS_LCD_BRIGHTNESS + void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); } +#endif + +#if ENABLED(SCROLL_LONG_FILENAMES) + + char shift_name[LONG_FILENAME_LENGTH + 1]; + int8_t shift_amt; // = 0 + millis_t shift_ms; // = 0 + + // Init the shift name based on the highlighted item + void Init_Shift_Name() { + const bool is_subdir = !card.flag.workDirIsRoot; + const int8_t filenum = select_file.now - 1 - is_subdir; // Skip "Back" and ".." + const uint16_t fileCnt = card.get_num_Files(); + if (WITHIN(filenum, 0, fileCnt - 1)) { + card.getfilename_sorted(SD_ORDER(filenum, fileCnt)); + char * const name = card.longest_filename(); + make_name_without_ext(shift_name, name, 100); + } + } + + void Init_SDItem_Shift() { + shift_amt = 0; + shift_ms = select_file.now != CASE_BACK && strlen(shift_name) > MENU_CHAR_LIMIT + ? millis() + 750UL : 0; + } + +#endif + +/** + * Display an SD item, adding a CDUP for subfolders. + */ +void Draw_SDItem(const uint16_t item, int16_t row=-1) { + if (row < 0) row = item + 1 + MROWS - index_file; + const bool is_subdir = !card.flag.workDirIsRoot; + if (is_subdir && item == 0) { + Draw_Menu_Line(row, ICON_Folder, F("..")); + return; + } + + card.getfilename_sorted(SD_ORDER(item - is_subdir, card.get_num_Files())); + char * const name = card.longest_filename(); + + #if ENABLED(SCROLL_LONG_FILENAMES) + // Init the current selected name + // This is used during scroll drawing + if (item == select_file.now - 1) { + make_name_without_ext(shift_name, name, 100); + Init_SDItem_Shift(); + } + #endif + + // Draw the file/folder with name aligned left + char str[strlen(name) + 1]; + make_name_without_ext(str, name); + Draw_Menu_Line(row, card.flag.filenameIsDir ? ICON_Folder : ICON_File, str); +} + +#if ENABLED(SCROLL_LONG_FILENAMES) + + void Draw_SDItem_Shifted(uint8_t &shift) { + // Limit to the number of chars past the cutoff + const size_t len = strlen(shift_name); + NOMORE(shift, _MAX(len - MENU_CHAR_LIMIT, 0U)); + + // Shorten to the available space + const size_t lastchar = _MIN((signed)len, shift + MENU_CHAR_LIMIT); + + const char c = shift_name[lastchar]; + shift_name[lastchar] = '\0'; + + const uint8_t row = select_file.now + MROWS - index_file; // skip "Back" and scroll + Erase_Menu_Text(row); + Draw_Menu_Line(row, 0, &shift_name[shift]); + + shift_name[lastchar] = c; + } + +#endif + +// Redraw the first set of SD Files +void Redraw_SD_List() { + select_file.reset(); + index_file = MROWS; + + Clear_Menu_Area(); // Leave title bar unchanged + + Draw_Back_First(); + + if (card.isMounted()) { + // As many files as will fit + LOOP_L_N(i, _MIN(nr_sd_menu_items(), MROWS)) + Draw_SDItem(i, i + 1); + + TERN_(SCROLL_LONG_FILENAMES, Init_SDItem_Shift()); + } + else { + DWIN_Draw_Rectangle(1, Color_Bg_Red, 10, MBASE(3) - 10, DWIN_WIDTH - 10, MBASE(4)); + DWIN_Draw_String(false, font16x32, Color_Yellow, Color_Bg_Red, ((DWIN_WIDTH) - 8 * 16) / 2, MBASE(3), F("No Media")); + } +} + +bool DWIN_lcd_sd_status = false; + +void SDCard_Up() { + card.cdup(); + Redraw_SD_List(); + DWIN_lcd_sd_status = false; // On next DWIN_Update +} + +void SDCard_Folder(char * const dirname) { + card.cd(dirname); + Redraw_SD_List(); + DWIN_lcd_sd_status = false; // On next DWIN_Update +} + +// +// Watch for media mount / unmount +// +void HMI_SDCardUpdate() { + if (HMI_flag.home_flag) return; + if (DWIN_lcd_sd_status != card.isMounted()) { + DWIN_lcd_sd_status = card.isMounted(); + //SERIAL_ECHOLNPGM("HMI_SDCardUpdate: ", DWIN_lcd_sd_status); + if (DWIN_lcd_sd_status) { + if (checkkey == SelectFile) + Redraw_SD_List(); + } + else { + // clean file icon + if (checkkey == SelectFile) { + Redraw_SD_List(); + } + else if (checkkey == PrintProcess || checkkey == Tune || printingIsActive()) { + // TODO: Move card removed abort handling + // to CardReader::manage_media. + card.abortFilePrintSoon(); + wait_for_heatup = wait_for_user = false; + dwin_abort_flag = true; // Reset feedrate, return to Home + } + } + DWIN_UpdateLCD(); + } +} + +// +// The status area is always on-screen, except during +// full-screen modal dialogs. (TODO: Keep alive during dialogs) +// +void Draw_Status_Area(const bool with_update) { + + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, STATUS_Y, DWIN_WIDTH, DWIN_HEIGHT - 1); + + #if HAS_HOTEND + DWIN_ICON_Show(ICON, ICON_HotendTemp, 10, 383); + Draw_Stat_Int(28, 384, thermalManager.wholeDegHotend(0)); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Black, 25 + 3 * STAT_CHR_W + 5, 384, F("/")); + Draw_Stat_Int(25 + 4 * STAT_CHR_W + 6, 384, thermalManager.degTargetHotend(0)); + + DWIN_ICON_Show(ICON, ICON_StepE, 112, 417); + Draw_Stat_Int(116 + 2 * STAT_CHR_W, 417, planner.flow_percentage[0]); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Black, 116 + 5 * STAT_CHR_W + 2, 417, F("%")); + #endif + + #if HAS_HEATED_BED + DWIN_ICON_Show(ICON, ICON_BedTemp, 10, 416); + Draw_Stat_Int(28, 417, thermalManager.wholeDegBed()); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Black, 25 + 3 * STAT_CHR_W + 5, 417, F("/")); + Draw_Stat_Int(25 + 4 * STAT_CHR_W + 6, 417, thermalManager.degTargetBed()); + #endif + + DWIN_ICON_Show(ICON, ICON_Speed, 113, 383); + Draw_Stat_Int(116 + 2 * STAT_CHR_W, 384, feedrate_percentage); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Black, 116 + 5 * STAT_CHR_W + 2, 384, F("%")); + + #if HAS_FAN + DWIN_ICON_Show(ICON, ICON_FanSpeed, 187, 383); + Draw_Stat_Int(195 + 2 * STAT_CHR_W, 384, thermalManager.fan_speed[0]); + #endif + + #if HAS_ZOFFSET_ITEM + DWIN_ICON_Show(ICON, ICON_Zoffset, 187, 416); + #endif + + if (BABY_Z_VAR < 0) { + Draw_Stat_Float(207, 417, -BABY_Z_VAR * 100); + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F("-")); + } + else { + Draw_Stat_Float(207, 417, BABY_Z_VAR * 100); + DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F(" ")); + } + + DWIN_Draw_Rectangle(1, Line_Color, 0, 449, DWIN_WIDTH, 451); + + DWIN_ICON_Show(ICON, ICON_MaxSpeedX, 10, 456); + DWIN_ICON_Show(ICON, ICON_MaxSpeedY, 95, 456); + DWIN_ICON_Show(ICON, ICON_MaxSpeedZ, 180, 456); + _draw_xyz_position(true); + + if (with_update) { + DWIN_UpdateLCD(); + delay(5); + } +} + +void HMI_StartFrame(const bool with_update) { + Goto_MainMenu(); + Draw_Status_Area(with_update); +} + +void Draw_Info_Menu() { + Clear_Main_Window(); + + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, (DWIN_WIDTH - strlen(MACHINE_SIZE) * MENU_CHR_W) / 2, 122, F(MACHINE_SIZE)); + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, (DWIN_WIDTH - strlen(SHORT_BUILD_VERSION) * MENU_CHR_W) / 2, 195, F(SHORT_BUILD_VERSION)); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(30, 17, 28, 13); // "Info" + + DWIN_Frame_AreaCopy(1, 197, 149, 252, 161, 108, 102); // "Size" + DWIN_Frame_AreaCopy(1, 1, 164, 56, 176, 108, 175); // "Firmware Version" + DWIN_Frame_AreaCopy(1, 58, 164, 113, 176, 105, 248); // "Contact Details" + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_INFO_SCREEN)); + #else + DWIN_Frame_TitleCopy(192, 15, 23, 12); // "Info" + #endif + + DWIN_Frame_AreaCopy(1, 120, 150, 146, 161, 124, 102); // "Size" + DWIN_Frame_AreaCopy(1, 146, 151, 254, 161, 82, 175); // "Firmware Version" + DWIN_Frame_AreaCopy(1, 1, 164, 96, 175, 89, 248); // "Contact details" + } + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, (DWIN_WIDTH - strlen(CORP_WEBSITE) * MENU_CHR_W) / 2, 268, F(CORP_WEBSITE)); + + Draw_Back_First(); + LOOP_L_N(i, 3) { + DWIN_ICON_Show(ICON, ICON_PrintSize + i, 26, 99 + i * 73); + DWIN_Draw_Line(Line_Color, 16, MBASE(2) + i * 73, 256, 156 + i * 73); + } +} + +void Draw_Print_File_Menu() { + Clear_Title_Bar(); + + if (HMI_IsChinese()) + DWIN_Frame_TitleCopy(0, 31, 56, 14); // "Print file" + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_MEDIA_MENU)); + #else + DWIN_Frame_TitleCopy(52, 31, 86, 11); // "Print file" + #endif + } + + Redraw_SD_List(); +} + +// Main Process +void HMI_MainMenu() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_page.inc(4)) { + switch (select_page.now) { + case PAGE_PRINT: ICON_Print(); break; + case PAGE_PREPARE: ICON_Print(); ICON_Prepare(); break; + case PAGE_CONTROL: ICON_Prepare(); ICON_Control(); break; + case PAGE_INFO_LEVELING: ICON_Control(); TERN(HAS_ONESTEP_LEVELING, ICON_Leveling, ICON_StartInfo)(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_page.dec()) { + switch (select_page.now) { + case PAGE_PRINT: ICON_Print(); ICON_Prepare(); break; + case PAGE_PREPARE: ICON_Prepare(); ICON_Control(); break; + case PAGE_CONTROL: ICON_Control(); TERN(HAS_ONESTEP_LEVELING, ICON_Leveling, ICON_StartInfo)(); break; + case PAGE_INFO_LEVELING: TERN(HAS_ONESTEP_LEVELING, ICON_Leveling, ICON_StartInfo)(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_page.now) { + case PAGE_PRINT: + checkkey = SelectFile; + Draw_Print_File_Menu(); + break; + + case PAGE_PREPARE: + checkkey = Prepare; + select_prepare.reset(); + index_prepare = MROWS; + Draw_Prepare_Menu(); + break; + + case PAGE_CONTROL: + checkkey = Control; + select_control.reset(); + index_control = MROWS; + Draw_Control_Menu(); + break; + + case PAGE_INFO_LEVELING: + #if HAS_ONESTEP_LEVELING + checkkey = Leveling; + HMI_Leveling(); + #else + checkkey = Info; + Draw_Info_Menu(); + #endif + break; + } + } + DWIN_UpdateLCD(); +} + +// Select (and Print) File +void HMI_SelectFile() { + EncoderState encoder_diffState = get_encoder_state(); + + const uint16_t hasUpDir = !card.flag.workDirIsRoot; + + if (encoder_diffState == ENCODER_DIFF_NO) { + #if ENABLED(SCROLL_LONG_FILENAMES) + if (shift_ms && select_file.now >= 1 + hasUpDir) { + // Scroll selected filename every second + const millis_t ms = millis(); + if (ELAPSED(ms, shift_ms)) { + const bool was_reset = shift_amt < 0; + shift_ms = ms + 375UL + was_reset * 250UL; // ms per character + uint8_t shift_new = shift_amt + 1; // Try to shift by... + Draw_SDItem_Shifted(shift_new); // Draw the item + if (!was_reset && shift_new == 0) // Was it limited to 0? + shift_ms = 0; // No scrolling needed + else if (shift_new == shift_amt) // Scroll reached the end + shift_new = -1; // Reset + shift_amt = shift_new; // Set new scroll + } + } + #endif + return; + } + + // First pause is long. Easy. + // On reset, long pause must be after 0. + + const uint16_t fullCnt = nr_sd_menu_items(); + + if (encoder_diffState == ENCODER_DIFF_CW && fullCnt) { + if (select_file.inc(1 + fullCnt)) { + const uint8_t itemnum = select_file.now - 1; // -1 for "Back" + if (TERN0(SCROLL_LONG_FILENAMES, shift_ms)) { // If line was shifted + Erase_Menu_Text(itemnum + MROWS - index_file); // Erase and + Draw_SDItem(itemnum - 1); // redraw + } + if (select_file.now > MROWS && select_file.now > index_file) { // Cursor past the bottom + index_file = select_file.now; // New bottom line + Scroll_Menu(DWIN_SCROLL_UP); + Draw_SDItem(itemnum, MROWS); // Draw and init the shift name + } + else { + Move_Highlight(1, select_file.now + MROWS - index_file); // Just move highlight + TERN_(SCROLL_LONG_FILENAMES, Init_Shift_Name()); // ...and init the shift name + } + TERN_(SCROLL_LONG_FILENAMES, Init_SDItem_Shift()); + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW && fullCnt) { + if (select_file.dec()) { + const uint8_t itemnum = select_file.now - 1; // -1 for "Back" + if (TERN0(SCROLL_LONG_FILENAMES, shift_ms)) { // If line was shifted + Erase_Menu_Text(select_file.now + 1 + MROWS - index_file); // Erase and + Draw_SDItem(itemnum + 1); // redraw + } + if (select_file.now < index_file - MROWS) { // Cursor past the top + index_file--; // New bottom line + Scroll_Menu(DWIN_SCROLL_DOWN); + if (index_file == MROWS) { + Draw_Back_First(); + TERN_(SCROLL_LONG_FILENAMES, shift_ms = 0); + } + else + Draw_SDItem(itemnum, 0); // Draw the item (and init shift name) + } + else { + Move_Highlight(-1, select_file.now + MROWS - index_file); // Just move highlight + TERN_(SCROLL_LONG_FILENAMES, Init_Shift_Name()); // ...and init the shift name + } + TERN_(SCROLL_LONG_FILENAMES, Init_SDItem_Shift()); // Reset left. Init timer. + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (select_file.now == CASE_BACK) { // Back + select_page.set(0); + Goto_MainMenu(); + } + else if (hasUpDir && select_file.now == 1) { // CD-Up + SDCard_Up(); + goto HMI_SelectFileExit; + } + else { + const uint16_t filenum = select_file.now - 1 - hasUpDir; + card.getfilename_sorted(SD_ORDER(filenum, card.get_num_Files())); + + // Enter that folder! + if (card.flag.filenameIsDir) { + SDCard_Folder(card.filename); + goto HMI_SelectFileExit; + } + + // Reset highlight for next entry + select_print.reset(); + select_file.reset(); + + // Start choice and print SD file + HMI_flag.heat_flag = true; + HMI_flag.print_finish = false; + HMI_ValueStruct.show_mode = 0; + + card.openAndPrintFile(card.filename); + + #if HAS_FAN + // All fans on for Ender 3 v2 ? + // The slicer should manage this for us. + //for (uint8_t i = 0; i < FAN_COUNT; i++) + // thermalManager.fan_speed[i] = 255; + #endif + + _card_percent = 0; + _remain_time = 0; + Goto_PrintProcess(); + } + } + + HMI_SelectFileExit: + DWIN_UpdateLCD(); +} + +// Printing +void HMI_Printing() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + if (HMI_flag.done_confirm_flag) { + if (encoder_diffState == ENCODER_DIFF_ENTER) { + HMI_flag.done_confirm_flag = false; + dwin_abort_flag = true; // Reset feedrate, return to Home + } + return; + } + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_print.inc(3)) { + switch (select_print.now) { + case PRINT_SETUP: ICON_Tune(); break; + case PRINT_PAUSE_RESUME: ICON_Tune(); ICON_ResumeOrPause(); break; + case PRINT_STOP: ICON_ResumeOrPause(); ICON_Stop(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_print.dec()) { + switch (select_print.now) { + case PRINT_SETUP: ICON_Tune(); ICON_ResumeOrPause(); break; + case PRINT_PAUSE_RESUME: ICON_ResumeOrPause(); ICON_Stop(); break; + case PRINT_STOP: ICON_Stop(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_print.now) { + case PRINT_SETUP: + checkkey = Tune; + HMI_ValueStruct.show_mode = 0; + select_tune.reset(); + index_tune = MROWS; + Draw_Tune_Menu(); + break; + + case PRINT_PAUSE_RESUME: + if (HMI_flag.pause_flag) { + ICON_Pause(); + + char cmd[40]; + cmd[0] = '\0'; + + #if BOTH(HAS_HEATED_BED, PAUSE_HEAT) + if (resume_bed_temp) sprintf_P(cmd, PSTR("M190 S%i\n"), resume_bed_temp); + #endif + #if BOTH(HAS_HOTEND, PAUSE_HEAT) + if (resume_hotend_temp) sprintf_P(&cmd[strlen(cmd)], PSTR("M109 S%i\n"), resume_hotend_temp); + #endif + + strcat_P(cmd, M24_STR); + queue.inject(cmd); + } + else { + HMI_flag.select_flag = true; + checkkey = Print_window; + Popup_window_PauseOrStop(); + } + break; + + case PRINT_STOP: + HMI_flag.select_flag = true; + checkkey = Print_window; + Popup_window_PauseOrStop(); + break; + + default: break; + } + } + DWIN_UpdateLCD(); +} + +// Pause and Stop window +void HMI_PauseOrStop() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + if (encoder_diffState == ENCODER_DIFF_CW) + Draw_Select_Highlight(false); + else if (encoder_diffState == ENCODER_DIFF_CCW) + Draw_Select_Highlight(true); + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (select_print.now == PRINT_PAUSE_RESUME) { + if (HMI_flag.select_flag) { + HMI_flag.pause_action = true; + queue.inject(F("M25")); + } + Goto_PrintProcess(); + } + else if (select_print.now == PRINT_STOP) { + if (HMI_flag.select_flag) { + checkkey = Back_Main; + wait_for_heatup = wait_for_user = false; // Stop waiting for heating/user + card.abortFilePrintSoon(); // Let the main loop handle SD abort + dwin_abort_flag = true; // Reset feedrate, return to Home + #ifdef ACTION_ON_CANCEL + hostui.cancel(); + #endif + Popup_Window_Home(true); + if (HMI_flag.home_flag) planner.synchronize(); // Wait for planner moves to finish! + } + else + Goto_PrintProcess(); // cancel stop + } + } + DWIN_UpdateLCD(); +} + +void Draw_Move_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(192, 1, 42, 14); // "Move" + Item_AreaCopy(58, 118, 106, 132, 1); + Item_AreaCopy(109, 118, 157, 132, 2); + Item_AreaCopy(160, 118, 209, 132, 3); + TERN_(HAS_HOTEND, Item_AreaCopy(212, 118, 253, 131, 4)); + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_MOVE_AXIS)); + #else + DWIN_Frame_TitleCopy(231, 2, 35, 11); // "Move" + #endif + + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(1, GET_TEXT_F(MSG_MOVE_X)); + DWIN_Draw_Label(2, GET_TEXT_F(MSG_MOVE_Y)); + DWIN_Draw_Label(3, GET_TEXT_F(MSG_MOVE_Z)); + TERN_(HAS_HOTEND, DWIN_Draw_Label(4, GET_TEXT_F(MSG_MOVE_E))); + #else + say_move_en(1); say_x_en(38, 1); // "Move X" + say_move_en(2); say_y_en(38, 2); // "Move Y" + say_move_en(3); say_z_en(38, 3); // "Move Z" + TERN_(HAS_HOTEND, (say_move_en(4), Item_AreaCopy(99, 194, 151, 204, 4, 38))); // "Move Extruder" + #endif + } + + Draw_Back_First(select_axis.now == CASE_BACK); + if (select_axis.now != CASE_BACK) Draw_Menu_Cursor(select_axis.now); + + // Draw separators and icons + LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_MoveX + i); +} + +void Item_Adv_HomeOffsets(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Set Home Offsets" + } + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_SET_HOME_OFFSETS)); + #else + Item_AreaCopy(1, 76, 102, 87, row); // "Set Home Offsets" + #endif + } + Draw_Menu_Line(row, ICON_HomeOffset); + Draw_More_Icon(row); +} + +#if HAS_ONESTEP_LEVELING + + void Item_Adv_ProbeOffsets(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Probe Offsets" + } + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_ZPROBE_OFFSETS)); + #else + say_probe_offs_en(row); + #endif + } + Draw_Menu_Line(row, ICON_ProbeOffset); + Draw_More_Icon(row); + } + +#endif + +void Item_Adv_HotendPID(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Hotend PID" + } + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, F("Hotend PID")); + #else + Item_AreaCopy(96, 104, 167, 114, row); // "Hotend PID" + #endif + } + Draw_Menu_Line(row, ICON_PIDNozzle); +} + +void Item_Adv_BedPID(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Bed PID" + } + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, F("Bed PID")); + #else + Item_AreaCopy(241, 104, 263, 115, row); // "Bed" + Item_AreaCopy(145, 104, 167, 114, row, 27); // "PID" + #endif + } + Draw_Menu_Line(row, ICON_PIDbed); +} + +#if ENABLED(POWER_LOSS_RECOVERY) + + void Item_Adv_PLR(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Power-loss Recovery" + } + else { + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(row, GET_TEXT_F(MSG_ZPROBE_OFFSETS)); + #else + Item_AreaCopy(1, 208, 137, 221, row); // "Power-loss Recovery" + #endif + } + Draw_Menu_Line(row, ICON_Motion); + Draw_Checkbox_Line(row, recovery.enabled); + } + +#endif + +void Draw_AdvancedSettings_Menu() { + Clear_Main_Window(); + + #if ADVSET_CASE_TOTAL >= TROWS + const int16_t scroll = MROWS - index_advset; // Scrolled-up lines + #else + constexpr int16_t scroll = 0; + #endif + #define ASCROL(L) (scroll + (L)) + #define AVISI(L) VISI(ADVSET_CASE_TOTAL, L, ASCROL(L)) + + if (false && HMI_IsChinese()) { + // TODO: Chinese "Advanced Settings" + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_ADVANCED_SETTINGS)); + #else + DWIN_Frame_TitleCopy(93, 401, 126, 15); // "Advanced Settings" + #endif + } + + if (AVISI(0)) Draw_Back_First(select_advset.now == CASE_BACK); + if (AVISI(ADVSET_CASE_HOMEOFF)) Item_Adv_HomeOffsets(ASCROL(ADVSET_CASE_HOMEOFF)); // Set Home Offsets > + #if HAS_ONESTEP_LEVELING + if (AVISI(ADVSET_CASE_PROBEOFF)) Item_Adv_ProbeOffsets(ASCROL(ADVSET_CASE_PROBEOFF)); // Probe Offsets > + #endif + if (AVISI(ADVSET_CASE_HEPID)) Item_Adv_HotendPID(ASCROL(ADVSET_CASE_HEPID)); // Nozzle PID + if (AVISI(ADVSET_CASE_BEDPID)) Item_Adv_BedPID(ASCROL(ADVSET_CASE_BEDPID)); // Bed PID + #if ENABLED(POWER_LOSS_RECOVERY) + if (AVISI(ADVSET_CASE_PWRLOSSR)) Item_Adv_PLR(ASCROL(ADVSET_CASE_PWRLOSSR)); // Power-loss recovery + #endif + if (select_advset.now != CASE_BACK) Draw_Menu_Cursor(ASCROL(select_advset.now)); +} + +void Item_HomeOffs_X(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Home Offset X" + } + else { + #ifdef USE_STRING_TITLES + Draw_Menu_Line(row, ICON_HomeOffsetX, GET_TEXT_F(MSG_HOME_OFFSET_X)); + #else + say_home_offs_en(row); say_x_en(75, row); // "Home Offset X" + #endif + } + Draw_Menu_Line(row, ICON_HomeOffset); + Draw_Edit_Signed_Float3(row, HMI_ValueStruct.Home_OffX_scaled); +} + +void Item_HomeOffs_Y(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Home Offset Y" + } + else { + #ifdef USE_STRING_TITLES + Draw_Menu_Line(row, ICON_HomeOffsetY, GET_TEXT_F(MSG_HOME_OFFSET_Y)); + #else + say_home_offs_en(row); say_y_en(75, row); // "Home Offset X" + #endif + } + Draw_Menu_Line(row, ICON_HomeOffset); + Draw_Edit_Signed_Float3(row, HMI_ValueStruct.Home_OffY_scaled); +} + +void Item_HomeOffs_Z(const uint8_t row) { + if (false && HMI_IsChinese()) { + // TODO: Chinese "Home Offset Z" + } + else { + #ifdef USE_STRING_TITLES + Draw_Menu_Line(row, ICON_HomeOffsetZ, GET_TEXT_F(MSG_HOME_OFFSET_Z)); + #else + say_home_offs_en(row); say_z_en(75, row); // "Home Offset Z" + #endif + } + Draw_Menu_Line(row, ICON_HomeOffset); + Draw_Edit_Signed_Float3(row, HMI_ValueStruct.Home_OffZ_scaled); +} + +void Draw_HomeOff_Menu() { + Clear_Main_Window(); + if (false && HMI_IsChinese()) { + // TODO: Chinese "Home Offsets" + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_SET_HOME_OFFSETS)); + #else + DWIN_Frame_TitleCopy(1, 401, 91, 12); // "Home Offsets" + #endif + } + Draw_Back_First(select_item.now == CASE_BACK); + Item_HomeOffs_X(1); // "Home Offset X" + Item_HomeOffs_Y(2); // "Home Offset Y" + Item_HomeOffs_Z(3); // "Home Offset Z" + if (select_item.now != CASE_BACK) Draw_Menu_Cursor(select_item.now); +} + +#if HAS_ONESTEP_LEVELING + + void Draw_ProbeOff_Menu() { + Clear_Main_Window(); + Draw_Back_First(select_item.now == CASE_BACK); + if (false && HMI_IsChinese()) { + // TODO: Chinese "Probe Offsets" + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_ZPROBE_OFFSETS)); + #else + DWIN_Frame_TitleCopy(124, 431, 91, 12); // "Probe Offsets" + #endif + #ifdef USE_STRING_TITLES + Draw_Menu_Line(1, ICON_ProbeOffsetX, GET_TEXT_F(MSG_ZPROBE_XOFFSET)); // Probe X Offset + Draw_Menu_Line(2, ICON_ProbeOffsetY, GET_TEXT_F(MSG_ZPROBE_YOFFSET)); // Probe Y Offset + #else + say_probe_offs_en(1); say_x_en(75, 1); // "Probe Offset X" + say_probe_offs_en(2); say_y_en(75, 2); // "Probe Offset Y" + #endif + } + + Draw_Edit_Signed_Float3(1, HMI_ValueStruct.Probe_OffX_scaled); + Draw_Edit_Signed_Float3(2, HMI_ValueStruct.Probe_OffY_scaled); + + if (select_item.now != CASE_BACK) Draw_Menu_Cursor(select_item.now); + } + +#endif + +#include "../../../libs/buzzer.h" + +void HMI_AudioFeedback(const bool success=true) { + if (success) { + BUZZ(100, 659); + BUZZ(10, 0); + BUZZ(100, 698); + } + else + BUZZ(40, 440); +} + +// Prepare +void HMI_Prepare() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_prepare.inc(1 + PREPARE_CASE_TOTAL)) { + if (select_prepare.now > MROWS && select_prepare.now > index_prepare) { + index_prepare = select_prepare.now; + + // Scroll up and draw a blank bottom line + Scroll_Menu(DWIN_SCROLL_UP); + Draw_Menu_Icon(MROWS, ICON_Axis + select_prepare.now - 1); + + // Draw "More" icon for sub-menus + if (index_prepare < 7) Draw_More_Icon(MROWS - index_prepare + 1); + + #if PREHEAT_COUNT > 1 + if (index_prepare == PREPARE_CASE_ABS) Item_Prepare_ABS(MROWS); + #endif + #if HAS_HOTEND || HAS_HEATED_BED + if (index_prepare == PREPARE_CASE_COOL) Item_Prepare_Cool(MROWS); + #endif + if (index_prepare == PREPARE_CASE_LANG) Item_Prepare_Lang(MROWS); + } + else { + Move_Highlight(1, select_prepare.now + MROWS - index_prepare); + } + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_prepare.dec()) { + if (select_prepare.now < index_prepare - MROWS) { + index_prepare--; + Scroll_Menu(DWIN_SCROLL_DOWN); + + if (index_prepare == MROWS) + Draw_Back_First(); + else + Draw_Menu_Line(0, ICON_Axis + select_prepare.now - 1); + + if (index_prepare < 7) Draw_More_Icon(MROWS - index_prepare + 1); + + if (index_prepare == 6) Item_Prepare_Move(0); + else if (index_prepare == 7) Item_Prepare_Disable(0); + else if (index_prepare == 8) Item_Prepare_Home(0); + } + else { + Move_Highlight(-1, select_prepare.now + MROWS - index_prepare); + } + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_prepare.now) { + case CASE_BACK: + select_page.set(1); + Goto_MainMenu(); + break; + case PREPARE_CASE_MOVE: + checkkey = AxisMove; + select_axis.reset(); + Draw_Move_Menu(); + + Draw_Edit_Float3(1, current_position.x * MINUNITMULT); + Draw_Edit_Float3(2, current_position.y * MINUNITMULT); + Draw_Edit_Float3(3, current_position.z * MINUNITMULT); + #if HAS_HOTEND + HMI_ValueStruct.Move_E_scaled = current_position.e * MINUNITMULT; + Draw_Edit_Signed_Float3(4, HMI_ValueStruct.Move_E_scaled); + #endif + break; + + case PREPARE_CASE_DISA: queue.inject(F("M84")); break; + + case PREPARE_CASE_HOME: // Homing + checkkey = Last_Prepare; + index_prepare = MROWS; + queue.inject_P(G28_STR); // G28 will set home_flag + Popup_Window_Home(); + break; + + #if HAS_ZOFFSET_ITEM + case PREPARE_CASE_ZOFF: + #if EITHER(HAS_BED_PROBE, BABYSTEPPING) + checkkey = Homeoffset; + HMI_ValueStruct.show_mode = -4; + HMI_ValueStruct.offset_value = BABY_Z_VAR * 100; + Draw_Edit_Signed_Float2(PREPARE_CASE_ZOFF + MROWS - index_prepare, HMI_ValueStruct.offset_value, true); + EncoderRate.enabled = true; + #else + // Apply workspace offset, making the current position 0,0,0 + queue.inject(F("G92X0Y0Z0")); + HMI_AudioFeedback(); + #endif + break; + #endif + + #if HAS_PREHEAT + case PREPARE_CASE_PLA: ui.preheat_all(0); break; + #if PREHEAT_COUNT > 1 + case PREPARE_CASE_ABS: ui.preheat_all(1); break; + #endif + #endif + + #if HAS_HOTEND || HAS_HEATED_BED + case PREPARE_CASE_COOL: + thermalManager.cooldown(); + ui.reset_status(); + break; + #endif + + case PREPARE_CASE_LANG: + HMI_ToggleLanguage(); + Draw_Prepare_Menu(); + break; + + default: break; + } + } + DWIN_UpdateLCD(); +} + +void Draw_Temperature_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(236, 2, 28, 12); // "Temperature" + #if HAS_HOTEND + Item_AreaCopy(1, 134, 56, 146, TEMP_CASE_TEMP); + #endif + #if HAS_HEATED_BED + Item_AreaCopy(58, 134, 113, 146, TEMP_CASE_BED); + #endif + #if HAS_FAN + Item_AreaCopy(115, 134, 170, 146, TEMP_CASE_FAN); + #endif + #if HAS_PREHEAT + Item_AreaCopy(100, 89, 178, 101, TEMP_CASE_PLA); + #if PREHEAT_COUNT > 1 + Item_AreaCopy(180, 89, 260, 100, TEMP_CASE_ABS); + #endif + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_TEMPERATURE)); + #else + DWIN_Frame_TitleCopy(56, 15, 85, 14); // "Temperature" + #endif + #ifdef USE_STRING_TITLES + #if HAS_HOTEND + DWIN_Draw_Label(TEMP_CASE_TEMP, GET_TEXT_F(MSG_UBL_SET_TEMP_HOTEND)); + #endif + #if HAS_HEATED_BED + DWIN_Draw_Label(TEMP_CASE_BED, GET_TEXT_F(MSG_UBL_SET_TEMP_BED)); + #endif + #if HAS_FAN + DWIN_Draw_Label(TEMP_CASE_FAN, GET_TEXT_F(MSG_FAN_SPEED)); + #endif + #if HAS_PREHEAT + DWIN_Draw_Label(TEMP_CASE_PLA, F(PREHEAT_1_LABEL " Preheat Settings")); + #if PREHEAT_COUNT > 1 + DWIN_Draw_Label(TEMP_CASE_ABS, F(PREHEAT_2_LABEL " Preheat Settings")); + #endif + #endif + #else + #if HAS_HOTEND + Item_AreaCopy(197, 104, 238, 114, TEMP_CASE_TEMP); // "Nozzle" + Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_TEMP, 44); // "Temperature" + #endif + #if HAS_HEATED_BED + Item_AreaCopy(240, 104, 264, 114, TEMP_CASE_BED); // "Bed" + Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_BED, 27); // "Temperature" + #endif + #if HAS_FAN + Item_AreaCopy( 1, 119, 61, 132, TEMP_CASE_FAN); // "Fan speed" + #endif + #if HAS_PREHEAT + Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_PLA); // "Preheat" + say_pla_en(52, TEMP_CASE_PLA); // "PLA" + Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_PLA, 79); // "Settings" + #if PREHEAT_COUNT > 1 + Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_ABS); // "Preheat" + say_abs_en(52, TEMP_CASE_ABS); // "ABS" + Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_ABS, 81); // "Settings" + #endif + #endif + #endif + } + + Draw_Back_First(select_temp.now == CASE_BACK); + if (select_temp.now != CASE_BACK) Draw_Menu_Cursor(select_temp.now); + + // Draw icons and lines + uint8_t i = 0; + #define _TMENU_ICON(N) Draw_Menu_Line(++i, ICON_SetEndTemp + (N) - 1) + #if HAS_HOTEND + _TMENU_ICON(TEMP_CASE_TEMP); + Draw_Edit_Integer3(i, thermalManager.degTargetHotend(0)); + #endif + #if HAS_HEATED_BED + _TMENU_ICON(TEMP_CASE_BED); + Draw_Edit_Integer3(i, thermalManager.degTargetBed()); + #endif + #if HAS_FAN + _TMENU_ICON(TEMP_CASE_FAN); + Draw_Edit_Integer3(i, thermalManager.fan_speed[0]); + #endif + #if HAS_PREHEAT + // PLA/ABS items have submenus + _TMENU_ICON(TEMP_CASE_PLA); Draw_More_Icon(i); + #if PREHEAT_COUNT > 1 + _TMENU_ICON(TEMP_CASE_ABS); Draw_More_Icon(i); + #endif + #endif +} + +// Control +void HMI_Control() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_control.inc(1 + CONTROL_CASE_TOTAL)) { + if (select_control.now > MROWS && select_control.now > index_control) { + index_control = select_control.now; + + // Scroll up and draw a blank bottom line + Scroll_Menu(DWIN_SCROLL_UP); + + switch (index_control) { // Last menu items + case CONTROL_CASE_ADVSET: Item_Control_Advanced(MROWS); break; + case CONTROL_CASE_INFO: Item_Control_Info(MROWS); break; + default: break; + } + + } + else + Move_Highlight(1, select_control.now + MROWS - index_control); + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_control.dec()) { + if (select_control.now < index_control - MROWS) { + index_control--; + Scroll_Menu(DWIN_SCROLL_DOWN); + switch (index_control) { // First menu items + case MROWS: Draw_Back_First(); break; + case MROWS + 1: Item_Control_Temp(0); break; + case MROWS + 2: Item_Control_Motion(0); break; + default: break; + } + } + else + Move_Highlight(-1, select_control.now + MROWS - index_control); + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_control.now) { + case CASE_BACK: + select_page.set(2); + Goto_MainMenu(); + break; + case CONTROL_CASE_TEMP: + checkkey = TemperatureID; + HMI_ValueStruct.show_mode = -1; + select_temp.reset(); + Draw_Temperature_Menu(); + break; + case CONTROL_CASE_MOVE: + checkkey = Motion; + select_motion.reset(); + Draw_Motion_Menu(); + break; + #if ENABLED(EEPROM_SETTINGS) + case CONTROL_CASE_SAVE: { + const bool success = settings.save(); + HMI_AudioFeedback(success); + } break; + case CONTROL_CASE_LOAD: { + const bool success = settings.load(); + HMI_AudioFeedback(success); + } break; + case CONTROL_CASE_RESET: + settings.reset(); + HMI_AudioFeedback(); + break; + #endif + case CONTROL_CASE_ADVSET: + checkkey = AdvSet; + select_advset.reset(); + Draw_AdvancedSettings_Menu(); + break; + case CONTROL_CASE_INFO: + checkkey = Info; + Draw_Info_Menu(); + break; + default: break; + } + } + DWIN_UpdateLCD(); +} + +#if HAS_ONESTEP_LEVELING + // Leveling + void HMI_Leveling() { + Popup_Window_Leveling(); + DWIN_UpdateLCD(); + queue.inject(F("G28O\nG29")); + } +#endif + +// Axis Move +void HMI_AxisMove() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + #if ENABLED(PREVENT_COLD_EXTRUSION) + // popup window resume + if (HMI_flag.cold_flag) { + if (encoder_diffState == ENCODER_DIFF_ENTER) { + HMI_flag.cold_flag = false; + HMI_ValueStruct.Move_E_scaled = current_position.e * MINUNITMULT; + Draw_Move_Menu(); + Draw_Edit_Float3(1, HMI_ValueStruct.Move_X_scaled); + Draw_Edit_Float3(2, HMI_ValueStruct.Move_Y_scaled); + Draw_Edit_Float3(3, HMI_ValueStruct.Move_Z_scaled); + Draw_Edit_Signed_Float3(4, 0); + DWIN_UpdateLCD(); + } + return; + } + #endif + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_axis.inc(1 + 3 + ENABLED(HAS_HOTEND))) Move_Highlight(1, select_axis.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_axis.dec()) Move_Highlight(-1, select_axis.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_axis.now) { + case CASE_BACK: + checkkey = Prepare; + select_prepare.set(1); + index_prepare = MROWS; + Draw_Prepare_Menu(); + break; + case 1: // X axis move + checkkey = Move_X; + HMI_ValueStruct.Move_X_scaled = current_position.x * MINUNITMULT; + Draw_Edit_Float3(1, HMI_ValueStruct.Move_X_scaled, true); + EncoderRate.enabled = true; + break; + case 2: // Y axis move + checkkey = Move_Y; + HMI_ValueStruct.Move_Y_scaled = current_position.y * MINUNITMULT; + Draw_Edit_Float3(2, HMI_ValueStruct.Move_Y_scaled, true); + EncoderRate.enabled = true; + break; + case 3: // Z axis move + checkkey = Move_Z; + HMI_ValueStruct.Move_Z_scaled = current_position.z * MINUNITMULT; + Draw_Edit_Float3(3, HMI_ValueStruct.Move_Z_scaled, true); + EncoderRate.enabled = true; + break; + #if HAS_HOTEND + case 4: // Extruder + #if ENABLED(PREVENT_COLD_EXTRUSION) + if (thermalManager.tooColdToExtrude(0)) { + HMI_flag.cold_flag = true; + Popup_Window_ETempTooLow(); + DWIN_UpdateLCD(); + return; + } + #endif + checkkey = Extruder; + HMI_ValueStruct.Move_E_scaled = current_position.e * MINUNITMULT; + Draw_Edit_Signed_Float3(4, HMI_ValueStruct.Move_E_scaled, true); + EncoderRate.enabled = true; + break; + #endif + } + } + DWIN_UpdateLCD(); +} + +// TemperatureID +void HMI_Temperature() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_temp.inc(1 + TEMP_CASE_TOTAL)) Move_Highlight(1, select_temp.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_temp.dec()) Move_Highlight(-1, select_temp.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_temp.now) { + case CASE_BACK: + checkkey = Control; + select_control.set(1); + index_control = MROWS; + Draw_Control_Menu(); + break; + #if HAS_HOTEND + case TEMP_CASE_TEMP: + checkkey = ETemp; + HMI_ValueStruct.E_Temp = thermalManager.degTargetHotend(0); + Draw_Edit_Integer3(1, HMI_ValueStruct.E_Temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_HEATED_BED + case TEMP_CASE_BED: + checkkey = BedTemp; + HMI_ValueStruct.Bed_Temp = thermalManager.degTargetBed(); + Draw_Edit_Integer3(2, HMI_ValueStruct.Bed_Temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_FAN + case TEMP_CASE_FAN: + checkkey = FanSpeed; + HMI_ValueStruct.Fan_speed = thermalManager.fan_speed[0]; + Draw_Edit_Integer3(3, HMI_ValueStruct.Fan_speed, true); + EncoderRate.enabled = true; + break; + #endif + + #if HAS_PREHEAT + case TEMP_CASE_PLA: { + checkkey = PLAPreheat; + select_PLA.reset(); + HMI_ValueStruct.show_mode = -2; + + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(59, 16, 81, 14); // "PLA Settings" + Item_AreaCopy(100, 89, 124, 101, PREHEAT_CASE_TEMP); + Item_AreaCopy(1, 134, 56, 146, PREHEAT_CASE_TEMP, 24); // PLA nozzle temp + #if HAS_HEATED_BED + Item_AreaCopy(100, 89, 124, 101, PREHEAT_CASE_BED); + Item_AreaCopy(58, 134, 113, 146, PREHEAT_CASE_BED, 24); // PLA bed temp + #endif + #if HAS_FAN + Item_AreaCopy(100, 89, 124, 101, PREHEAT_CASE_FAN); + Item_AreaCopy(115, 134, 170, 146, PREHEAT_CASE_FAN, 24); // PLA fan speed + #endif + #if ENABLED(EEPROM_SETTINGS) + Item_AreaCopy(72, 148, 151, 162, PREHEAT_CASE_SAVE); // Save PLA configuration + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(F(PREHEAT_1_LABEL " Settings")); // TODO: GET_TEXT_F + #else + DWIN_Frame_TitleCopy(56, 15, 85, 14); // "Temperature" TODO: "PLA Settings" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(PREHEAT_CASE_TEMP, F("Nozzle Temp")); + #if HAS_HEATED_BED + DWIN_Draw_Label(PREHEAT_CASE_BED, F("Bed Temp")); + #endif + #if HAS_FAN + DWIN_Draw_Label(PREHEAT_CASE_FAN, GET_TEXT_F(MSG_FAN_SPEED)); + #endif + #if ENABLED(EEPROM_SETTINGS) + DWIN_Draw_Label(PREHEAT_CASE_SAVE, GET_TEXT_F(MSG_STORE_EEPROM)); + #endif + #else + say_pla_en(0, PREHEAT_CASE_TEMP); // "PLA" + Item_AreaCopy(198, 104, 237, 114, PREHEAT_CASE_TEMP, 27); // "Nozzle" + Item_AreaCopy(1, 89, 81, 102, PREHEAT_CASE_TEMP, 71); // "Temperature" + #if HAS_HEATED_BED + say_pla_en(0, PREHEAT_CASE_BED); // "PLA" + Item_AreaCopy(240, 104, 264, 114, PREHEAT_CASE_BED, 27); // "Bed" + Item_AreaCopy(1, 89, 83, 101, PREHEAT_CASE_BED, 54); // "Temperature" + #endif + #if HAS_FAN + say_pla_en(0, PREHEAT_CASE_FAN); // "PLA" + Item_AreaCopy(0, 119, 64, 132, PREHEAT_CASE_FAN, 27); // "Fan speed" + #endif + #if ENABLED(EEPROM_SETTINGS) + Item_AreaCopy(98, 164, 233, 177, PREHEAT_CASE_SAVE); // "Save PLA parameters" + #endif + #endif + } + + Draw_Back_First(); + + uint8_t i = 0; + Draw_Menu_Line(++i, ICON_SetEndTemp); + Draw_Edit_Integer3(i, ui.material_preset[0].hotend_temp); + #if HAS_HEATED_BED + Draw_Menu_Line(++i, ICON_SetBedTemp); + Draw_Edit_Integer3(i, ui.material_preset[0].bed_temp); + #endif + #if HAS_FAN + Draw_Menu_Line(++i, ICON_FanSpeed); + Draw_Edit_Integer3(i, ui.material_preset[0].fan_speed); + #endif + #if ENABLED(EEPROM_SETTINGS) + Draw_Menu_Line(++i, ICON_WriteEEPROM); + #endif + } break; + #endif // HAS_PREHEAT + + #if PREHEAT_COUNT > 1 + case TEMP_CASE_ABS: { // ABS preheat setting + checkkey = ABSPreheat; + select_ABS.reset(); + HMI_ValueStruct.show_mode = -3; + + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(142, 16, 82, 14); // "ABS Settings" + + Item_AreaCopy(180, 89, 204, 100, PREHEAT_CASE_TEMP); + Item_AreaCopy(1, 134, 56, 146, PREHEAT_CASE_TEMP, 24); // ABS nozzle temp + #if HAS_HEATED_BED + Item_AreaCopy(180, 89, 204, 100, PREHEAT_CASE_BED); + Item_AreaCopy(58, 134, 113, 146, PREHEAT_CASE_BED, 24); // ABS bed temp + #endif + #if HAS_FAN + Item_AreaCopy(180, 89, 204, 100, PREHEAT_CASE_FAN); + Item_AreaCopy(115, 134, 170, 146, PREHEAT_CASE_FAN, 24); // ABS fan speed + #endif + #if ENABLED(EEPROM_SETTINGS) + Item_AreaCopy(72, 148, 151, 162, PREHEAT_CASE_SAVE); + Item_AreaCopy(180, 89, 204, 100, PREHEAT_CASE_SAVE, 28, 2); // Save ABS configuration + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(F("ABS Settings")); // TODO: GET_TEXT_F + #else + DWIN_Frame_TitleCopy(56, 15, 85, 14); // "Temperature" TODO: "ABS Settings" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(PREHEAT_CASE_TEMP, F("Nozzle Temp")); + #if HAS_HEATED_BED + DWIN_Draw_Label(PREHEAT_CASE_BED, F("Bed Temp")); + #endif + #if HAS_FAN + DWIN_Draw_Label(PREHEAT_CASE_FAN, GET_TEXT_F(MSG_FAN_SPEED)); + #endif + #if ENABLED(EEPROM_SETTINGS) + DWIN_Draw_Label(PREHEAT_CASE_SAVE, GET_TEXT_F(MSG_STORE_EEPROM)); + #endif + #else + say_abs_en(0, PREHEAT_CASE_TEMP); // "ABS" + Item_AreaCopy(197, 104, 238, 114, PREHEAT_CASE_TEMP, 29); // "Nozzle" + Item_AreaCopy(1, 89, 34, 102, PREHEAT_CASE_TEMP, 73); // "Temp" + #if HAS_HEATED_BED + say_abs_en(0, PREHEAT_CASE_BED); // "ABS" + Item_AreaCopy(240, 104, 264, 114, PREHEAT_CASE_BED, 29); // "Bed" + Item_AreaCopy(1, 89, 83, 102, PREHEAT_CASE_BED, 56); // "Temperature" + #endif + #if HAS_FAN + say_abs_en(0, PREHEAT_CASE_FAN); // "ABS" + Item_AreaCopy(0, 119, 64, 132, PREHEAT_CASE_FAN, 29); // "Fan speed" + #endif + #if ENABLED(EEPROM_SETTINGS) + Item_AreaCopy(98, 165, 233, 177, PREHEAT_CASE_SAVE); // "Save PLA parameters" + say_abs_en(33, PREHEAT_CASE_SAVE); // "ABS" + #endif + #endif + } + + Draw_Back_First(); + + uint8_t i = 0; + Draw_Menu_Line(++i, ICON_SetEndTemp); + Draw_Edit_Integer3(i, ui.material_preset[1].hotend_temp); + #if HAS_HEATED_BED + Draw_Menu_Line(++i, ICON_SetBedTemp); + Draw_Edit_Integer3(i, ui.material_preset[1].bed_temp); + #endif + #if HAS_FAN + Draw_Menu_Line(++i, ICON_FanSpeed); + Draw_Edit_Integer3(i, ui.material_preset[1].fan_speed); + #endif + #if ENABLED(EEPROM_SETTINGS) + Draw_Menu_Line(++i, ICON_WriteEEPROM); + #endif + + } break; + + #endif // PREHEAT_COUNT > 1 + } + } + DWIN_UpdateLCD(); +} + +void Draw_Max_Speed_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(1, 16, 28, 13); // "Max Speed (mm/s)" + + auto say_max_speed_cn = [](const uint8_t line) { + Item_AreaCopy(173, 133, 228, 147, line); // "Max speed" + }; + + say_max_speed_cn(1); // "Max speed" + Item_AreaCopy(229, 133, 236, 147, 1, 58); // "X" + say_max_speed_cn(2); // "Max speed" + Item_AreaCopy(1, 150, 7, 160, 2, 58, 3); // "Y" + say_max_speed_cn(3); // "Max speed" + Item_AreaCopy(9, 150, 16, 160, 3, 58, 3); // "Z" + #if HAS_HOTEND + say_max_speed_cn(4); // "Max speed" + Item_AreaCopy(18, 150, 25, 160, 4, 58, 3); // "E" + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(F("Max Speed (mm/s)")); // TODO: GET_TEXT_F + #else + DWIN_Frame_TitleCopy(144, 16, 46, 11); // "Max Speed (mm/s)" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(1, F("Max Feedrate X")); + DWIN_Draw_Label(2, F("Max Feedrate Y")); + DWIN_Draw_Label(3, F("Max Feedrate Z")); + #if HAS_HOTEND + DWIN_Draw_Label(4, F("Max Feedrate E")); + #endif + #else + say_max_en(1); say_speed_en(30, 1); say_x_en(73, 1); // "Max Speed X" + say_max_en(2); say_speed_en(30, 2); say_y_en(73, 2); // "Max Speed Y" + say_max_en(3); say_speed_en(30, 3); say_z_en(73, 3); // "Max Speed Z" + #if HAS_HOTEND + say_max_en(4); say_speed_en(30, 4); say_e_en(73, 4); // "Max Speed E" + #endif + #endif + } + + Draw_Back_First(); + LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_MaxSpeedX + i); + Draw_Edit_Integer4(1, planner.settings.max_feedrate_mm_s[X_AXIS]); + Draw_Edit_Integer4(2, planner.settings.max_feedrate_mm_s[Y_AXIS]); + Draw_Edit_Integer4(3, planner.settings.max_feedrate_mm_s[Z_AXIS]); + #if HAS_HOTEND + Draw_Edit_Integer4(4, planner.settings.max_feedrate_mm_s[E_AXIS]); + #endif +} + +void Draw_Max_Accel_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(1, 16, 28, 13); // "Acceleration" + + Item_AreaCopy(173, 133, 200, 147, 1); + Item_AreaCopy( 28, 149, 69, 161, 1, 30, 1); + Item_AreaCopy(229, 133, 236, 147, 1, 74); // Max acceleration X + Item_AreaCopy(173, 133, 200, 147, 2); + Item_AreaCopy( 28, 149, 69, 161, 2, 30, 1); + Item_AreaCopy( 1, 150, 7, 160, 2, 74, 2); // Max acceleration Y + Item_AreaCopy(173, 133, 200, 147, 3); + Item_AreaCopy( 28, 149, 69, 161, 3, 30, 1); + Item_AreaCopy( 9, 150, 16, 160, 3, 74, 2); // Max acceleration Z + #if HAS_HOTEND + Item_AreaCopy(173, 133, 200, 147, 4); + Item_AreaCopy( 28, 149, 69, 161, 4, 30, 1); + Item_AreaCopy( 18, 150, 25, 160, 4, 74, 2); // Max acceleration E + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_ACCELERATION)); + #else + DWIN_Frame_TitleCopy(144, 16, 46, 11); // "Acceleration" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(1, F("Max Accel X")); + DWIN_Draw_Label(2, F("Max Accel Y")); + DWIN_Draw_Label(3, F("Max Accel Z")); + #if HAS_HOTEND + DWIN_Draw_Label(4, F("Max Accel E")); + #endif + #else + say_max_accel_en(1); say_x_en(112, 1); // "Max Acceleration X" + say_max_accel_en(2); say_y_en(112, 2); // "Max Acceleration Y" + say_max_accel_en(3); say_z_en(112, 3); // "Max Acceleration Z" + #if HAS_HOTEND + say_max_accel_en(4); say_e_en(112, 4); // "Max Acceleration E" + #endif + #endif + } + + Draw_Back_First(); + LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_MaxAccX + i); + Draw_Edit_Integer4(1, planner.settings.max_acceleration_mm_per_s2[X_AXIS]); + Draw_Edit_Integer4(2, planner.settings.max_acceleration_mm_per_s2[Y_AXIS]); + Draw_Edit_Integer4(3, planner.settings.max_acceleration_mm_per_s2[Z_AXIS]); + #if HAS_HOTEND + Draw_Edit_Integer4(4, planner.settings.max_acceleration_mm_per_s2[E_AXIS]); + #endif +} + +#if HAS_CLASSIC_JERK + void Draw_Max_Jerk_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(1, 16, 28, 13); // "Jerk" + + Item_AreaCopy(173, 133, 200, 147, 1); + Item_AreaCopy( 1, 180, 28, 192, 1, 30, 1); + Item_AreaCopy(202, 133, 228, 147, 1, 56); + Item_AreaCopy(229, 133, 236, 147, 1, 86); // Max Jerk speed X + Item_AreaCopy(173, 133, 200, 147, 2); + Item_AreaCopy( 1, 180, 28, 192, 2, 30, 1); + Item_AreaCopy(202, 133, 228, 147, 2, 56); + Item_AreaCopy( 1, 150, 7, 160, 2, 86, 3); // Max Jerk speed Y + Item_AreaCopy(173, 133, 200, 147, 3); + Item_AreaCopy( 1, 180, 28, 192, 3, 30, 1); + Item_AreaCopy(202, 133, 228, 147, 3, 56); + Item_AreaCopy( 9, 150, 16, 160, 3, 86, 3); // Max Jerk speed Z + #if HAS_HOTEND + Item_AreaCopy(173, 133, 200, 147, 4); + Item_AreaCopy( 1, 180, 28, 192, 4, 30, 1); + Item_AreaCopy(202, 133, 228, 147, 4, 56); + Item_AreaCopy( 18, 150, 25, 160, 4, 86, 3); // Max Jerk speed E + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_JERK)); + #else + DWIN_Frame_TitleCopy(144, 16, 46, 11); // "Jerk" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(1, GET_TEXT_F(MSG_VA_JERK)); + DWIN_Draw_Label(2, GET_TEXT_F(MSG_VB_JERK)); + DWIN_Draw_Label(3, GET_TEXT_F(MSG_VC_JERK)); + #if HAS_HOTEND + DWIN_Draw_Label(4, GET_TEXT_F(MSG_VE_JERK)); + #endif + #else + say_max_jerk_speed_en(1); say_x_en(102, 1); // Max Jerk speed X + say_max_jerk_speed_en(2); say_y_en(102, 2); // Max Jerk speed Y + say_max_jerk_speed_en(3); say_z_en(102, 3); // Max Jerk speed Z + #if HAS_HOTEND + say_max_jerk_speed_en(4); say_e_en(102, 4); // Max Jerk speed E + #endif + #endif + } + + Draw_Back_First(); + LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_MaxSpeedJerkX + i); + Draw_Edit_Float3(1, planner.max_jerk[X_AXIS] * MINUNITMULT); + Draw_Edit_Float3(2, planner.max_jerk[Y_AXIS] * MINUNITMULT); + Draw_Edit_Float3(3, planner.max_jerk[Z_AXIS] * MINUNITMULT); + #if HAS_HOTEND + Draw_Edit_Float3(4, planner.max_jerk[E_AXIS] * MINUNITMULT); + #endif + } +#endif + +void Draw_Steps_Menu() { + Clear_Main_Window(); + + if (HMI_IsChinese()) { + DWIN_Frame_TitleCopy(1, 16, 28, 13); // "Steps per mm" + + Item_AreaCopy(153, 148, 194, 161, 1); + Item_AreaCopy(229, 133, 236, 147, 1, 44); // Transmission Ratio X + Item_AreaCopy(153, 148, 194, 161, 2); + Item_AreaCopy( 1, 150, 7, 160, 2, 44, 3); // Transmission Ratio Y + Item_AreaCopy(153, 148, 194, 161, 3); + Item_AreaCopy( 9, 150, 16, 160, 3, 44, 3); // Transmission Ratio Z + #if HAS_HOTEND + Item_AreaCopy(153, 148, 194, 161, 4); + Item_AreaCopy( 18, 150, 25, 160, 4, 44, 3); // Transmission Ratio E + #endif + } + else { + #ifdef USE_STRING_HEADINGS + Draw_Title(GET_TEXT_F(MSG_STEPS_PER_MM)); + #else + DWIN_Frame_TitleCopy(144, 16, 46, 11); // "Steps per mm" + #endif + #ifdef USE_STRING_TITLES + DWIN_Draw_Label(1, GET_TEXT_F(MSG_A_STEPS)); + DWIN_Draw_Label(2, GET_TEXT_F(MSG_B_STEPS)); + DWIN_Draw_Label(3, GET_TEXT_F(MSG_C_STEPS)); + #if HAS_HOTEND + DWIN_Draw_Label(4, GET_TEXT_F(MSG_E_STEPS)); + #endif + #else + say_steps_per_mm_en(1); say_x_en(101, 1); // "Steps-per-mm X" + say_steps_per_mm_en(2); say_y_en(101, 2); // "Y" + say_steps_per_mm_en(3); say_z_en(101, 3); // "Z" + #if HAS_HOTEND + say_steps_per_mm_en(4); say_e_en(101, 4); // "E" + #endif + #endif + } + + Draw_Back_First(); + LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_StepX + i); + Draw_Edit_Float3(1, planner.settings.axis_steps_per_mm[X_AXIS] * MINUNITMULT); + Draw_Edit_Float3(2, planner.settings.axis_steps_per_mm[Y_AXIS] * MINUNITMULT); + Draw_Edit_Float3(3, planner.settings.axis_steps_per_mm[Z_AXIS] * MINUNITMULT); + #if HAS_HOTEND + Draw_Edit_Float3(4, planner.settings.axis_steps_per_mm[E_AXIS] * MINUNITMULT); + #endif +} + +// Motion +void HMI_Motion() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_motion.inc(1 + MOTION_CASE_TOTAL)) Move_Highlight(1, select_motion.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_motion.dec()) Move_Highlight(-1, select_motion.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_motion.now) { + case CASE_BACK: + checkkey = Control; + select_control.set(CONTROL_CASE_MOVE); + index_control = MROWS; + Draw_Control_Menu(); + break; + case MOTION_CASE_RATE: + checkkey = MaxSpeed; + select_speed.reset(); + Draw_Max_Speed_Menu(); + break; + case MOTION_CASE_ACCEL: + checkkey = MaxAcceleration; + select_acc.reset(); + Draw_Max_Accel_Menu(); + break; + #if HAS_CLASSIC_JERK + case MOTION_CASE_JERK: + checkkey = MaxJerk; + select_jerk.reset(); + Draw_Max_Jerk_Menu(); + break; + #endif + case MOTION_CASE_STEPS: + checkkey = Step; + select_step.reset(); + Draw_Steps_Menu(); + break; + default: break; + } + } + DWIN_UpdateLCD(); +} + +// Advanced Settings +void HMI_AdvSet() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_advset.inc(1 + ADVSET_CASE_TOTAL)) { + if (select_advset.now > MROWS && select_advset.now > index_advset) { + index_advset = select_advset.now; + + // Scroll up and draw a blank bottom line + Scroll_Menu(DWIN_SCROLL_UP); + + //switch (index_advset) { // Redraw last menu items + // default: break; + //} + + } + else { + Move_Highlight(1, select_advset.now + MROWS - index_advset); + } + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_advset.dec()) { + if (select_advset.now < index_advset - MROWS) { + index_advset--; + Scroll_Menu(DWIN_SCROLL_DOWN); + + //switch (index_advset) { // Redraw first menu items + // default: break; + //} + } + else { + Move_Highlight(-1, select_advset.now + MROWS - index_advset); + } + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_advset.now) { + case CASE_BACK: + checkkey = Control; + select_control.set(CONTROL_CASE_ADVSET); + index_control = CONTROL_CASE_ADVSET; + Draw_Control_Menu(); + break; + + #if HAS_HOME_OFFSET + case ADVSET_CASE_HOMEOFF: + checkkey = HomeOff; + select_item.reset(); + HMI_ValueStruct.Home_OffX_scaled = home_offset.x * 10; + HMI_ValueStruct.Home_OffY_scaled = home_offset.y * 10; + HMI_ValueStruct.Home_OffZ_scaled = home_offset.z * 10; + Draw_HomeOff_Menu(); + break; + #endif + + #if HAS_ONESTEP_LEVELING + case ADVSET_CASE_PROBEOFF: + checkkey = ProbeOff; + select_item.reset(); + HMI_ValueStruct.Probe_OffX_scaled = probe.offset.x * 10; + HMI_ValueStruct.Probe_OffY_scaled = probe.offset.y * 10; + Draw_ProbeOff_Menu(); + break; + #endif + + #if HAS_HOTEND + case ADVSET_CASE_HEPID: + thermalManager.PID_autotune(ui.material_preset[0].hotend_temp, H_E0, 10, true); + break; + #endif + + #if HAS_HEATED_BED + case ADVSET_CASE_BEDPID: + thermalManager.PID_autotune(ui.material_preset[0].bed_temp, H_BED, 10, true); + break; + #endif + + #if ENABLED(POWER_LOSS_RECOVERY) + case ADVSET_CASE_PWRLOSSR: + recovery.enable(!recovery.enabled); + Draw_Checkbox_Line(ADVSET_CASE_PWRLOSSR + MROWS - index_advset, recovery.enabled); + break; + #endif + default: break; + } + } + DWIN_UpdateLCD(); +} + +#if HAS_HOME_OFFSET + + // Home Offset + void HMI_HomeOff() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_item.inc(1 + 3)) Move_Highlight(1, select_item.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_item.dec()) Move_Highlight(-1, select_item.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_item.now) { + case CASE_BACK: + checkkey = AdvSet; + select_advset.set(ADVSET_CASE_HOMEOFF); + Draw_AdvancedSettings_Menu(); + break; + case 1: // Home Offset X + checkkey = HomeOffX; + Draw_Edit_Signed_Float3(1, HMI_ValueStruct.Home_OffX_scaled, true); + EncoderRate.enabled = true; + break; + case 2: // Home Offset Y + checkkey = HomeOffY; + Draw_Edit_Signed_Float3(2, HMI_ValueStruct.Home_OffY_scaled, true); + EncoderRate.enabled = true; + break; + case 3: // Home Offset Z + checkkey = HomeOffZ; + Draw_Edit_Signed_Float3(3, HMI_ValueStruct.Home_OffZ_scaled, true); + EncoderRate.enabled = true; + break; + default: break; + } + } + DWIN_UpdateLCD(); + } + + void HMI_HomeOffN(const AxisEnum axis, float &posScaled, const_float_t lo, const_float_t hi) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + if (Apply_Encoder(encoder_diffState, posScaled)) { + checkkey = HomeOff; + EncoderRate.enabled = false; + set_home_offset(axis, posScaled / 10); + Draw_Edit_Signed_Float3(select_item.now, posScaled); + return; + } + LIMIT(posScaled, lo, hi); + Draw_Edit_Signed_Float3(select_item.now, posScaled, true); + } + + void HMI_HomeOffX() { HMI_HomeOffN(X_AXIS, HMI_ValueStruct.Home_OffX_scaled, -500, 500); } + void HMI_HomeOffY() { HMI_HomeOffN(Y_AXIS, HMI_ValueStruct.Home_OffY_scaled, -500, 500); } + void HMI_HomeOffZ() { HMI_HomeOffN(Z_AXIS, HMI_ValueStruct.Home_OffZ_scaled, -20, 20); } + +#endif // HAS_HOME_OFFSET + +#if HAS_ONESTEP_LEVELING + + // Probe Offset + void HMI_ProbeOff() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_item.inc(1 + 2)) Move_Highlight(1, select_item.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_item.dec()) Move_Highlight(-1, select_item.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_item.now) { + case CASE_BACK: + checkkey = AdvSet; + select_advset.set(ADVSET_CASE_PROBEOFF); + Draw_AdvancedSettings_Menu(); + break; + case 1: // Probe Offset X + checkkey = ProbeOffX; + Draw_Edit_Signed_Float3(1, HMI_ValueStruct.Probe_OffX_scaled, true); + EncoderRate.enabled = true; + break; + case 2: // Probe Offset Y + checkkey = ProbeOffY; + Draw_Edit_Signed_Float3(2, HMI_ValueStruct.Probe_OffY_scaled, true); + EncoderRate.enabled = true; + break; + } + } + DWIN_UpdateLCD(); + } + + void HMI_ProbeOffN(float &posScaled, float &offset_ref) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + if (Apply_Encoder(encoder_diffState, posScaled)) { + checkkey = ProbeOff; + EncoderRate.enabled = false; + offset_ref = posScaled / 10; + Draw_Edit_Signed_Float3(select_item.now, posScaled); + return; + } + LIMIT(posScaled, -500, 500); + Draw_Edit_Signed_Float3(select_item.now, posScaled, true); + } + + void HMI_ProbeOffX() { HMI_ProbeOffN(HMI_ValueStruct.Probe_OffX_scaled, probe.offset.x); } + void HMI_ProbeOffY() { HMI_ProbeOffN(HMI_ValueStruct.Probe_OffY_scaled, probe.offset.y); } + +#endif // HAS_ONESTEP_LEVELING + +// Info +void HMI_Info() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_ENTER) { + #if HAS_ONESTEP_LEVELING + checkkey = Control; + select_control.set(CONTROL_CASE_INFO); + Draw_Control_Menu(); + #else + select_page.set(3); + Goto_MainMenu(); + #endif + } + DWIN_UpdateLCD(); +} + +// Tune +void HMI_Tune() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_tune.inc(1 + TUNE_CASE_TOTAL)) { + if (select_tune.now > MROWS && select_tune.now > index_tune) { + index_tune = select_tune.now; + Scroll_Menu(DWIN_SCROLL_UP); + } + else + Move_Highlight(1, select_tune.now + MROWS - index_tune); + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_tune.dec()) { + if (select_tune.now < index_tune - MROWS) { + index_tune--; + Scroll_Menu(DWIN_SCROLL_DOWN); + if (index_tune == MROWS) Draw_Back_First(); + } + else + Move_Highlight(-1, select_tune.now + MROWS - index_tune); + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_tune.now) { + case 0: { // Back + select_print.set(0); + Goto_PrintProcess(); + } + break; + case TUNE_CASE_SPEED: // Print speed + checkkey = PrintSpeed; + HMI_ValueStruct.print_speed = feedrate_percentage; + Draw_Edit_Integer3(TUNE_CASE_SPEED + MROWS - index_tune, HMI_ValueStruct.print_speed, true); + EncoderRate.enabled = true; + break; + #if HAS_HOTEND + case TUNE_CASE_TEMP: // Nozzle temp + checkkey = ETemp; + HMI_ValueStruct.E_Temp = thermalManager.degTargetHotend(0); + Draw_Edit_Integer3(TUNE_CASE_TEMP + MROWS - index_tune, HMI_ValueStruct.E_Temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_HEATED_BED + case TUNE_CASE_BED: // Bed temp + checkkey = BedTemp; + HMI_ValueStruct.Bed_Temp = thermalManager.degTargetBed(); + Draw_Edit_Integer3(TUNE_CASE_BED + MROWS - index_tune, HMI_ValueStruct.Bed_Temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_FAN + case TUNE_CASE_FAN: // Fan speed + checkkey = FanSpeed; + HMI_ValueStruct.Fan_speed = thermalManager.fan_speed[0]; + Draw_Edit_Integer3(TUNE_CASE_FAN + MROWS - index_tune, HMI_ValueStruct.Fan_speed, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_ZOFFSET_ITEM + case TUNE_CASE_ZOFF: // Z-offset + #if EITHER(HAS_BED_PROBE, BABYSTEPPING) + checkkey = Homeoffset; + HMI_ValueStruct.offset_value = BABY_Z_VAR * 100; + Draw_Edit_Signed_Float2(TUNE_CASE_ZOFF + MROWS - index_tune, HMI_ValueStruct.offset_value, true); + EncoderRate.enabled = true; + #else + // Apply workspace offset, making the current position 0,0,0 + queue.inject(F("G92X0Y0Z0")); + HMI_AudioFeedback(); + #endif + break; + #endif + default: break; + } + } + DWIN_UpdateLCD(); +} + +#if HAS_PREHEAT + + // PLA Preheat + void HMI_PLAPreheatSetting() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_PLA.inc(1 + PREHEAT_CASE_TOTAL)) Move_Highlight(1, select_PLA.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_PLA.dec()) Move_Highlight(-1, select_PLA.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_PLA.now) { + case CASE_BACK: + checkkey = TemperatureID; + select_temp.now = TEMP_CASE_PLA; + HMI_ValueStruct.show_mode = -1; + Draw_Temperature_Menu(); + break; + #if HAS_HOTEND + case PREHEAT_CASE_TEMP: + checkkey = ETemp; + HMI_ValueStruct.E_Temp = ui.material_preset[0].hotend_temp; + Draw_Edit_Integer3(PREHEAT_CASE_TEMP, ui.material_preset[0].hotend_temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_HEATED_BED + case PREHEAT_CASE_BED: + checkkey = BedTemp; + HMI_ValueStruct.Bed_Temp = ui.material_preset[0].bed_temp; + Draw_Edit_Integer3(PREHEAT_CASE_BED, ui.material_preset[0].bed_temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_FAN + case PREHEAT_CASE_FAN: + checkkey = FanSpeed; + HMI_ValueStruct.Fan_speed = ui.material_preset[0].fan_speed; + Draw_Edit_Integer3(PREHEAT_CASE_FAN, ui.material_preset[0].fan_speed, true); + EncoderRate.enabled = true; + break; + #endif + #if ENABLED(EEPROM_SETTINGS) + case PREHEAT_CASE_SAVE: { + const bool success = settings.save(); + HMI_AudioFeedback(success); + } break; + #endif + default: break; + } + } + DWIN_UpdateLCD(); + } + + #if PREHEAT_COUNT > 1 + // ABS Preheat + void HMI_ABSPreheatSetting() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_ABS.inc(1 + PREHEAT_CASE_TOTAL)) Move_Highlight(1, select_ABS.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_ABS.dec()) Move_Highlight(-1, select_ABS.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_ABS.now) { + case CASE_BACK: + checkkey = TemperatureID; + select_temp.now = TEMP_CASE_ABS; + HMI_ValueStruct.show_mode = -1; + Draw_Temperature_Menu(); + break; + #if HAS_HOTEND + case PREHEAT_CASE_TEMP: + checkkey = ETemp; + HMI_ValueStruct.E_Temp = ui.material_preset[1].hotend_temp; + Draw_Edit_Integer3(PREHEAT_CASE_TEMP, ui.material_preset[1].hotend_temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_HEATED_BED + case PREHEAT_CASE_BED: + checkkey = BedTemp; + HMI_ValueStruct.Bed_Temp = ui.material_preset[1].bed_temp; + Draw_Edit_Integer3(PREHEAT_CASE_BED, ui.material_preset[1].bed_temp, true); + EncoderRate.enabled = true; + break; + #endif + #if HAS_FAN + case PREHEAT_CASE_FAN: + checkkey = FanSpeed; + HMI_ValueStruct.Fan_speed = ui.material_preset[1].fan_speed; + Draw_Edit_Integer3(PREHEAT_CASE_FAN, ui.material_preset[1].fan_speed, true); + EncoderRate.enabled = true; + break; + #endif + #if ENABLED(EEPROM_SETTINGS) + case PREHEAT_CASE_SAVE: { + const bool success = settings.save(); + HMI_AudioFeedback(success); + } break; + #endif + default: break; + } + } + DWIN_UpdateLCD(); + } + #endif // PREHEAT_COUNT > 1 + +#endif // HAS_PREHEAT + +// Max Speed +void HMI_MaxSpeed() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_speed.inc(1 + 3 + ENABLED(HAS_HOTEND))) Move_Highlight(1, select_speed.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_speed.dec()) Move_Highlight(-1, select_speed.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (WITHIN(select_speed.now, 1, 4)) { + checkkey = MaxSpeed_value; + HMI_flag.feedspeed_axis = AxisEnum(select_speed.now - 1); + HMI_ValueStruct.Max_Feedspeed = planner.settings.max_feedrate_mm_s[HMI_flag.feedspeed_axis]; + Draw_Edit_Integer4(select_speed.now, HMI_ValueStruct.Max_Feedspeed, true); + EncoderRate.enabled = true; + } + else { // Back + checkkey = Motion; + select_motion.now = MOTION_CASE_RATE; + Draw_Motion_Menu(); + } + } + DWIN_UpdateLCD(); +} + +// Max Acceleration +void HMI_MaxAcceleration() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_acc.inc(1 + 3 + ENABLED(HAS_HOTEND))) Move_Highlight(1, select_acc.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_acc.dec()) Move_Highlight(-1, select_acc.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (WITHIN(select_acc.now, 1, 4)) { + checkkey = MaxAcceleration_value; + HMI_flag.acc_axis = AxisEnum(select_acc.now - 1); + HMI_ValueStruct.Max_Acceleration = planner.settings.max_acceleration_mm_per_s2[HMI_flag.acc_axis]; + Draw_Edit_Integer4(select_acc.now, HMI_ValueStruct.Max_Acceleration, true); + EncoderRate.enabled = true; + } + else { // Back + checkkey = Motion; + select_motion.now = MOTION_CASE_ACCEL; + Draw_Motion_Menu(); + } + } + DWIN_UpdateLCD(); +} + +#if HAS_CLASSIC_JERK + // Max Jerk + void HMI_MaxJerk() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_jerk.inc(1 + 3 + ENABLED(HAS_HOTEND))) Move_Highlight(1, select_jerk.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_jerk.dec()) Move_Highlight(-1, select_jerk.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (WITHIN(select_jerk.now, 1, 4)) { + checkkey = MaxJerk_value; + HMI_flag.jerk_axis = AxisEnum(select_jerk.now - 1); + HMI_ValueStruct.Max_Jerk_scaled = planner.max_jerk[HMI_flag.jerk_axis] * MINUNITMULT; + Draw_Edit_Float3(select_jerk.now, HMI_ValueStruct.Max_Jerk_scaled, true); + EncoderRate.enabled = true; + } + else { // Back + checkkey = Motion; + select_motion.now = MOTION_CASE_JERK; + Draw_Motion_Menu(); + } + } + DWIN_UpdateLCD(); + } +#endif // HAS_CLASSIC_JERK + +// Step +void HMI_Step() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_step.inc(1 + 3 + ENABLED(HAS_HOTEND))) Move_Highlight(1, select_step.now); + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_step.dec()) Move_Highlight(-1, select_step.now); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (WITHIN(select_step.now, 1, 4)) { + checkkey = Step_value; + HMI_flag.step_axis = AxisEnum(select_step.now - 1); + HMI_ValueStruct.Max_Step_scaled = planner.settings.axis_steps_per_mm[HMI_flag.step_axis] * MINUNITMULT; + Draw_Edit_Float3(select_step.now, HMI_ValueStruct.Max_Step_scaled, true); + EncoderRate.enabled = true; + } + else { // Back + checkkey = Motion; + select_motion.now = MOTION_CASE_STEPS; + Draw_Motion_Menu(); + } + } + DWIN_UpdateLCD(); +} + +void HMI_Init() { + HMI_SDCardInit(); + + for (uint16_t t = 0; t <= 100; t += 2) { + DWIN_ICON_Show(ICON, ICON_Bar, 15, 260); + DWIN_Draw_Rectangle(1, Color_Bg_Black, 15 + t * 242 / 100, 260, 257, 280); + DWIN_UpdateLCD(); + delay(20); + } + + HMI_SetLanguage(); +} + +void DWIN_InitScreen() { + Encoder_Configuration(); + HMI_Init(); + HMI_SetLanguageCache(); + HMI_StartFrame(true); +} + +void DWIN_Update() { + EachMomentUpdate(); // Status update + HMI_SDCardUpdate(); // SD card update + DWIN_HandleScreen(); // Rotary encoder update +} + +void EachMomentUpdate() { + static millis_t next_var_update_ms = 0, next_rts_update_ms = 0; + + const millis_t ms = millis(); + if (ELAPSED(ms, next_var_update_ms)) { + next_var_update_ms = ms + DWIN_VAR_UPDATE_INTERVAL; + update_variable(); + } + + if (PENDING(ms, next_rts_update_ms)) return; + next_rts_update_ms = ms + DWIN_SCROLL_UPDATE_INTERVAL; + + if (checkkey == PrintProcess) { + // if print done + if (HMI_flag.print_finish && !HMI_flag.done_confirm_flag) { + HMI_flag.print_finish = false; + HMI_flag.done_confirm_flag = true; + + TERN_(POWER_LOSS_RECOVERY, recovery.cancel()); + + planner.finish_and_disable(); + + // show percent bar and value + _card_percent = 0; + Draw_Print_ProgressBar(); + + // show print done confirm + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, 250, DWIN_WIDTH - 1, STATUS_Y); + DWIN_ICON_Show(ICON, HMI_IsChinese() ? ICON_Confirm_C : ICON_Confirm_E, 86, 283); + } + else if (HMI_flag.pause_flag != printingIsPaused()) { + // print status update + HMI_flag.pause_flag = printingIsPaused(); + ICON_ResumeOrPause(); + } + } + + // pause after homing + if (HMI_flag.pause_action && printingIsPaused() && !planner.has_blocks_queued()) { + HMI_flag.pause_action = false; + #if ENABLED(PAUSE_HEAT) + TERN_(HAS_HOTEND, resume_hotend_temp = thermalManager.degTargetHotend(0)); + TERN_(HAS_HEATED_BED, resume_bed_temp = thermalManager.degTargetBed()); + thermalManager.disable_all_heaters(); + #endif + queue.inject(F("G1 F1200 X0 Y0")); + } + + if (card.isPrinting() && checkkey == PrintProcess) { // print process + const uint8_t card_pct = card.percentDone(); + static uint8_t last_cardpercentValue = 101; + if (last_cardpercentValue != card_pct) { // print percent + last_cardpercentValue = card_pct; + if (card_pct) { + _card_percent = card_pct; + Draw_Print_ProgressBar(); + } + } + + duration_t elapsed = print_job_timer.duration(); // print timer + + // Print time so far + static uint16_t last_Printtime = 0; + const uint16_t min = (elapsed.value % 3600) / 60; + if (last_Printtime != min) { // 1 minute update + last_Printtime = min; + Draw_Print_ProgressElapsed(); + } + + // Estimate remaining time every 20 seconds + static millis_t next_remain_time_update = 0; + if (_card_percent > 1 && ELAPSED(ms, next_remain_time_update) && !HMI_flag.heat_flag) { + _remain_time = (elapsed.value - dwin_heat_time) / (_card_percent * 0.01f) - (elapsed.value - dwin_heat_time); + next_remain_time_update += DWIN_REMAIN_TIME_UPDATE_INTERVAL; + Draw_Print_ProgressRemain(); + } + } + else if (dwin_abort_flag && !HMI_flag.home_flag) { // Print Stop + dwin_abort_flag = false; + HMI_ValueStruct.print_speed = feedrate_percentage = 100; + dwin_zoffset = BABY_Z_VAR; + select_page.set(0); + Goto_MainMenu(); + } + #if ENABLED(POWER_LOSS_RECOVERY) + else if (DWIN_lcd_sd_status && recovery.dwin_flag) { // resume print before power off + recovery.dwin_flag = false; + + auto update_selection = [&](const bool sel) { + HMI_flag.select_flag = sel; + const uint16_t c1 = sel ? Color_Bg_Window : Select_Color; + DWIN_Draw_Rectangle(0, c1, 25, 306, 126, 345); + DWIN_Draw_Rectangle(0, c1, 24, 305, 127, 346); + const uint16_t c2 = sel ? Select_Color : Color_Bg_Window; + DWIN_Draw_Rectangle(0, c2, 145, 306, 246, 345); + DWIN_Draw_Rectangle(0, c2, 144, 305, 247, 346); + }; + + Popup_Window_Resume(); + update_selection(true); + + char * const name = card.longest_filename(); + const int8_t npos = _MAX(0U, DWIN_WIDTH - strlen(name) * (MENU_CHR_W)) / 2; + DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, npos, 252, name); + DWIN_UpdateLCD(); + + bool recovery_flag = true; + while (recovery_flag) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (encoder_diffState == ENCODER_DIFF_ENTER) { + recovery_flag = false; + if (HMI_flag.select_flag) break; + TERN_(POWER_LOSS_RECOVERY, queue.inject(F("M1000C"))); + HMI_StartFrame(true); + return; + } + else + update_selection(encoder_diffState == ENCODER_DIFF_CW); + + DWIN_UpdateLCD(); + } + } + + select_print.set(0); + HMI_ValueStruct.show_mode = 0; + queue.inject(F("M1000")); + Goto_PrintProcess(); + Draw_Status_Area(true); + } + #endif // POWER_LOSS_RECOVERY + + DWIN_UpdateLCD(); +} + +void DWIN_HandleScreen() { + switch (checkkey) { + case MainMenu: HMI_MainMenu(); break; + case SelectFile: HMI_SelectFile(); break; + case Prepare: HMI_Prepare(); break; + case Control: HMI_Control(); break; + case Leveling: break; + case PrintProcess: HMI_Printing(); break; + case Print_window: HMI_PauseOrStop(); break; + case AxisMove: HMI_AxisMove(); break; + case TemperatureID: HMI_Temperature(); break; + case Motion: HMI_Motion(); break; + case AdvSet: HMI_AdvSet(); break; + #if HAS_HOME_OFFSET + case HomeOff: HMI_HomeOff(); break; + case HomeOffX: HMI_HomeOffX(); break; + case HomeOffY: HMI_HomeOffY(); break; + case HomeOffZ: HMI_HomeOffZ(); break; + #endif + #if HAS_ONESTEP_LEVELING + case ProbeOff: HMI_ProbeOff(); break; + case ProbeOffX: HMI_ProbeOffX(); break; + case ProbeOffY: HMI_ProbeOffY(); break; + #endif + case Info: HMI_Info(); break; + case Tune: HMI_Tune(); break; + #if HAS_PREHEAT + case PLAPreheat: HMI_PLAPreheatSetting(); break; + #if PREHEAT_COUNT > 1 + case ABSPreheat: HMI_ABSPreheatSetting(); break; + #endif + #endif + case MaxSpeed: HMI_MaxSpeed(); break; + case MaxAcceleration: HMI_MaxAcceleration(); break; + #if HAS_CLASSIC_JERK + case MaxJerk: HMI_MaxJerk(); break; + #endif + case Step: HMI_Step(); break; + case Move_X: HMI_Move_X(); break; + case Move_Y: HMI_Move_Y(); break; + case Move_Z: HMI_Move_Z(); break; + #if HAS_HOTEND + case Extruder: HMI_Move_E(); break; + case ETemp: HMI_ETemp(); break; + #endif + #if EITHER(HAS_BED_PROBE, BABYSTEPPING) + case Homeoffset: HMI_Zoffset(); break; + #endif + #if HAS_HEATED_BED + case BedTemp: HMI_BedTemp(); break; + #endif + #if HAS_PREHEAT && HAS_FAN + case FanSpeed: HMI_FanSpeed(); break; + #endif + case PrintSpeed: HMI_PrintSpeed(); break; + case MaxSpeed_value: HMI_MaxFeedspeedXYZE(); break; + case MaxAcceleration_value: HMI_MaxAccelerationXYZE(); break; + #if HAS_CLASSIC_JERK + case MaxJerk_value: HMI_MaxJerkXYZE(); break; + #endif + case Step_value: HMI_StepXYZE(); break; + default: break; + } +} + +void DWIN_HomingDone() { + HMI_flag.home_flag = false; + dwin_zoffset = TERN0(HAS_BED_PROBE, probe.offset.z); + if (checkkey == Last_Prepare) { + checkkey = Prepare; + select_prepare.now = PREPARE_CASE_HOME; + index_prepare = MROWS; + Draw_Prepare_Menu(); + } + else if (checkkey == Back_Main) { + HMI_ValueStruct.print_speed = feedrate_percentage = 100; + planner.finish_and_disable(); + Goto_MainMenu(); + } +} + +void DWIN_LevelingDone() { + if (checkkey == Leveling) Goto_MainMenu(); +} + +void DWIN_StatusChanged(const char * const cstr/*=nullptr*/) { + DWIN_Draw_Rectangle(1, Color_Bg_Blue, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 24); + const int8_t x = _MAX(0U, DWIN_WIDTH - strlen(cstr) * MENU_CHR_W) / 2; + DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Blue, x, STATUS_Y + 3, cstr); + DWIN_UpdateLCD(); +} + +void DWIN_StatusChanged(FSTR_P const fstr) { + #ifdef __AVR__ + char str[strlen_P(FTOP(fstr)) + 1]; + strcpy_P(str, FTOP(fstr)); + DWIN_StatusChanged(str); + #else + DWIN_StatusChanged(FTOP(fstr)); + #endif +} + +#endif // DWIN_CREALITY_LCD diff --git a/src/lcd/e3v2/creality/dwin.h b/src/lcd/e3v2/creality/dwin.h new file mode 100644 index 0000000..487f309 --- /dev/null +++ b/src/lcd/e3v2/creality/dwin.h @@ -0,0 +1,249 @@ +/** + * 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 + +/** + * DWIN by Creality3D + */ + +#include "dwin_lcd.h" +#include "../common/encoder.h" +#include "../../../libs/BL24CXX.h" + +#include "../../../inc/MarlinConfigPre.h" + +enum processID : uint8_t { + // Process ID + MainMenu, + SelectFile, + Prepare, + Control, + Leveling, + PrintProcess, + AxisMove, + TemperatureID, + Motion, + Info, + Tune, + #if HAS_PREHEAT + PLAPreheat, + #if PREHEAT_COUNT > 1 + ABSPreheat, + #endif + #endif + MaxSpeed, + MaxSpeed_value, + MaxAcceleration, + MaxAcceleration_value, + MaxJerk, + MaxJerk_value, + Step, + Step_value, + HomeOff, + HomeOffX, + HomeOffY, + HomeOffZ, + + // Last Process ID + Last_Prepare, + + // Advance Settings + AdvSet, + ProbeOff, + ProbeOffX, + ProbeOffY, + + // Back Process ID + Back_Main, + Back_Print, + + // Date variable ID + Move_X, + Move_Y, + Move_Z, + #if HAS_HOTEND + Extruder, + ETemp, + #endif + Homeoffset, + #if HAS_HEATED_BED + BedTemp, + #endif + #if HAS_FAN + FanSpeed, + #endif + PrintSpeed, + + // Window ID + Print_window, + Popup_Window +}; + +extern uint8_t checkkey; +extern float zprobe_zoffset; +extern char print_filename[16]; + +extern millis_t dwin_heat_time; + +typedef struct { + #if HAS_HOTEND + celsius_t E_Temp = 0; + #endif + #if HAS_HEATED_BED + celsius_t Bed_Temp = 0; + #endif + #if HAS_FAN + int16_t Fan_speed = 0; + #endif + int16_t print_speed = 100; + float Max_Feedspeed = 0; + float Max_Acceleration = 0; + float Max_Jerk_scaled = 0; + float Max_Step_scaled = 0; + float Move_X_scaled = 0; + float Move_Y_scaled = 0; + float Move_Z_scaled = 0; + #if HAS_HOTEND + float Move_E_scaled = 0; + #endif + float offset_value = 0; + int8_t show_mode = 0; // -1: Temperature control 0: Printing temperature + float Home_OffX_scaled = 0; + float Home_OffY_scaled = 0; + float Home_OffZ_scaled = 0; + float Probe_OffX_scaled = 0; + float Probe_OffY_scaled = 0; +} HMI_value_t; + +#define DWIN_CHINESE 123 +#define DWIN_ENGLISH 0 + +typedef struct { + uint8_t language; + bool pause_flag:1; // printing is paused + bool pause_action:1; // flag a pause action + bool print_finish:1; // print was finished + bool select_flag:1; // Popup button selected + bool home_flag:1; // homing in course + bool heat_flag:1; // 0: heating done 1: during heating + bool done_confirm_flag:1; + #if ENABLED(PREVENT_COLD_EXTRUSION) + bool cold_flag:1; + #endif + AxisEnum feedspeed_axis, acc_axis, jerk_axis, step_axis; +} HMI_flag_t; + +extern HMI_value_t HMI_ValueStruct; +extern HMI_flag_t HMI_flag; + +#if HAS_HOTEND || HAS_HEATED_BED + // Popup message window + void DWIN_Popup_Temperature(const bool toohigh); +#endif + +#if HAS_HOTEND + void Popup_Window_ETempTooLow(); +#endif + +void Popup_Window_Resume(); +void Popup_Window_Home(const bool parking=false); +void Popup_Window_Leveling(); + +void Goto_PrintProcess(); +void Goto_MainMenu(); + +// Variable control +void HMI_Move_X(); +void HMI_Move_Y(); +void HMI_Move_Z(); +void HMI_Move_E(); + +void HMI_Zoffset(); + +#if HAS_HOTEND + void HMI_ETemp(); +#endif +#if HAS_HEATED_BED + void HMI_BedTemp(); +#endif +#if HAS_FAN + void HMI_FanSpeed(); +#endif + +void HMI_PrintSpeed(); + +void HMI_MaxFeedspeedXYZE(); +void HMI_MaxAccelerationXYZE(); +void HMI_MaxJerkXYZE(); +void HMI_StepXYZE(); +void HMI_SetLanguageCache(); + +void update_variable(); +void DWIN_Draw_Signed_Float(uint8_t size, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, long value); + +// SD Card +void HMI_SDCardInit(); +void HMI_SDCardUpdate(); + +// Main Process +void Icon_print(bool value); +void Icon_control(bool value); +void Icon_temperature(bool value); +void Icon_leveling(bool value); + +// Other +void Draw_Status_Area(const bool with_update); // Status Area +void HMI_StartFrame(const bool with_update); // Prepare the menu view +void HMI_MainMenu(); // Main process screen +void HMI_SelectFile(); // File page +void HMI_Printing(); // Print page +void HMI_Prepare(); // Prepare page +void HMI_Control(); // Control page +void HMI_Leveling(); // Level the page +void HMI_AxisMove(); // Axis movement menu +void HMI_Temperature(); // Temperature menu +void HMI_Motion(); // Sports menu +void HMI_Info(); // Information menu +void HMI_Tune(); // Adjust the menu + +#if HAS_PREHEAT + void HMI_PLAPreheatSetting(); // PLA warm-up setting + void HMI_ABSPreheatSetting(); // ABS warm-up setting +#endif + +void HMI_MaxSpeed(); // Maximum speed submenu +void HMI_MaxAcceleration(); // Maximum acceleration submenu +void HMI_MaxJerk(); // Maximum jerk speed submenu +void HMI_Step(); // Transmission ratio + +void HMI_Init(); +void DWIN_InitScreen(); +void DWIN_Update(); +void EachMomentUpdate(); +void DWIN_HandleScreen(); +void DWIN_StatusChanged(const char * const cstr=nullptr); +void DWIN_StatusChanged(FSTR_P const fstr); + +inline void DWIN_HomingStart() { HMI_flag.home_flag = true; } + +void DWIN_HomingDone(); +void DWIN_LevelingDone(); diff --git a/src/lcd/e3v2/creality/dwin_lcd.cpp b/src/lcd/e3v2/creality/dwin_lcd.cpp new file mode 100644 index 0000000..3d60e32 --- /dev/null +++ b/src/lcd/e3v2/creality/dwin_lcd.cpp @@ -0,0 +1,84 @@ +/** + * 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 . + * + */ + +/******************************************************************************** + * @file lcd/e3v2/creality/dwin_lcd.cpp + * @author LEO / Creality3D + * @date 2019/07/18 + * @version 2.0.1 + * @brief DWIN screen control functions + ********************************************************************************/ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_CREALITY_LCD) + +#include "../../../inc/MarlinConfig.h" + +#include "dwin_lcd.h" + +//#define DEBUG_OUT 1 +#include "../../../core/debug_out.h" + +/*-------------------------------------- System variable function --------------------------------------*/ + +void DWIN_Startup() { + DEBUG_ECHOPGM("\r\nDWIN handshake "); + delay(750); // Delay here or init later in the boot process + if (DWIN_Handshake()) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error."); + DWIN_Frame_SetDir(1); + #if DISABLED(SHOW_BOOTSCREEN) + DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here + #endif + DWIN_JPG_ShowAndCache(3); + DWIN_UpdateLCD(); +} + +/*---------------------------------------- Picture related functions ----------------------------------------*/ + +// Draw an Icon +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + DWIN_ICON_Show(true, false, false, libID, picID, x, y); +} + +// Copy area from virtual display area to current screen +// cacheID: virtual area number +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + size_t i = 0; + DWIN_Byte(i, 0x27); + DWIN_Byte(i, 0x80 | cacheID); + DWIN_Word(i, xStart); + DWIN_Word(i, yStart); + DWIN_Word(i, xEnd); + DWIN_Word(i, yEnd); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Send(i); +} + +#endif // DWIN_CREALITY_LCD diff --git a/src/lcd/e3v2/creality/dwin_lcd.h b/src/lcd/e3v2/creality/dwin_lcd.h new file mode 100644 index 0000000..b37a659 --- /dev/null +++ b/src/lcd/e3v2/creality/dwin_lcd.h @@ -0,0 +1,47 @@ +/** + * 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 + +/******************************************************************************** + * @file dwin_lcd.h + * @author LEO / Creality3D + * @date 2019/07/18 + * @version 2.0.1 + * @brief 迪文屏控制操作函数 + ********************************************************************************/ + +#include "../common/dwin_api.h" +#include "../common/dwin_set.h" +#include "../common/dwin_font.h" +#include "../common/dwin_color.h" + +#define DWIN_FONT_MENU font10x20 +#define DWIN_FONT_STAT font10x20 +#define DWIN_FONT_HEAD font10x20 +#define DWIN_FONT_ALERT font14x28 + +// Copy area from virtual display area to current screen +// cacheID: virtual area number +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y); diff --git a/src/lcd/e3v2/jyersui/README.md b/src/lcd/e3v2/jyersui/README.md new file mode 100644 index 0000000..83ccb74 --- /dev/null +++ b/src/lcd/e3v2/jyersui/README.md @@ -0,0 +1,7 @@ +# DWIN for Creality Ender 3 v2 + +Marlin's Ender 3 v2 support requires the `DWIN_SET` included with the Ender 3 V2 [example configuration](https://github.com/MarlinFirmware/Configurations/tree/bugfix-2.0.x/config/examples/Creality/Ender-3%20V2). + +## Easy Install + +Copy the `DWIN_SET` folder onto a Micro-SD card and insert the card into the slot on the DWIN screen. Cycle the machine and wait for the screen to go from blue to orange. Turn the machine off and remove the SD card. When you turn on the machine the screen will display a "Creality" loading screen. diff --git a/src/lcd/e3v2/jyersui/dwin.cpp b/src/lcd/e3v2/jyersui/dwin.cpp new file mode 100644 index 0000000..285013d --- /dev/null +++ b/src/lcd/e3v2/jyersui/dwin.cpp @@ -0,0 +1,4848 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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/e3v2/jyersui/dwin.cpp + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_CREALITY_LCD_JYERSUI) + +#include "dwin.h" + +#include "../../marlinui.h" +#include "../../../MarlinCore.h" + +#include "../../../gcode/gcode.h" +#include "../../../module/temperature.h" +#include "../../../module/planner.h" +#include "../../../module/settings.h" +#include "../../../libs/buzzer.h" +#include "../../../inc/Conditionals_post.h" + +//#define DEBUG_OUT 1 +#include "../../../core/debug_out.h" + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + #include "../../../feature/pause.h" +#endif + +#if ENABLED(FILAMENT_RUNOUT_SENSOR) + #include "../../../feature/runout.h" +#endif + +#if ENABLED(HOST_ACTION_COMMANDS) + #include "../../../feature/host_actions.h" +#endif + +#if ANY(BABYSTEPPING, HAS_BED_PROBE, HAS_WORKSPACE_OFFSET) + #define HAS_ZOFFSET_ITEM 1 +#endif + +#ifndef strcasecmp_P + #define strcasecmp_P(a, b) strcasecmp((a), (b)) +#endif + +#if HAS_LEVELING + #include "../../../feature/bedlevel/bedlevel.h" +#endif + +#if ENABLED(AUTO_BED_LEVELING_UBL) + #include "../../../libs/least_squares_fit.h" + #include "../../../libs/vector_3.h" +#endif + +#if HAS_BED_PROBE + #include "../../../module/probe.h" +#endif + +#if ENABLED(POWER_LOSS_RECOVERY) + #include "../../../feature/powerloss.h" +#endif + +#define MACHINE_SIZE STRINGIFY(X_BED_SIZE) "x" STRINGIFY(Y_BED_SIZE) "x" STRINGIFY(Z_MAX_POS) + +#define DWIN_FONT_MENU font8x16 +#define DWIN_FONT_STAT font10x20 +#define DWIN_FONT_HEAD font10x20 + +#define MENU_CHAR_LIMIT 24 +#define STATUS_Y 352 + +#define MAX_PRINT_SPEED 500 +#define MIN_PRINT_SPEED 10 + +#if HAS_FAN + #define MAX_FAN_SPEED 255 + #define MIN_FAN_SPEED 0 +#endif + +#define MAX_XY_OFFSET 100 + +#if HAS_ZOFFSET_ITEM + #define MAX_Z_OFFSET 9.99 + #if HAS_BED_PROBE + #define MIN_Z_OFFSET -9.99 + #else + #define MIN_Z_OFFSET -1 + #endif +#endif + +#if HAS_HOTEND + #define MAX_FLOW_RATE 200 + #define MIN_FLOW_RATE 10 + + #define MAX_E_TEMP (HEATER_0_MAXTEMP - HOTEND_OVERSHOOT) + #define MIN_E_TEMP 0 +#endif + +#if HAS_HEATED_BED + #define MAX_BED_TEMP BED_MAXTEMP + #define MIN_BED_TEMP 0 +#endif + +/** + * Custom menu items with jyersLCD + */ +#if ENABLED(CUSTOM_MENU_CONFIG) + #ifdef CONFIG_MENU_ITEM_5_DESC + #define CUSTOM_MENU_COUNT 5 + #elif defined(CONFIG_MENU_ITEM_4_DESC) + #define CUSTOM_MENU_COUNT 4 + #elif defined(CONFIG_MENU_ITEM_3_DESC) + #define CUSTOM_MENU_COUNT 3 + #elif defined(CONFIG_MENU_ITEM_2_DESC) + #define CUSTOM_MENU_COUNT 2 + #elif defined(CONFIG_MENU_ITEM_1_DESC) + #define CUSTOM_MENU_COUNT 1 + #endif + #if CUSTOM_MENU_COUNT + #define HAS_CUSTOM_MENU 1 + #endif +#endif + +constexpr uint16_t TROWS = 6, MROWS = TROWS - 1, + TITLE_HEIGHT = 30, + MLINE = 53, + LBLX = 60, + MENU_CHR_W = 8, MENU_CHR_H = 16, STAT_CHR_W = 10; + +#define MBASE(L) (49 + MLINE * (L)) + +constexpr float default_max_feedrate[] = DEFAULT_MAX_FEEDRATE; +constexpr float default_max_acceleration[] = DEFAULT_MAX_ACCELERATION; +constexpr float default_steps[] = DEFAULT_AXIS_STEPS_PER_UNIT; +#if HAS_CLASSIC_JERK + constexpr float default_max_jerk[] = { DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_EJERK }; +#endif + +enum SelectItem : uint8_t { + PAGE_PRINT = 0, + PAGE_PREPARE, + PAGE_CONTROL, + PAGE_INFO_LEVELING, + PAGE_COUNT, + + PRINT_SETUP = 0, + PRINT_PAUSE_RESUME, + PRINT_STOP, + PRINT_COUNT +}; + +uint8_t active_menu = MainMenu, last_menu = MainMenu; +uint8_t selection = 0, last_selection = 0; +uint8_t scrollpos = 0; +uint8_t process = Main, last_process = Main; +PopupID popup, last_popup; + +void (*funcpointer)() = nullptr; +void *valuepointer = nullptr; +float tempvalue; +float valuemin; +float valuemax; +uint8_t valueunit; +uint8_t valuetype; + +char cmd[MAX_CMD_SIZE+16], str_1[16], str_2[16], str_3[16]; +char statusmsg[64]; +char filename[LONG_FILENAME_LENGTH]; +bool printing = false; +bool paused = false; +bool sdprint = false; + +int16_t pausetemp, pausebed, pausefan; + +bool livemove = false; +bool liveadjust = false; +uint8_t preheatmode = 0; +float zoffsetvalue = 0; +uint8_t gridpoint; +float corner_avg; +float corner_pos; + +bool probe_deployed = false; + +CrealityDWINClass CrealityDWIN; + +#if HAS_MESH + + struct Mesh_Settings { + bool viewer_asymmetric_range = false; + bool viewer_print_value = false; + bool goto_mesh_value = false; + bool drawing_mesh = false; + uint8_t mesh_x = 0; + uint8_t mesh_y = 0; + + #if ENABLED(AUTO_BED_LEVELING_UBL) + uint8_t tilt_grid = 1; + + void manual_value_update(bool undefined=false) { + sprintf_P(cmd, PSTR("M421 I%i J%i Z%s %s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1), undefined ? "N" : ""); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } + + bool create_plane_from_mesh() { + struct linear_fit_data lsf_results; + incremental_LSF_reset(&lsf_results); + GRID_LOOP(x, y) { + if (!isnan(bedlevel.z_values[x][y])) { + xy_pos_t rpos = { bedlevel.get_mesh_x(x), bedlevel.get_mesh_y(y) }; + incremental_LSF(&lsf_results, rpos, bedlevel.z_values[x][y]); + } + } + + if (finish_incremental_LSF(&lsf_results)) { + SERIAL_ECHOPGM("Could not complete LSF!"); + return true; + } + + bedlevel.set_all_mesh_points_to_value(0); + + matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1)); + GRID_LOOP(i, j) { + float mx = bedlevel.get_mesh_x(i), + my = bedlevel.get_mesh_y(j), + mz = bedlevel.z_values[i][j]; + + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOPAIR_F("before rotation = [", mx, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(my, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(mz, 7); + DEBUG_ECHOPGM("] ---> "); + DEBUG_DELAY(20); + } + + rotation.apply_rotation_xyz(mx, my, mz); + + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOPAIR_F("after rotation = [", mx, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(my, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(mz, 7); + DEBUG_ECHOLNPGM("]"); + DEBUG_DELAY(20); + } + + bedlevel.z_values[i][j] = mz - lsf_results.D; + } + return false; + } + + #else + + void manual_value_update() { + sprintf_P(cmd, PSTR("G29 I%i J%i Z%s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } + + #endif + + void manual_mesh_move(const bool zmove=false) { + if (zmove) { + planner.synchronize(); + current_position.z = goto_mesh_value ? bedlevel.z_values[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES; + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + planner.synchronize(); + } + else { + CrealityDWIN.Popup_Handler(MoveWait); + sprintf_P(cmd, PSTR("G0 F300 Z%s"), dtostrf(Z_CLEARANCE_BETWEEN_PROBES, 1, 3, str_1)); + gcode.process_subcommands_now(cmd); + sprintf_P(cmd, PSTR("G42 F4000 I%i J%i"), mesh_x, mesh_y); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + current_position.z = goto_mesh_value ? bedlevel.z_values[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES; + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + planner.synchronize(); + CrealityDWIN.Redraw_Menu(); + } + } + + float get_max_value() { + float max = __FLT_MIN__; + GRID_LOOP(x, y) { + if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] > max) + max = bedlevel.z_values[x][y]; + } + return max; + } + + float get_min_value() { + float min = __FLT_MAX__; + GRID_LOOP(x, y) { + if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] < min) + min = bedlevel.z_values[x][y]; + } + return min; + } + + void Draw_Bed_Mesh(int16_t selected = -1, uint8_t gridline_width = 1, uint16_t padding_x = 8, uint16_t padding_y_top = 40 + 53 - 7) { + drawing_mesh = true; + const uint16_t total_width_px = DWIN_WIDTH - padding_x - padding_x, + cell_width_px = total_width_px / (GRID_MAX_POINTS_X), + cell_height_px = total_width_px / (GRID_MAX_POINTS_Y); + const float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max); + + // Clear background from previous selection and select new square + DWIN_Draw_Rectangle(1, Color_Bg_Black, _MAX(0, padding_x - gridline_width), _MAX(0, padding_y_top - gridline_width), padding_x + total_width_px, padding_y_top + total_width_px); + if (selected >= 0) { + const auto selected_y = selected / (GRID_MAX_POINTS_X); + const auto selected_x = selected - (GRID_MAX_POINTS_X) * selected_y; + const auto start_y_px = padding_y_top + selected_y * cell_height_px; + const auto start_x_px = padding_x + selected_x * cell_width_px; + DWIN_Draw_Rectangle(1, Color_White, _MAX(0, start_x_px - gridline_width), _MAX(0, start_y_px - gridline_width), start_x_px + cell_width_px, start_y_px + cell_height_px); + } + + // Draw value square grid + char buf[8]; + GRID_LOOP(x, y) { + const auto start_x_px = padding_x + x * cell_width_px; + const auto end_x_px = start_x_px + cell_width_px - 1 - gridline_width; + const auto start_y_px = padding_y_top + (GRID_MAX_POINTS_Y - y - 1) * cell_height_px; + const auto end_y_px = start_y_px + cell_height_px - 1 - gridline_width; + DWIN_Draw_Rectangle(1, // RGB565 colors: http://www.barth-dev.de/online/rgb565-color-picker/ + isnan(bedlevel.z_values[x][y]) ? Color_Grey : ( // gray if undefined + (bedlevel.z_values[x][y] < 0 ? + (uint16_t)round(0x1F * -bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_min)) << 11 : // red if mesh point value is negative + (uint16_t)round(0x3F * bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_max)) << 5) | // green if mesh point value is positive + _MIN(0x1F, (((uint8_t)abs(bedlevel.z_values[x][y]) / 10) * 4))), // + blue stepping for every mm + start_x_px, start_y_px, end_x_px, end_y_px + ); + + safe_delay(10); + LCD_SERIAL.flushTX(); + + // Draw value text on + if (viewer_print_value) { + int8_t offset_x, offset_y = cell_height_px / 2 - 6; + if (isnan(bedlevel.z_values[x][y])) { // undefined + DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X")); + } + else { // has value + if (GRID_MAX_POINTS_X < 10) + sprintf_P(buf, PSTR("%s"), dtostrf(abs(bedlevel.z_values[x][y]), 1, 2, str_1)); + else + sprintf_P(buf, PSTR("%02i"), (uint16_t)(abs(bedlevel.z_values[x][y] - (int16_t)bedlevel.z_values[x][y]) * 100)); + offset_x = cell_width_px / 2 - 3 * (strlen(buf)) - 2; + if (!(GRID_MAX_POINTS_X < 10)) + DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px - 2 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, F(".")); + DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + 1 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, buf); + } + safe_delay(10); + LCD_SERIAL.flushTX(); + } + } + } + + void Set_Mesh_Viewer_Status() { // TODO: draw gradient with values as a legend instead + float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max); + if (v_min > 3e+10F) v_min = 0.0000001; + if (v_max > 3e+10F) v_max = 0.0000001; + if (range > 3e+10F) range = 0.0000001; + char msg[46]; + if (viewer_asymmetric_range) { + dtostrf(-v_min, 1, 3, str_1); + dtostrf( v_max, 1, 3, str_2); + } + else { + dtostrf(-range, 1, 3, str_1); + dtostrf( range, 1, 3, str_2); + } + sprintf_P(msg, PSTR("Red %s..0..%s Green"), str_1, str_2); + CrealityDWIN.Update_Status(msg); + drawing_mesh = false; + } + + }; + Mesh_Settings mesh_conf; + +#endif // HAS_MESH + +/* General Display Functions */ + +struct CrealityDWINClass::EEPROM_Settings CrealityDWINClass::eeprom_settings{0}; +constexpr const char * const CrealityDWINClass::color_names[11]; +constexpr const char * const CrealityDWINClass::preheat_modes[3]; + +// Clear a part of the screen +// 4=Entire screen +// 3=Title bar and Menu area (default) +// 2=Menu area +// 1=Title bar +void CrealityDWINClass::Clear_Screen(uint8_t e/*=3*/) { + if (e == 1 || e == 3 || e == 4) DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.menu_top_bg, Color_Bg_Blue, false), 0, 0, DWIN_WIDTH, TITLE_HEIGHT); // Clear Title Bar + if (e == 2 || e == 3) DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, 31, DWIN_WIDTH, STATUS_Y); // Clear Menu Area + if (e == 4) DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, 31, DWIN_WIDTH, DWIN_HEIGHT); // Clear Popup Area +} + +void CrealityDWINClass::Draw_Float(float value, uint8_t row, bool selected/*=false*/, uint8_t minunit/*=10*/) { + const uint8_t digits = (uint8_t)floor(log10(abs(value))) + log10(minunit) + (minunit > 1); + const uint16_t bColor = (selected) ? Select_Color : Color_Bg_Black; + const uint16_t xpos = 240 - (digits * 8); + DWIN_Draw_Rectangle(1, Color_Bg_Black, 194, MBASE(row), 234 - (digits * 8), MBASE(row) + 16); + if (isnan(value)) + DWIN_Draw_String(true, DWIN_FONT_MENU, Color_White, bColor, xpos - 8, MBASE(row), F(" NaN")); + else { + DWIN_Draw_FloatValue(true, true, 0, DWIN_FONT_MENU, Color_White, bColor, digits - log10(minunit) + 1, log10(minunit), xpos, MBASE(row), (value < 0 ? -value : value)); + DWIN_Draw_String(true, DWIN_FONT_MENU, Color_White, bColor, xpos - 8, MBASE(row), value < 0 ? F("-") : F(" ")); + } +} + +void CrealityDWINClass::Draw_Option(uint8_t value, const char * const * options, uint8_t row, bool selected/*=false*/, bool color/*=false*/) { + uint16_t bColor = (selected) ? Select_Color : Color_Bg_Black, + tColor = (color) ? GetColor(value, Color_White, false) : Color_White; + DWIN_Draw_Rectangle(1, bColor, 202, MBASE(row) + 14, 258, MBASE(row) - 2); + DWIN_Draw_String(false, DWIN_FONT_MENU, tColor, bColor, 202, MBASE(row) - 1, options[value]); +} + +uint16_t CrealityDWINClass::GetColor(uint8_t color, uint16_t original, bool light/*=false*/) { + switch (color) { + case Default: + return original; + break; + case White: + return (light) ? Color_Light_White : Color_White; + break; + case Green: + return (light) ? Color_Light_Green : Color_Green; + break; + case Cyan: + return (light) ? Color_Light_Cyan : Color_Cyan; + break; + case Blue: + return (light) ? Color_Light_Blue : Color_Blue; + break; + case Magenta: + return (light) ? Color_Light_Magenta : Color_Magenta; + break; + case Red: + return (light) ? Color_Light_Red : Color_Red; + break; + case Orange: + return (light) ? Color_Light_Orange : Color_Orange; + break; + case Yellow: + return (light) ? Color_Light_Yellow : Color_Yellow; + break; + case Brown: + return (light) ? Color_Light_Brown : Color_Brown; + break; + case Black: + return Color_Black; + break; + } + return Color_White; +} + +void CrealityDWINClass::Draw_Title(const char * ctitle) { + DWIN_Draw_String(false, DWIN_FONT_HEAD, GetColor(eeprom_settings.menu_top_txt, Color_White, false), Color_Bg_Blue, (DWIN_WIDTH - strlen(ctitle) * STAT_CHR_W) / 2, 5, ctitle); +} +void CrealityDWINClass::Draw_Title(FSTR_P const ftitle) { + DWIN_Draw_String(false, DWIN_FONT_HEAD, GetColor(eeprom_settings.menu_top_txt, Color_White, false), Color_Bg_Blue, (DWIN_WIDTH - strlen_P(FTOP(ftitle)) * STAT_CHR_W) / 2, 5, ftitle); +} + +void _Decorate_Menu_Item(uint8_t row, uint8_t icon, bool more) { + if (icon) DWIN_ICON_Show(ICON, icon, 26, MBASE(row) - 3); //Draw Menu Icon + if (more) DWIN_ICON_Show(ICON, ICON_More, 226, MBASE(row) - 3); // Draw More Arrow + DWIN_Draw_Line(CrealityDWIN.GetColor(CrealityDWIN.eeprom_settings.menu_split_line, Line_Color, true), 16, MBASE(row) + 33, 256, MBASE(row) + 33); // Draw Menu Line +} + +void CrealityDWINClass::Draw_Menu_Item(uint8_t row, uint8_t icon/*=0*/, const char * label1, const char * label2, bool more/*=false*/, bool centered/*=false*/) { + const uint8_t label_offset_y = (label1 || label2) ? MENU_CHR_H * 3 / 5 : 0, + label1_offset_x = !centered ? LBLX : LBLX * 4/5 + _MAX(LBLX * 1U/5, (DWIN_WIDTH - LBLX - (label1 ? strlen(label1) : 0) * MENU_CHR_W) / 2), + label2_offset_x = !centered ? LBLX : LBLX * 4/5 + _MAX(LBLX * 1U/5, (DWIN_WIDTH - LBLX - (label2 ? strlen(label2) : 0) * MENU_CHR_W) / 2); + if (label1) DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, label1_offset_x, MBASE(row) - 1 - label_offset_y, label1); // Draw Label + if (label2) DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, label2_offset_x, MBASE(row) - 1 + label_offset_y, label2); // Draw Label + _Decorate_Menu_Item(row, icon, more); +} + +void CrealityDWINClass::Draw_Menu_Item(uint8_t row, uint8_t icon/*=0*/, FSTR_P const flabel1, FSTR_P const flabel2, bool more/*=false*/, bool centered/*=false*/) { + const uint8_t label_offset_y = (flabel1 || flabel2) ? MENU_CHR_H * 3 / 5 : 0, + label1_offset_x = !centered ? LBLX : LBLX * 4/5 + _MAX(LBLX * 1U/5, (DWIN_WIDTH - LBLX - (flabel1 ? strlen_P(FTOP(flabel1)) : 0) * MENU_CHR_W) / 2), + label2_offset_x = !centered ? LBLX : LBLX * 4/5 + _MAX(LBLX * 1U/5, (DWIN_WIDTH - LBLX - (flabel2 ? strlen_P(FTOP(flabel2)) : 0) * MENU_CHR_W) / 2); + if (flabel1) DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, label1_offset_x, MBASE(row) - 1 - label_offset_y, flabel1); // Draw Label + if (flabel2) DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, label2_offset_x, MBASE(row) - 1 + label_offset_y, flabel2); // Draw Label + _Decorate_Menu_Item(row, icon, more); +} + +void CrealityDWINClass::Draw_Checkbox(uint8_t row, bool value) { + #if ENABLED(DWIN_CREALITY_LCD_CUSTOM_ICONS) // Draw appropriate checkbox icon + DWIN_ICON_Show(ICON, (value ? ICON_Checkbox_T : ICON_Checkbox_F), 226, MBASE(row) - 3); + #else // Draw a basic checkbox using rectangles and lines + DWIN_Draw_Rectangle(1, Color_Bg_Black, 226, MBASE(row) - 3, 226 + 20, MBASE(row) - 3 + 20); + DWIN_Draw_Rectangle(0, Color_White, 226, MBASE(row) - 3, 226 + 20, MBASE(row) - 3 + 20); + if (value) { + DWIN_Draw_Line(Check_Color, 227, MBASE(row) - 3 + 11, 226 + 8, MBASE(row) - 3 + 17); + DWIN_Draw_Line(Check_Color, 227 + 8, MBASE(row) - 3 + 17, 226 + 19, MBASE(row) - 3 + 1); + DWIN_Draw_Line(Check_Color, 227, MBASE(row) - 3 + 12, 226 + 8, MBASE(row) - 3 + 18); + DWIN_Draw_Line(Check_Color, 227 + 8, MBASE(row) - 3 + 18, 226 + 19, MBASE(row) - 3 + 2); + DWIN_Draw_Line(Check_Color, 227, MBASE(row) - 3 + 13, 226 + 8, MBASE(row) - 3 + 19); + DWIN_Draw_Line(Check_Color, 227 + 8, MBASE(row) - 3 + 19, 226 + 19, MBASE(row) - 3 + 3); + } + #endif +} + +void CrealityDWINClass::Draw_Menu(uint8_t menu, uint8_t select/*=0*/, uint8_t scroll/*=0*/) { + if (active_menu != menu) { + last_menu = active_menu; + if (process == Menu) last_selection = selection; + } + selection = _MIN(select, Get_Menu_Size(menu)); + scrollpos = scroll; + if (selection - scrollpos > MROWS) + scrollpos = selection - MROWS; + process = Menu; + active_menu = menu; + Clear_Screen(); + Draw_Title(Get_Menu_Title(menu)); + LOOP_L_N(i, TROWS) Menu_Item_Handler(menu, i + scrollpos); + DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.cursor_color, Rectangle_Color), 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); +} + +void CrealityDWINClass::Redraw_Menu(bool lastprocess/*=true*/, bool lastselection/*=false*/, bool lastmenu/*=false*/) { + switch ((lastprocess) ? last_process : process) { + case Menu: + Draw_Menu((lastmenu) ? last_menu : active_menu, (lastselection) ? last_selection : selection, (lastmenu) ? 0 : scrollpos); + break; + case Main: Draw_Main_Menu((lastselection) ? last_selection : selection); break; + case Print: Draw_Print_Screen(); break; + case File: Draw_SD_List(); break; + default: break; + } +} + +void CrealityDWINClass::Redraw_Screen() { + Redraw_Menu(false); + Draw_Status_Area(true); + Update_Status_Bar(true); +} + +/* Primary Menus and Screen Elements */ + +void CrealityDWINClass::Main_Menu_Icons() { + if (selection == 0) { + DWIN_ICON_Show(ICON, ICON_Print_1, 17, 130); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 17, 130, 126, 229); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 52, 200, F("Print")); + } + else { + DWIN_ICON_Show(ICON, ICON_Print_0, 17, 130); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 52, 200, F("Print")); + } + if (selection == 1) { + DWIN_ICON_Show(ICON, ICON_Prepare_1, 145, 130); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 145, 130, 254, 229); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 170, 200, F("Prepare")); + } + else { + DWIN_ICON_Show(ICON, ICON_Prepare_0, 145, 130); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 170, 200, F("Prepare")); + } + if (selection == 2) { + DWIN_ICON_Show(ICON, ICON_Control_1, 17, 246); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 17, 246, 126, 345); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 43, 317, F("Control")); + } + else { + DWIN_ICON_Show(ICON, ICON_Control_0, 17, 246); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 43, 317, F("Control")); + } + #if HAS_ABL_OR_UBL + if (selection == 3) { + DWIN_ICON_Show(ICON, ICON_Leveling_1, 145, 246); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 145, 246, 254, 345); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 179, 317, F("Level")); + } + else { + DWIN_ICON_Show(ICON, ICON_Leveling_0, 145, 246); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 179, 317, F("Level")); + } + #else + if (selection == 3) { + DWIN_ICON_Show(ICON, ICON_Info_1, 145, 246); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 145, 246, 254, 345); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 181, 317, F("Info")); + } + else { + DWIN_ICON_Show(ICON, ICON_Info_0, 145, 246); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 181, 317, F("Info")); + } + #endif +} + +void CrealityDWINClass::Draw_Main_Menu(uint8_t select/*=0*/) { + process = Main; + active_menu = MainMenu; + selection = select; + Clear_Screen(); + Draw_Title(Get_Menu_Title(MainMenu)); + SERIAL_ECHOPGM("\nDWIN handshake "); + DWIN_ICON_Show(ICON, ICON_LOGO, 71, 72); + Main_Menu_Icons(); +} + +void CrealityDWINClass::Print_Screen_Icons() { + if (selection == 0) { + DWIN_ICON_Show(ICON, ICON_Setup_1, 8, 252); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 8, 252, 87, 351); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 30, 322, F("Tune")); + } + else { + DWIN_ICON_Show(ICON, ICON_Setup_0, 8, 252); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 30, 322, F("Tune")); + } + if (selection == 2) { + DWIN_ICON_Show(ICON, ICON_Stop_1, 184, 252); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 184, 252, 263, 351); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 205, 322, F("Stop")); + } + else { + DWIN_ICON_Show(ICON, ICON_Stop_0, 184, 252); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 205, 322, F("Stop")); + } + if (paused) { + if (selection == 1) { + DWIN_ICON_Show(ICON, ICON_Continue_1, 96, 252); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 96, 252, 175, 351); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 114, 322, F("Print")); + } + else { + DWIN_ICON_Show(ICON, ICON_Continue_0, 96, 252); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 114, 322, F("Print")); + } + } + else { + if (selection == 1) { + DWIN_ICON_Show(ICON, ICON_Pause_1, 96, 252); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 96, 252, 175, 351); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 114, 322, F("Pause")); + } + else { + DWIN_ICON_Show(ICON, ICON_Pause_0, 96, 252); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Blue, 114, 322, F("Pause")); + } + } +} + +void CrealityDWINClass::Draw_Print_Screen() { + process = Print; + selection = 0; + Clear_Screen(); + DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 352, DWIN_WIDTH - 8, 376); + Draw_Title("Printing..."); + Print_Screen_Icons(); + DWIN_ICON_Show(ICON, ICON_PrintTime, 14, 171); + DWIN_ICON_Show(ICON, ICON_RemainTime, 147, 169); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, 41, 163, F("Elapsed")); + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, 176, 163, F("Remaining")); + Update_Status_Bar(true); + Draw_Print_ProgressBar(); + Draw_Print_ProgressElapsed(); + TERN_(USE_M73_REMAINING_TIME, Draw_Print_ProgressRemain()); + Draw_Print_Filename(true); +} + +void CrealityDWINClass::Draw_Print_Filename(const bool reset/*=false*/) { + static uint8_t namescrl = 0; + if (reset) namescrl = 0; + if (process == Print) { + constexpr int8_t maxlen = 30; + char *outstr = filename; + size_t slen = strlen(filename); + int8_t outlen = slen; + if (slen > maxlen) { + char dispname[maxlen + 1]; + int8_t pos = slen - namescrl, len = maxlen; + if (pos >= 0) { + NOMORE(len, pos); + LOOP_L_N(i, len) dispname[i] = filename[i + namescrl]; + } + else { + const int8_t mp = maxlen + pos; + LOOP_L_N(i, mp) dispname[i] = ' '; + LOOP_S_L_N(i, mp, maxlen) dispname[i] = filename[i - mp]; + if (mp <= 0) namescrl = 0; + } + dispname[len] = '\0'; + outstr = dispname; + outlen = maxlen; + namescrl++; + } + DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 50, DWIN_WIDTH - 8, 80); + const int8_t npos = (DWIN_WIDTH - outlen * MENU_CHR_W) / 2; + DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, npos, 60, outstr); + } +} + +void CrealityDWINClass::Draw_Print_ProgressBar() { + uint8_t printpercent = sdprint ? card.percentDone() : (ui._get_progress() / 100); + DWIN_ICON_Show(ICON, ICON_Bar, 15, 93); + DWIN_Draw_Rectangle(1, BarFill_Color, 16 + printpercent * 240 / 100, 93, 256, 113); + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_percent, Percent_Color), Color_Bg_Black, 3, 109, 133, printpercent); + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_percent, Percent_Color), Color_Bg_Black, 133, 133, F("%")); +} + +#if ENABLED(USE_M73_REMAINING_TIME) + + void CrealityDWINClass::Draw_Print_ProgressRemain() { + uint16_t remainingtime = ui.get_remaining_time(); + DWIN_Draw_IntValue(true, true, 1, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 2, 176, 187, remainingtime / 3600); + DWIN_Draw_IntValue(true, true, 1, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 2, 200, 187, (remainingtime % 3600) / 60); + if (eeprom_settings.time_format_textual) { + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 192, 187, F("h")); + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 216, 187, F("m")); + } + else + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 192, 187, F(":")); + } + +#endif + +void CrealityDWINClass::Draw_Print_ProgressElapsed() { + duration_t elapsed = print_job_timer.duration(); + DWIN_Draw_IntValue(true, true, 1, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 2, 42, 187, elapsed.value / 3600); + DWIN_Draw_IntValue(true, true, 1, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 2, 66, 187, (elapsed.value % 3600) / 60); + if (eeprom_settings.time_format_textual) { + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 58, 187, F("h")); + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 82, 187, F("m")); + } + else + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.progress_time, Color_White), Color_Bg_Black, 58, 187, F(":")); +} + +void CrealityDWINClass::Draw_Print_confirm() { + Draw_Print_Screen(); + process = Confirm; + popup = Complete; + DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 252, 263, 351); + DWIN_ICON_Show(ICON, ICON_Confirm_E, 87, 283); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 86, 282, 187, 321); + DWIN_Draw_Rectangle(0, GetColor(eeprom_settings.highlight_box, Color_White), 85, 281, 188, 322); +} + +void CrealityDWINClass::Draw_SD_Item(uint8_t item, uint8_t row) { + if (item == 0) + Draw_Menu_Item(0, ICON_Back, card.flag.workDirIsRoot ? F("Back") : F("..")); + else { + card.getfilename_sorted(SD_ORDER(item - 1, card.get_num_Files())); + char * const filename = card.longest_filename(); + size_t max = MENU_CHAR_LIMIT; + size_t pos = strlen(filename), len = pos; + if (!card.flag.filenameIsDir) + while (pos && filename[pos] != '.') pos--; + len = pos; + if (len > max) len = max; + char name[len + 1]; + LOOP_L_N(i, len) name[i] = filename[i]; + if (pos > max) + LOOP_S_L_N(i, len - 3, len) name[i] = '.'; + name[len] = '\0'; + Draw_Menu_Item(row, card.flag.filenameIsDir ? ICON_More : ICON_File, name); + } +} + +void CrealityDWINClass::Draw_SD_List(bool removed/*=false*/) { + Clear_Screen(); + Draw_Title("Select File"); + selection = 0; + scrollpos = 0; + process = File; + if (card.isMounted() && !removed) { + LOOP_L_N(i, _MIN(card.get_num_Files() + 1, TROWS)) + Draw_SD_Item(i, i); + } + else { + Draw_Menu_Item(0, ICON_Back, F("Back")); + DWIN_Draw_Rectangle(1, Color_Bg_Red, 10, MBASE(3) - 10, DWIN_WIDTH - 10, MBASE(4)); + DWIN_Draw_String(false, font16x32, Color_Yellow, Color_Bg_Red, ((DWIN_WIDTH) - 8 * 16) / 2, MBASE(3), F("No Media")); + } + DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.cursor_color, Rectangle_Color), 0, MBASE(0) - 18, 14, MBASE(0) + 33); +} + +void CrealityDWINClass::Draw_Status_Area(bool icons/*=false*/) { + + if (icons) DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, STATUS_Y, DWIN_WIDTH, DWIN_HEIGHT - 1); + + #if HAS_HOTEND + static float hotend = -1; + static int16_t hotendtarget = -1, flow = -1; + if (icons) { + hotend = -1; + hotendtarget = -1; + DWIN_ICON_Show(ICON, ICON_HotendTemp, 10, 383); + DWIN_Draw_String(false, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 25 + 3 * STAT_CHR_W + 5, 384, F("/")); + } + if (thermalManager.temp_hotend[0].celsius != hotend) { + hotend = thermalManager.temp_hotend[0].celsius; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 28, 384, thermalManager.temp_hotend[0].celsius); + DWIN_Draw_DegreeSymbol(GetColor(eeprom_settings.status_area_text, Color_White), 25 + 3 * STAT_CHR_W + 5, 386); + } + if (thermalManager.temp_hotend[0].target != hotendtarget) { + hotendtarget = thermalManager.temp_hotend[0].target; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 25 + 4 * STAT_CHR_W + 6, 384, thermalManager.temp_hotend[0].target); + DWIN_Draw_DegreeSymbol(GetColor(eeprom_settings.status_area_text, Color_White), 25 + 4 * STAT_CHR_W + 39, 386); + } + if (icons) { + flow = -1; + DWIN_ICON_Show(ICON, ICON_StepE, 112, 417); + DWIN_Draw_String(false, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 116 + 5 * STAT_CHR_W + 2, 417, F("%")); + } + if (planner.flow_percentage[0] != flow) { + flow = planner.flow_percentage[0]; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 116 + 2 * STAT_CHR_W, 417, planner.flow_percentage[0]); + } + #endif + + #if HAS_HEATED_BED + static float bed = -1; + static int16_t bedtarget = -1; + if (icons) { + bed = -1; + bedtarget = -1; + DWIN_ICON_Show(ICON, ICON_BedTemp, 10, 416); + DWIN_Draw_String(false, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 25 + 3 * STAT_CHR_W + 5, 417, F("/")); + } + if (thermalManager.temp_bed.celsius != bed) { + bed = thermalManager.temp_bed.celsius; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 28, 417, thermalManager.temp_bed.celsius); + DWIN_Draw_DegreeSymbol(GetColor(eeprom_settings.status_area_text, Color_White), 25 + 3 * STAT_CHR_W + 5, 419); + } + if (thermalManager.temp_bed.target != bedtarget) { + bedtarget = thermalManager.temp_bed.target; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 25 + 4 * STAT_CHR_W + 6, 417, thermalManager.temp_bed.target); + DWIN_Draw_DegreeSymbol(GetColor(eeprom_settings.status_area_text, Color_White), 25 + 4 * STAT_CHR_W + 39, 419); + } + #endif + + #if HAS_FAN + static uint8_t fan = -1; + if (icons) { + fan = -1; + DWIN_ICON_Show(ICON, ICON_FanSpeed, 187, 383); + } + if (thermalManager.fan_speed[0] != fan) { + fan = thermalManager.fan_speed[0]; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 195 + 2 * STAT_CHR_W, 384, thermalManager.fan_speed[0]); + } + #endif + + #if HAS_ZOFFSET_ITEM + static float offset = -1; + + if (icons) { + offset = -1; + DWIN_ICON_Show(ICON, ICON_Zoffset, 187, 416); + } + if (zoffsetvalue != offset) { + offset = zoffsetvalue; + DWIN_Draw_FloatValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 2, 2, 207, 417, (zoffsetvalue < 0 ? -zoffsetvalue : zoffsetvalue)); + DWIN_Draw_String(true, DWIN_FONT_MENU, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 205, 419, zoffsetvalue < 0 ? F("-") : F(" ")); + } + #endif + + static int16_t feedrate = -1; + if (icons) { + feedrate = -1; + DWIN_ICON_Show(ICON, ICON_Speed, 113, 383); + DWIN_Draw_String(false, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 116 + 5 * STAT_CHR_W + 2, 384, F("%")); + } + if (feedrate_percentage != feedrate) { + feedrate = feedrate_percentage; + DWIN_Draw_IntValue(true, true, 0, DWIN_FONT_STAT, GetColor(eeprom_settings.status_area_text, Color_White), Color_Bg_Black, 3, 116 + 2 * STAT_CHR_W, 384, feedrate_percentage); + } + + static float x = -1, y = -1, z = -1; + static bool update_x = false, update_y = false, update_z = false; + update_x = (current_position.x != x || axis_should_home(X_AXIS) || update_x); + update_y = (current_position.y != y || axis_should_home(Y_AXIS) || update_y); + update_z = (current_position.z != z || axis_should_home(Z_AXIS) || update_z); + if (icons) { + x = y = z = -1; + DWIN_Draw_Line(GetColor(eeprom_settings.coordinates_split_line, Line_Color, true), 16, 450, 256, 450); + DWIN_ICON_Show(ICON, ICON_MaxSpeedX, 10, 456); + DWIN_ICON_Show(ICON, ICON_MaxSpeedY, 95, 456); + DWIN_ICON_Show(ICON, ICON_MaxSpeedZ, 180, 456); + } + if (update_x) { + x = current_position.x; + if ((update_x = axis_should_home(X_AXIS) && ui.get_blink())) + DWIN_Draw_String(true, DWIN_FONT_MENU, GetColor(eeprom_settings.coordinates_text, Color_White), Color_Bg_Black, 35, 459, F(" -?- ")); + else + DWIN_Draw_FloatValue(true, true, 0, DWIN_FONT_MENU, GetColor(eeprom_settings.coordinates_text, Color_White), Color_Bg_Black, 3, 1, 35, 459, current_position.x); + } + if (update_y) { + y = current_position.y; + if ((update_y = axis_should_home(Y_AXIS) && ui.get_blink())) + DWIN_Draw_String(true, DWIN_FONT_MENU, GetColor(eeprom_settings.coordinates_text, Color_White), Color_Bg_Black, 120, 459, F(" -?- ")); + else + DWIN_Draw_FloatValue(true, true, 0, DWIN_FONT_MENU, GetColor(eeprom_settings.coordinates_text, Color_White), Color_Bg_Black, 3, 1, 120, 459, current_position.y); + } + if (update_z) { + z = current_position.z; + if ((update_z = axis_should_home(Z_AXIS) && ui.get_blink())) + DWIN_Draw_String(true, DWIN_FONT_MENU, GetColor(eeprom_settings.coordinates_text, Color_White), Color_Bg_Black, 205, 459, F(" -?- ")); + else + DWIN_Draw_FloatValue(true, true, 0, DWIN_FONT_MENU, GetColor(eeprom_settings.coordinates_text, Color_White), Color_Bg_Black, 3, 2, 205, 459, (current_position.z>=0) ? current_position.z : 0); + } + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::Draw_Popup(FSTR_P const line1, FSTR_P const line2, FSTR_P const line3, uint8_t mode, uint8_t icon/*=0*/) { + if (process != Confirm && process != Popup && process != Wait) last_process = process; + if ((process == Menu || process == Wait) && mode == Popup) last_selection = selection; + process = mode; + Clear_Screen(); + DWIN_Draw_Rectangle(0, Color_White, 13, 59, 259, 351); + DWIN_Draw_Rectangle(1, Color_Bg_Window, 14, 60, 258, 350); + const uint8_t ypos = (mode == Popup || mode == Confirm) ? 150 : 230; + if (icon > 0) DWIN_ICON_Show(ICON, icon, 101, 105); + DWIN_Draw_String(true, DWIN_FONT_MENU, Popup_Text_Color, Color_Bg_Window, (272 - 8 * strlen_P(FTOP(line1))) / 2, ypos, line1); + DWIN_Draw_String(true, DWIN_FONT_MENU, Popup_Text_Color, Color_Bg_Window, (272 - 8 * strlen_P(FTOP(line2))) / 2, ypos + 30, line2); + DWIN_Draw_String(true, DWIN_FONT_MENU, Popup_Text_Color, Color_Bg_Window, (272 - 8 * strlen_P(FTOP(line3))) / 2, ypos + 60, line3); + if (mode == Popup) { + selection = 0; + DWIN_Draw_Rectangle(1, Confirm_Color, 26, 280, 125, 317); + DWIN_Draw_Rectangle(1, Cancel_Color, 146, 280, 245, 317); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Window, 39, 290, F("Confirm")); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Window, 165, 290, F("Cancel")); + Popup_Select(); + } + else if (mode == Confirm) { + DWIN_Draw_Rectangle(1, Confirm_Color, 87, 280, 186, 317); + DWIN_Draw_String(false, DWIN_FONT_STAT, Color_White, Color_Bg_Window, 96, 290, F("Continue")); + } +} + +void MarlinUI::kill_screen(FSTR_P const error, FSTR_P const) { + CrealityDWIN.Draw_Popup(F("Printer Kill Reason:"), error, F("Restart Required"), Wait, ICON_BLTouch); +} + +void CrealityDWINClass::Popup_Select() { + const uint16_t c1 = (selection == 0) ? GetColor(eeprom_settings.highlight_box, Color_White) : Color_Bg_Window, + c2 = (selection == 0) ? Color_Bg_Window : GetColor(eeprom_settings.highlight_box, Color_White); + DWIN_Draw_Rectangle(0, c1, 25, 279, 126, 318); + DWIN_Draw_Rectangle(0, c1, 24, 278, 127, 319); + DWIN_Draw_Rectangle(0, c2, 145, 279, 246, 318); + DWIN_Draw_Rectangle(0, c2, 144, 278, 247, 319); +} + +void CrealityDWINClass::Update_Status_Bar(bool refresh/*=false*/) { + static bool new_msg; + static uint8_t msgscrl = 0; + static char lastmsg[64]; + if (strcmp(lastmsg, statusmsg) != 0 || refresh) { + strcpy(lastmsg, statusmsg); + msgscrl = 0; + new_msg = true; + } + size_t len = strlen(statusmsg); + int8_t pos = len; + if (pos > 30) { + pos -= msgscrl; + len = pos; + if (len > 30) + len = 30; + char dispmsg[len + 1]; + if (pos >= 0) { + LOOP_L_N(i, len) dispmsg[i] = statusmsg[i + msgscrl]; + } + else { + LOOP_L_N(i, 30 + pos) dispmsg[i] = ' '; + LOOP_S_L_N(i, 30 + pos, 30) dispmsg[i] = statusmsg[i - (30 + pos)]; + } + dispmsg[len] = '\0'; + if (process == Print) { + DWIN_Draw_Rectangle(1, Color_Grey, 8, 214, DWIN_WIDTH - 8, 238); + const int8_t npos = (DWIN_WIDTH - 30 * MENU_CHR_W) / 2; + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 219, dispmsg); + } + else { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 352, DWIN_WIDTH - 8, 376); + const int8_t npos = (DWIN_WIDTH - 30 * MENU_CHR_W) / 2; + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 357, dispmsg); + } + if (-pos >= 30) msgscrl = 0; + msgscrl++; + } + else { + if (new_msg) { + new_msg = false; + if (process == Print) { + DWIN_Draw_Rectangle(1, Color_Grey, 8, 214, DWIN_WIDTH - 8, 238); + const int8_t npos = (DWIN_WIDTH - strlen(statusmsg) * MENU_CHR_W) / 2; + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 219, statusmsg); + } + else { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 352, DWIN_WIDTH - 8, 376); + const int8_t npos = (DWIN_WIDTH - strlen(statusmsg) * MENU_CHR_W) / 2; + DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 357, statusmsg); + } + } + } +} + +/* Menu Item Config */ + +void CrealityDWINClass::Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw/*=true*/) { + const uint8_t row = item - scrollpos; + #if HAS_LEVELING + static bool level_state; + #endif + + #if HAS_PREHEAT + + #define PREHEAT_BACK 0 + #define PREHEAT_SUBMENU_HOTEND (PREHEAT_BACK + ENABLED(HAS_HOTEND)) + #define PREHEAT_SUBMENU_BED (PREHEAT_SUBMENU_HOTEND + ENABLED(HAS_HEATED_BED)) + #define PREHEAT_SUBMENU_FAN (PREHEAT_SUBMENU_BED + ENABLED(HAS_FAN)) + #define PREHEAT_SUBMENU_TOTAL PREHEAT_SUBMENU_FAN + + auto preheat_submenu = [&](const int index, const uint8_t item, const uint8_t sel) { + switch (item) { + case PREHEAT_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(TempMenu, sel); + break; + #if HAS_HOTEND + case PREHEAT_SUBMENU_HOTEND: + if (draw) { + Draw_Menu_Item(row, ICON_SetEndTemp, F("Hotend")); + Draw_Float(ui.material_preset[index].hotend_temp, row, false, 1); + } + else + Modify_Value(ui.material_preset[index].hotend_temp, MIN_E_TEMP, MAX_E_TEMP, 1); + break; + #endif + #if HAS_HEATED_BED + case PREHEAT_SUBMENU_BED: + if (draw) { + Draw_Menu_Item(row, ICON_SetBedTemp, F("Bed")); + Draw_Float(ui.material_preset[index].bed_temp, row, false, 1); + } + else + Modify_Value(ui.material_preset[index].bed_temp, MIN_BED_TEMP, MAX_BED_TEMP, 1); + break; + #endif + #if HAS_FAN + case PREHEAT_SUBMENU_FAN: + if (draw) { + Draw_Menu_Item(row, ICON_FanSpeed, F("Fan")); + Draw_Float(ui.material_preset[index].fan_speed, row, false, 1); + } + else + Modify_Value(ui.material_preset[index].fan_speed, MIN_FAN_SPEED, MAX_FAN_SPEED, 1); + break; + #endif + } + }; + + #endif + + switch (menu) { + case Prepare: + + #define PREPARE_BACK 0 + #define PREPARE_MOVE (PREPARE_BACK + 1) + #define PREPARE_DISABLE (PREPARE_MOVE + 1) + #define PREPARE_HOME (PREPARE_DISABLE + 1) + #define PREPARE_MANUALLEVEL (PREPARE_HOME + 1) + #define PREPARE_ZOFFSET (PREPARE_MANUALLEVEL + ENABLED(HAS_ZOFFSET_ITEM)) + #define PREPARE_PREHEAT (PREPARE_ZOFFSET + ENABLED(HAS_PREHEAT)) + #define PREPARE_COOLDOWN (PREPARE_PREHEAT + EITHER(HAS_HOTEND, HAS_HEATED_BED)) + #define PREPARE_CHANGEFIL (PREPARE_COOLDOWN + ENABLED(ADVANCED_PAUSE_FEATURE)) + #define PREPARE_CUSTOM_MENU (PREPARE_CHANGEFIL + ENABLED(HAS_CUSTOM_MENU)) + #define PREPARE_TOTAL PREPARE_CUSTOM_MENU + + switch (item) { + case PREPARE_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Main_Menu(1); + break; + case PREPARE_MOVE: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Move"), nullptr, true); + else + Draw_Menu(Move); + break; + case PREPARE_DISABLE: + if (draw) + Draw_Menu_Item(row, ICON_CloseMotor, F("Disable Stepper")); + else + queue.inject(F("M84")); + break; + case PREPARE_HOME: + if (draw) + Draw_Menu_Item(row, ICON_SetHome, F("Homing"), nullptr, true); + else + Draw_Menu(HomeMenu); + break; + case PREPARE_MANUALLEVEL: + if (draw) + Draw_Menu_Item(row, ICON_PrintSize, F("Manual Leveling"), nullptr, true); + else { + if (axes_should_home()) { + Popup_Handler(Home); + gcode.home_all_axes(true); + } + #if HAS_LEVELING + level_state = planner.leveling_active; + set_bed_leveling_enabled(false); + #endif + Draw_Menu(ManualLevel); + } + break; + + #if HAS_ZOFFSET_ITEM + case PREPARE_ZOFFSET: + if (draw) + Draw_Menu_Item(row, ICON_Zoffset, F("Z-Offset"), nullptr, true); + else { + #if HAS_LEVELING + level_state = planner.leveling_active; + set_bed_leveling_enabled(false); + #endif + Draw_Menu(ZOffset); + } + break; + #endif + + #if HAS_PREHEAT + case PREPARE_PREHEAT: + if (draw) + Draw_Menu_Item(row, ICON_Temperature, F("Preheat"), nullptr, true); + else + Draw_Menu(Preheat); + break; + #endif + + #if HAS_HOTEND || HAS_HEATED_BED + case PREPARE_COOLDOWN: + if (draw) + Draw_Menu_Item(row, ICON_Cool, F("Cooldown")); + else + thermalManager.cooldown(); + break; + #endif + + #if HAS_CUSTOM_MENU + case PREPARE_CUSTOM_MENU: + #ifndef CUSTOM_MENU_CONFIG_TITLE + #define CUSTOM_MENU_CONFIG_TITLE "Custom Commands" + #endif + if (draw) + Draw_Menu_Item(row, ICON_Version, F(CUSTOM_MENU_CONFIG_TITLE)); + else + Draw_Menu(MenuCustom); + break; + #endif + + #if ENABLED(ADVANCED_PAUSE_FEATURE) + case PREPARE_CHANGEFIL: + if (draw) { + Draw_Menu_Item(row, ICON_ResumeEEPROM, F("Change Filament") + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + , nullptr, true + #endif + ); + } + else { + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + Draw_Menu(ChangeFilament); + #else + if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp) + Popup_Handler(ETemp); + else { + if (thermalManager.temp_hotend[0].is_below_target(-2)) { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + } + Popup_Handler(FilChange); + sprintf_P(cmd, PSTR("M600 B1 R%i"), thermalManager.temp_hotend[0].target); + gcode.process_subcommands_now(cmd); + } + #endif + } + break; + #endif + } + break; + + case HomeMenu: + + #define HOME_BACK 0 + #define HOME_ALL (HOME_BACK + 1) + #define HOME_X (HOME_ALL + 1) + #define HOME_Y (HOME_X + 1) + #define HOME_Z (HOME_Y + 1) + #define HOME_SET (HOME_Z + 1) + #define HOME_TOTAL HOME_SET + + switch (item) { + case HOME_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Prepare, PREPARE_HOME); + break; + case HOME_ALL: + if (draw) + Draw_Menu_Item(row, ICON_Homing, F("Home All")); + else { + Popup_Handler(Home); + gcode.home_all_axes(true); + Redraw_Menu(); + } + break; + case HOME_X: + if (draw) + Draw_Menu_Item(row, ICON_MoveX, F("Home X")); + else { + Popup_Handler(Home); + gcode.process_subcommands_now(F("G28 X")); + planner.synchronize(); + Redraw_Menu(); + } + break; + case HOME_Y: + if (draw) + Draw_Menu_Item(row, ICON_MoveY, F("Home Y")); + else { + Popup_Handler(Home); + gcode.process_subcommands_now(F("G28 Y")); + planner.synchronize(); + Redraw_Menu(); + } + break; + case HOME_Z: + if (draw) + Draw_Menu_Item(row, ICON_MoveZ, F("Home Z")); + else { + Popup_Handler(Home); + gcode.process_subcommands_now(F("G28 Z")); + planner.synchronize(); + Redraw_Menu(); + } + break; + case HOME_SET: + if (draw) + Draw_Menu_Item(row, ICON_SetHome, F("Set Home Position")); + else { + gcode.process_subcommands_now(F("G92X0Y0Z0")); + AudioFeedback(); + } + break; + } + break; + + case Move: + + #define MOVE_BACK 0 + #define MOVE_X (MOVE_BACK + 1) + #define MOVE_Y (MOVE_X + 1) + #define MOVE_Z (MOVE_Y + 1) + #define MOVE_E (MOVE_Z + ENABLED(HAS_HOTEND)) + #define MOVE_P (MOVE_E + ENABLED(HAS_BED_PROBE)) + #define MOVE_LIVE (MOVE_P + 1) + #define MOVE_TOTAL MOVE_LIVE + + switch (item) { + case MOVE_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else { + #if HAS_BED_PROBE + probe_deployed = false; + probe.set_deployed(probe_deployed); + #endif + Draw_Menu(Prepare, PREPARE_MOVE); + } + break; + case MOVE_X: + if (draw) { + Draw_Menu_Item(row, ICON_MoveX, F("Move X")); + Draw_Float(current_position.x, row, false); + } + else + Modify_Value(current_position.x, X_MIN_POS, X_MAX_POS, 10); + break; + case MOVE_Y: + if (draw) { + Draw_Menu_Item(row, ICON_MoveY, F("Move Y")); + Draw_Float(current_position.y, row); + } + else + Modify_Value(current_position.y, Y_MIN_POS, Y_MAX_POS, 10); + break; + case MOVE_Z: + if (draw) { + Draw_Menu_Item(row, ICON_MoveZ, F("Move Z")); + Draw_Float(current_position.z, row); + } + else + Modify_Value(current_position.z, Z_MIN_POS, Z_MAX_POS, 10); + break; + + #if HAS_HOTEND + case MOVE_E: + if (draw) { + Draw_Menu_Item(row, ICON_Extruder, F("Extruder")); + current_position.e = 0; + sync_plan_position(); + Draw_Float(current_position.e, row); + } + else { + if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp) { + Popup_Handler(ETemp); + } + else { + if (thermalManager.temp_hotend[0].is_below_target(-2)) { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + Redraw_Menu(); + } + current_position.e = 0; + sync_plan_position(); + Modify_Value(current_position.e, -500, 500, 10); + } + } + break; + #endif // HAS_HOTEND + + #if HAS_BED_PROBE + case MOVE_P: + if (draw) { + Draw_Menu_Item(row, ICON_StockConfiguration, F("Probe")); + Draw_Checkbox(row, probe_deployed); + } + else { + probe_deployed = !probe_deployed; + probe.set_deployed(probe_deployed); + Draw_Checkbox(row, probe_deployed); + } + break; + #endif + + case MOVE_LIVE: + if (draw) { + Draw_Menu_Item(row, ICON_Axis, F("Live Movement")); + Draw_Checkbox(row, livemove); + } + else { + livemove = !livemove; + Draw_Checkbox(row, livemove); + } + break; + } + break; + case ManualLevel: + + #define MLEVEL_BACK 0 + #define MLEVEL_PROBE (MLEVEL_BACK + ENABLED(HAS_BED_PROBE)) + #define MLEVEL_BL (MLEVEL_PROBE + 1) + #define MLEVEL_TL (MLEVEL_BL + 1) + #define MLEVEL_TR (MLEVEL_TL + 1) + #define MLEVEL_BR (MLEVEL_TR + 1) + #define MLEVEL_C (MLEVEL_BR + 1) + #define MLEVEL_ZPOS (MLEVEL_C + 1) + #define MLEVEL_TOTAL MLEVEL_ZPOS + + static float mlev_z_pos = 0; + static bool use_probe = false; + + switch (item) { + case MLEVEL_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else { + TERN_(HAS_LEVELING, set_bed_leveling_enabled(level_state)); + Draw_Menu(Prepare, PREPARE_MANUALLEVEL); + } + break; + #if HAS_BED_PROBE + case MLEVEL_PROBE: + if (draw) { + Draw_Menu_Item(row, ICON_Zoffset, F("Use Probe")); + Draw_Checkbox(row, use_probe); + } + else { + use_probe = !use_probe; + Draw_Checkbox(row, use_probe); + if (use_probe) { + Popup_Handler(Level); + corner_avg = 0; + #define PROBE_X_MIN _MAX(0 + corner_pos, X_MIN_POS + probe.offset.x, X_MIN_POS + PROBING_MARGIN) - probe.offset.x + #define PROBE_X_MAX _MIN((X_BED_SIZE + X_MIN_POS) - corner_pos, X_MAX_POS + probe.offset.x, X_MAX_POS - PROBING_MARGIN) - probe.offset.x + #define PROBE_Y_MIN _MAX(0 + corner_pos, Y_MIN_POS + probe.offset.y, Y_MIN_POS + PROBING_MARGIN) - probe.offset.y + #define PROBE_Y_MAX _MIN((Y_BED_SIZE + Y_MIN_POS) - corner_pos, Y_MAX_POS + probe.offset.y, Y_MAX_POS - PROBING_MARGIN) - probe.offset.y + corner_avg += probe.probe_at_point(PROBE_X_MIN, PROBE_Y_MIN, PROBE_PT_RAISE, 0, false); + corner_avg += probe.probe_at_point(PROBE_X_MIN, PROBE_Y_MAX, PROBE_PT_RAISE, 0, false); + corner_avg += probe.probe_at_point(PROBE_X_MAX, PROBE_Y_MAX, PROBE_PT_RAISE, 0, false); + corner_avg += probe.probe_at_point(PROBE_X_MAX, PROBE_Y_MIN, PROBE_PT_STOW, 0, false); + corner_avg /= 4; + Redraw_Menu(); + } + } + break; + #endif + case MLEVEL_BL: + if (draw) + Draw_Menu_Item(row, ICON_AxisBL, F("Bottom Left")); + else { + Popup_Handler(MoveWait); + if (use_probe) { + #if HAS_BED_PROBE + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MIN, 1, 3, str_1), dtostrf(PROBE_Y_MIN, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Popup_Handler(ManualProbing); + #endif + } + else { + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s\nG0 F300 Z%s"), dtostrf(corner_pos, 1, 3, str_1), dtostrf(corner_pos, 1, 3, str_2), dtostrf(mlev_z_pos, 1, 3, str_3)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case MLEVEL_TL: + if (draw) + Draw_Menu_Item(row, ICON_AxisTL, F("Top Left")); + else { + Popup_Handler(MoveWait); + if (use_probe) { + #if HAS_BED_PROBE + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MIN, 1, 3, str_1), dtostrf(PROBE_Y_MAX, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Popup_Handler(ManualProbing); + #endif + } + else { + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s\nG0 F300 Z%s"), dtostrf(corner_pos, 1, 3, str_1), dtostrf((Y_BED_SIZE + Y_MIN_POS) - corner_pos, 1, 3, str_2), dtostrf(mlev_z_pos, 1, 3, str_3)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case MLEVEL_TR: + if (draw) + Draw_Menu_Item(row, ICON_AxisTR, F("Top Right")); + else { + Popup_Handler(MoveWait); + if (use_probe) { + #if HAS_BED_PROBE + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MAX, 1, 3, str_1), dtostrf(PROBE_Y_MAX, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Popup_Handler(ManualProbing); + #endif + } + else { + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s\nG0 F300 Z%s"), dtostrf((X_BED_SIZE + X_MIN_POS) - corner_pos, 1, 3, str_1), dtostrf((Y_BED_SIZE + Y_MIN_POS) - corner_pos, 1, 3, str_2), dtostrf(mlev_z_pos, 1, 3, str_3)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case MLEVEL_BR: + if (draw) + Draw_Menu_Item(row, ICON_AxisBR, F("Bottom Right")); + else { + Popup_Handler(MoveWait); + if (use_probe) { + #if HAS_BED_PROBE + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MAX, 1, 3, str_1), dtostrf(PROBE_Y_MIN, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Popup_Handler(ManualProbing); + #endif + } + else { + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s\nG0 F300 Z%s"), dtostrf((X_BED_SIZE + X_MIN_POS) - corner_pos, 1, 3, str_1), dtostrf(corner_pos, 1, 3, str_2), dtostrf(mlev_z_pos, 1, 3, str_3)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case MLEVEL_C: + if (draw) + Draw_Menu_Item(row, ICON_AxisC, F("Center")); + else { + Popup_Handler(MoveWait); + if (use_probe) { + #if HAS_BED_PROBE + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(X_MAX_POS / 2.0f - probe.offset.x, 1, 3, str_1), dtostrf(Y_MAX_POS / 2.0f - probe.offset.y, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Popup_Handler(ManualProbing); + #endif + } + else { + sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s\nG0 F300 Z%s"), dtostrf((X_BED_SIZE + X_MIN_POS) / 2.0f, 1, 3, str_1), dtostrf((Y_BED_SIZE + Y_MIN_POS) / 2.0f, 1, 3, str_2), dtostrf(mlev_z_pos, 1, 3, str_3)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case MLEVEL_ZPOS: + if (draw) { + Draw_Menu_Item(row, ICON_SetZOffset, F("Z Position")); + Draw_Float(mlev_z_pos, row, false, 100); + } + else + Modify_Value(mlev_z_pos, 0, MAX_Z_OFFSET, 100); + break; + } + break; + #if HAS_ZOFFSET_ITEM + case ZOffset: + + #define ZOFFSET_BACK 0 + #define ZOFFSET_HOME (ZOFFSET_BACK + 1) + #define ZOFFSET_MODE (ZOFFSET_HOME + 1) + #define ZOFFSET_OFFSET (ZOFFSET_MODE + 1) + #define ZOFFSET_UP (ZOFFSET_OFFSET + 1) + #define ZOFFSET_DOWN (ZOFFSET_UP + 1) + #define ZOFFSET_SAVE (ZOFFSET_DOWN + ENABLED(EEPROM_SETTINGS)) + #define ZOFFSET_TOTAL ZOFFSET_SAVE + + switch (item) { + case ZOFFSET_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else { + liveadjust = false; + TERN_(HAS_LEVELING, set_bed_leveling_enabled(level_state)); + Draw_Menu(Prepare, PREPARE_ZOFFSET); + } + break; + case ZOFFSET_HOME: + if (draw) + Draw_Menu_Item(row, ICON_Homing, F("Home Z Axis")); + else { + Popup_Handler(Home); + gcode.process_subcommands_now(F("G28 Z")); + Popup_Handler(MoveWait); + #if ENABLED(Z_SAFE_HOMING) + planner.synchronize(); + sprintf_P(cmd, PSTR("G0 F4000 X%s Y%s"), dtostrf(Z_SAFE_HOMING_X_POINT, 1, 3, str_1), dtostrf(Z_SAFE_HOMING_Y_POINT, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + #else + gcode.process_subcommands_now(F("G0 F4000 X117.5 Y117.5")); + #endif + gcode.process_subcommands_now(F("G0 F300 Z0")); + planner.synchronize(); + Redraw_Menu(); + } + break; + case ZOFFSET_MODE: + if (draw) { + Draw_Menu_Item(row, ICON_Zoffset, F("Live Adjustment")); + Draw_Checkbox(row, liveadjust); + } + else { + if (!liveadjust) { + if (axes_should_home()) { + Popup_Handler(Home); + gcode.home_all_axes(true); + } + Popup_Handler(MoveWait); + #if ENABLED(Z_SAFE_HOMING) + planner.synchronize(); + sprintf_P(cmd, PSTR("G0 F4000 X%s Y%s"), dtostrf(Z_SAFE_HOMING_X_POINT, 1, 3, str_1), dtostrf(Z_SAFE_HOMING_Y_POINT, 1, 3, str_2)); + gcode.process_subcommands_now(cmd); + #else + gcode.process_subcommands_now(F("G0 F4000 X117.5 Y117.5")); + #endif + gcode.process_subcommands_now(F("G0 F300 Z0")); + planner.synchronize(); + Redraw_Menu(); + } + liveadjust = !liveadjust; + Draw_Checkbox(row, liveadjust); + } + break; + case ZOFFSET_OFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_SetZOffset, F("Z Offset")); + Draw_Float(zoffsetvalue, row, false, 100); + } + else + Modify_Value(zoffsetvalue, MIN_Z_OFFSET, MAX_Z_OFFSET, 100); + break; + case ZOFFSET_UP: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Microstep Up")); + else { + if (zoffsetvalue < MAX_Z_OFFSET) { + if (liveadjust) { + gcode.process_subcommands_now(F("M290 Z0.01")); + planner.synchronize(); + } + zoffsetvalue += 0.01; + Draw_Float(zoffsetvalue, row - 1, false, 100); + } + } + break; + case ZOFFSET_DOWN: + if (draw) + Draw_Menu_Item(row, ICON_AxisD, F("Microstep Down")); + else { + if (zoffsetvalue > MIN_Z_OFFSET) { + if (liveadjust) { + gcode.process_subcommands_now(F("M290 Z-0.01")); + planner.synchronize(); + } + zoffsetvalue -= 0.01; + Draw_Float(zoffsetvalue, row - 2, false, 100); + } + } + break; + #if ENABLED(EEPROM_SETTINGS) + case ZOFFSET_SAVE: + if (draw) + Draw_Menu_Item(row, ICON_WriteEEPROM, F("Save")); + else + AudioFeedback(settings.save()); + break; + #endif + } + break; + #endif + + #if HAS_PREHEAT + case Preheat: { + #define PREHEAT_MODE (PREHEAT_BACK + 1) + #define PREHEAT_1 (PREHEAT_MODE + 1) + #define PREHEAT_2 (PREHEAT_1 + (PREHEAT_COUNT >= 2)) + #define PREHEAT_3 (PREHEAT_2 + (PREHEAT_COUNT >= 3)) + #define PREHEAT_4 (PREHEAT_3 + (PREHEAT_COUNT >= 4)) + #define PREHEAT_5 (PREHEAT_4 + (PREHEAT_COUNT >= 5)) + #define PREHEAT_TOTAL PREHEAT_5 + + auto do_preheat = [](const uint8_t m) { + thermalManager.cooldown(); + if (preheatmode == 0 || preheatmode == 1) { ui.preheat_hotend_and_fan(m); } + if (preheatmode == 0 || preheatmode == 2) ui.preheat_bed(m); + }; + + switch (item) { + case PREHEAT_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Prepare, PREPARE_PREHEAT); + break; + + case PREHEAT_MODE: + if (draw) { + Draw_Menu_Item(row, ICON_Homing, F("Preheat Mode")); + Draw_Option(preheatmode, preheat_modes, row); + } + else + Modify_Option(preheatmode, preheat_modes, 2); + break; + + #define _PREHEAT_CASE(N) \ + case PREHEAT_##N: { \ + if (draw) Draw_Menu_Item(row, ICON_Temperature, F(PREHEAT_## N ##_LABEL)); \ + else do_preheat(N - 1); \ + } break; + + REPEAT_1(PREHEAT_COUNT, _PREHEAT_CASE) + } + } break; + #endif // HAS_PREHEAT + + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + case ChangeFilament: + + #define CHANGEFIL_BACK 0 + #define CHANGEFIL_LOAD (CHANGEFIL_BACK + 1) + #define CHANGEFIL_UNLOAD (CHANGEFIL_LOAD + 1) + #define CHANGEFIL_CHANGE (CHANGEFIL_UNLOAD + 1) + #define CHANGEFIL_TOTAL CHANGEFIL_CHANGE + + switch (item) { + case CHANGEFIL_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Prepare, PREPARE_CHANGEFIL); + break; + case CHANGEFIL_LOAD: + if (draw) + Draw_Menu_Item(row, ICON_WriteEEPROM, F("Load Filament")); + else { + if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp) + Popup_Handler(ETemp); + else { + if (thermalManager.temp_hotend[0].is_below_target(-2)) { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + } + Popup_Handler(FilLoad); + gcode.process_subcommands_now(F("M701")); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case CHANGEFIL_UNLOAD: + if (draw) + Draw_Menu_Item(row, ICON_ReadEEPROM, F("Unload Filament")); + else { + if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp) { + Popup_Handler(ETemp); + } + else { + if (thermalManager.temp_hotend[0].is_below_target(-2)) { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + } + Popup_Handler(FilLoad, true); + gcode.process_subcommands_now(F("M702")); + planner.synchronize(); + Redraw_Menu(); + } + } + break; + case CHANGEFIL_CHANGE: + if (draw) + Draw_Menu_Item(row, ICON_ResumeEEPROM, F("Change Filament")); + else { + if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp) + Popup_Handler(ETemp); + else { + if (thermalManager.temp_hotend[0].is_below_target(-2)) { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + } + Popup_Handler(FilChange); + sprintf_P(cmd, PSTR("M600 B1 R%i"), thermalManager.temp_hotend[0].target); + gcode.process_subcommands_now(cmd); + } + } + break; + } + break; + #endif // FILAMENT_LOAD_UNLOAD_GCODES + + #if HAS_CUSTOM_MENU + + case MenuCustom: + + #define CUSTOM_MENU_BACK 0 + #define CUSTOM_MENU_1 1 + #define CUSTOM_MENU_2 2 + #define CUSTOM_MENU_3 3 + #define CUSTOM_MENU_4 4 + #define CUSTOM_MENU_5 5 + #define CUSTOM_MENU_TOTAL CUSTOM_MENU_COUNT + + switch (item) { + case CUSTOM_MENU_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Prepare, PREPARE_CUSTOM_MENU); + break; + + #if CUSTOM_MENU_COUNT >= 1 + case CUSTOM_MENU_1: + if (draw) + Draw_Menu_Item(row, ICON_Info, F(CONFIG_MENU_ITEM_1_DESC)); + else { + Popup_Handler(Custom); + //queue.inject(F(CONFIG_MENU_ITEM_1_GCODE)); // Old code + gcode.process_subcommands_now(F(CONFIG_MENU_ITEM_1_GCODE)); + planner.synchronize(); + Redraw_Menu(); + #if ENABLED(CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK) + AudioFeedback(); + #endif + #ifdef CUSTOM_MENU_CONFIG_SCRIPT_RETURN + queue.inject(F(CUSTOM_MENU_CONFIG_SCRIPT_DONE)); + #endif + } + break; + #endif + + #if CUSTOM_MENU_COUNT >= 2 + case CUSTOM_MENU_2: + if (draw) + Draw_Menu_Item(row, ICON_Info, F(CONFIG_MENU_ITEM_2_DESC)); + else { + Popup_Handler(Custom); + gcode.process_subcommands_now(F(CONFIG_MENU_ITEM_2_GCODE)); + planner.synchronize(); + Redraw_Menu(); + #if ENABLED(CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK) + AudioFeedback(); + #endif + #ifdef CUSTOM_MENU_CONFIG_SCRIPT_RETURN + queue.inject(F(CUSTOM_MENU_CONFIG_SCRIPT_DONE)); + #endif + } + break; + #endif + + #if CUSTOM_MENU_COUNT >= 3 + case CUSTOM_MENU_3: + if (draw) + Draw_Menu_Item(row, ICON_Info, F(CONFIG_MENU_ITEM_3_DESC)); + else { + Popup_Handler(Custom); + gcode.process_subcommands_now(F(CONFIG_MENU_ITEM_3_GCODE)); + planner.synchronize(); + Redraw_Menu(); + #if ENABLED(CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK) + AudioFeedback(); + #endif + #ifdef CUSTOM_MENU_CONFIG_SCRIPT_RETURN + queue.inject(F(CUSTOM_MENU_CONFIG_SCRIPT_DONE)); + #endif + } + break; + #endif + + #if CUSTOM_MENU_COUNT >= 4 + case CUSTOM_MENU_4: + if (draw) + Draw_Menu_Item(row, ICON_Info, F(CONFIG_MENU_ITEM_4_DESC)); + else { + Popup_Handler(Custom); + gcode.process_subcommands_now(F(CONFIG_MENU_ITEM_4_GCODE)); + planner.synchronize(); + Redraw_Menu(); + #if ENABLED(CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK) + AudioFeedback(); + #endif + #ifdef CUSTOM_MENU_CONFIG_SCRIPT_RETURN + queue.inject(F(CUSTOM_MENU_CONFIG_SCRIPT_DONE)); + #endif + } + break; + #endif + + #if CUSTOM_MENU_COUNT >= 5 + case CUSTOM_MENU_5: + if (draw) + Draw_Menu_Item(row, ICON_Info, F(CONFIG_MENU_ITEM_5_DESC)); + else { + Popup_Handler(Custom); + gcode.process_subcommands_now(F(CONFIG_MENU_ITEM_5_GCODE)); + planner.synchronize(); + Redraw_Menu(); + #if ENABLED(CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK) + AudioFeedback(); + #endif + #ifdef CUSTOM_MENU_CONFIG_SCRIPT_RETURN + queue.inject(F(CUSTOM_MENU_CONFIG_SCRIPT_DONE)); + #endif + } + break; + #endif // Custom Menu + } + break; + + #endif // HAS_CUSTOM_MENU + + case Control: + + #define CONTROL_BACK 0 + #define CONTROL_TEMP (CONTROL_BACK + 1) + #define CONTROL_MOTION (CONTROL_TEMP + 1) + #define CONTROL_VISUAL (CONTROL_MOTION + 1) + #define CONTROL_ADVANCED (CONTROL_VISUAL + 1) + #define CONTROL_SAVE (CONTROL_ADVANCED + ENABLED(EEPROM_SETTINGS)) + #define CONTROL_RESTORE (CONTROL_SAVE + ENABLED(EEPROM_SETTINGS)) + #define CONTROL_RESET (CONTROL_RESTORE + ENABLED(EEPROM_SETTINGS)) + #define CONTROL_INFO (CONTROL_RESET + 1) + #define CONTROL_TOTAL CONTROL_INFO + + switch (item) { + case CONTROL_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Main_Menu(2); + break; + case CONTROL_TEMP: + if (draw) + Draw_Menu_Item(row, ICON_Temperature, F("Temperature"), nullptr, true); + else + Draw_Menu(TempMenu); + break; + case CONTROL_MOTION: + if (draw) + Draw_Menu_Item(row, ICON_Motion, F("Motion"), nullptr, true); + else + Draw_Menu(Motion); + break; + case CONTROL_VISUAL: + if (draw) + Draw_Menu_Item(row, ICON_PrintSize, F("Visual"), nullptr, true); + else + Draw_Menu(Visual); + break; + case CONTROL_ADVANCED: + if (draw) + Draw_Menu_Item(row, ICON_Version, F("Advanced"), nullptr, true); + else + Draw_Menu(Advanced); + break; + #if ENABLED(EEPROM_SETTINGS) + case CONTROL_SAVE: + if (draw) + Draw_Menu_Item(row, ICON_WriteEEPROM, F("Store Settings")); + else + AudioFeedback(settings.save()); + break; + case CONTROL_RESTORE: + if (draw) + Draw_Menu_Item(row, ICON_ReadEEPROM, F("Restore Settings")); + else + AudioFeedback(settings.load()); + break; + case CONTROL_RESET: + if (draw) + Draw_Menu_Item(row, ICON_Temperature, F("Reset to Defaults")); + else { + settings.reset(); + AudioFeedback(); + } + break; + #endif + case CONTROL_INFO: + if (draw) + Draw_Menu_Item(row, ICON_Info, F("Info")); + else + Draw_Menu(Info); + break; + } + break; + + case TempMenu: + + #define TEMP_BACK 0 + #define TEMP_HOTEND (TEMP_BACK + ENABLED(HAS_HOTEND)) + #define TEMP_BED (TEMP_HOTEND + ENABLED(HAS_HEATED_BED)) + #define TEMP_FAN (TEMP_BED + ENABLED(HAS_FAN)) + #define TEMP_PID (TEMP_FAN + ANY(HAS_HOTEND, HAS_HEATED_BED)) + #define TEMP_PREHEAT1 (TEMP_PID + (PREHEAT_COUNT >= 1)) + #define TEMP_PREHEAT2 (TEMP_PREHEAT1 + (PREHEAT_COUNT >= 2)) + #define TEMP_PREHEAT3 (TEMP_PREHEAT2 + (PREHEAT_COUNT >= 3)) + #define TEMP_PREHEAT4 (TEMP_PREHEAT3 + (PREHEAT_COUNT >= 4)) + #define TEMP_PREHEAT5 (TEMP_PREHEAT4 + (PREHEAT_COUNT >= 5)) + #define TEMP_TOTAL TEMP_PREHEAT5 + + switch (item) { + case TEMP_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Control, CONTROL_TEMP); + break; + #if HAS_HOTEND + case TEMP_HOTEND: + if (draw) { + Draw_Menu_Item(row, ICON_SetEndTemp, F("Hotend")); + Draw_Float(thermalManager.temp_hotend[0].target, row, false, 1); + } + else + Modify_Value(thermalManager.temp_hotend[0].target, MIN_E_TEMP, MAX_E_TEMP, 1); + break; + #endif + #if HAS_HEATED_BED + case TEMP_BED: + if (draw) { + Draw_Menu_Item(row, ICON_SetBedTemp, F("Bed")); + Draw_Float(thermalManager.temp_bed.target, row, false, 1); + } + else + Modify_Value(thermalManager.temp_bed.target, MIN_BED_TEMP, MAX_BED_TEMP, 1); + break; + #endif + #if HAS_FAN + case TEMP_FAN: + if (draw) { + Draw_Menu_Item(row, ICON_FanSpeed, F("Fan")); + Draw_Float(thermalManager.fan_speed[0], row, false, 1); + } + else + Modify_Value(thermalManager.fan_speed[0], MIN_FAN_SPEED, MAX_FAN_SPEED, 1); + break; + #endif + #if HAS_HOTEND || HAS_HEATED_BED + case TEMP_PID: + if (draw) + Draw_Menu_Item(row, ICON_Step, F("PID"), nullptr, true); + else + Draw_Menu(PID); + break; + #endif + + #define _TEMP_PREHEAT_CASE(N) \ + case TEMP_PREHEAT##N: { \ + if (draw) Draw_Menu_Item(row, ICON_Step, F(PREHEAT_## N ##_LABEL), nullptr, true); \ + else Draw_Menu(Preheat##N); \ + } break; + + REPEAT_1(PREHEAT_COUNT, _TEMP_PREHEAT_CASE) + } + break; + + #if HAS_HOTEND || HAS_HEATED_BED + case PID: + + #define PID_BACK 0 + #define PID_HOTEND (PID_BACK + ENABLED(HAS_HOTEND)) + #define PID_BED (PID_HOTEND + ENABLED(HAS_HEATED_BED)) + #define PID_CYCLES (PID_BED + 1) + #define PID_TOTAL PID_CYCLES + + static uint8_t PID_cycles = 5; + + switch (item) { + case PID_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(TempMenu, TEMP_PID); + break; + #if HAS_HOTEND + case PID_HOTEND: + if (draw) + Draw_Menu_Item(row, ICON_HotendTemp, F("Hotend"), nullptr, true); + else + Draw_Menu(HotendPID); + break; + #endif + #if HAS_HEATED_BED + case PID_BED: + if (draw) + Draw_Menu_Item(row, ICON_BedTemp, F("Bed"), nullptr, true); + else + Draw_Menu(BedPID); + break; + #endif + case PID_CYCLES: + if (draw) { + Draw_Menu_Item(row, ICON_FanSpeed, F("Cycles")); + Draw_Float(PID_cycles, row, false, 1); + } + else + Modify_Value(PID_cycles, 3, 50, 1); + break; + } + break; + #endif // HAS_HOTEND || HAS_HEATED_BED + + #if HAS_HOTEND + case HotendPID: + + #define HOTENDPID_BACK 0 + #define HOTENDPID_TUNE (HOTENDPID_BACK + 1) + #define HOTENDPID_TEMP (HOTENDPID_TUNE + 1) + #define HOTENDPID_KP (HOTENDPID_TEMP + 1) + #define HOTENDPID_KI (HOTENDPID_KP + 1) + #define HOTENDPID_KD (HOTENDPID_KI + 1) + #define HOTENDPID_TOTAL HOTENDPID_KD + + static uint16_t PID_e_temp = 180; + + switch (item) { + case HOTENDPID_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(PID, PID_HOTEND); + break; + case HOTENDPID_TUNE: + if (draw) + Draw_Menu_Item(row, ICON_HotendTemp, F("Autotune")); + else { + Popup_Handler(PIDWait); + sprintf_P(cmd, PSTR("M303 E0 C%i S%i U1"), PID_cycles, PID_e_temp); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + break; + case HOTENDPID_TEMP: + if (draw) { + Draw_Menu_Item(row, ICON_Temperature, F("Temperature")); + Draw_Float(PID_e_temp, row, false, 1); + } + else + Modify_Value(PID_e_temp, MIN_E_TEMP, MAX_E_TEMP, 1); + break; + case HOTENDPID_KP: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("Kp Value")); + Draw_Float(thermalManager.temp_hotend[0].pid.Kp, row, false, 100); + } + else + Modify_Value(thermalManager.temp_hotend[0].pid.Kp, 0, 5000, 100, thermalManager.updatePID); + break; + case HOTENDPID_KI: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("Ki Value")); + Draw_Float(unscalePID_i(thermalManager.temp_hotend[0].pid.Ki), row, false, 100); + } + else + Modify_Value(thermalManager.temp_hotend[0].pid.Ki, 0, 5000, 100, thermalManager.updatePID); + break; + case HOTENDPID_KD: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("Kd Value")); + Draw_Float(unscalePID_d(thermalManager.temp_hotend[0].pid.Kd), row, false, 100); + } + else + Modify_Value(thermalManager.temp_hotend[0].pid.Kd, 0, 5000, 100, thermalManager.updatePID); + break; + } + break; + #endif // HAS_HOTEND + + #if HAS_HEATED_BED + case BedPID: + + #define BEDPID_BACK 0 + #define BEDPID_TUNE (BEDPID_BACK + 1) + #define BEDPID_TEMP (BEDPID_TUNE + 1) + #define BEDPID_KP (BEDPID_TEMP + 1) + #define BEDPID_KI (BEDPID_KP + 1) + #define BEDPID_KD (BEDPID_KI + 1) + #define BEDPID_TOTAL BEDPID_KD + + static uint16_t PID_bed_temp = 60; + + switch (item) { + case BEDPID_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(PID, PID_BED); + break; + case BEDPID_TUNE: + if (draw) + Draw_Menu_Item(row, ICON_HotendTemp, F("Autotune")); + else { + Popup_Handler(PIDWait); + sprintf_P(cmd, PSTR("M303 E-1 C%i S%i U1"), PID_cycles, PID_bed_temp); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + Redraw_Menu(); + } + break; + case BEDPID_TEMP: + if (draw) { + Draw_Menu_Item(row, ICON_Temperature, F("Temperature")); + Draw_Float(PID_bed_temp, row, false, 1); + } + else + Modify_Value(PID_bed_temp, MIN_BED_TEMP, MAX_BED_TEMP, 1); + break; + case BEDPID_KP: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("Kp Value")); + Draw_Float(thermalManager.temp_bed.pid.Kp, row, false, 100); + } + else { + Modify_Value(thermalManager.temp_bed.pid.Kp, 0, 5000, 100, thermalManager.updatePID); + } + break; + case BEDPID_KI: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("Ki Value")); + Draw_Float(unscalePID_i(thermalManager.temp_bed.pid.Ki), row, false, 100); + } + else + Modify_Value(thermalManager.temp_bed.pid.Ki, 0, 5000, 100, thermalManager.updatePID); + break; + case BEDPID_KD: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("Kd Value")); + Draw_Float(unscalePID_d(thermalManager.temp_bed.pid.Kd), row, false, 100); + } + else + Modify_Value(thermalManager.temp_bed.pid.Kd, 0, 5000, 100, thermalManager.updatePID); + break; + } + break; + #endif // HAS_HEATED_BED + + #if HAS_PREHEAT + #define _PREHEAT_SUBMENU_CASE(N) case Preheat##N: preheat_submenu((N) - 1, item, TEMP_PREHEAT##N); break; + REPEAT_1(PREHEAT_COUNT, _PREHEAT_SUBMENU_CASE) + #endif + + case Motion: + + #define MOTION_BACK 0 + #define MOTION_HOMEOFFSETS (MOTION_BACK + 1) + #define MOTION_SPEED (MOTION_HOMEOFFSETS + 1) + #define MOTION_ACCEL (MOTION_SPEED + 1) + #define MOTION_JERK (MOTION_ACCEL + ENABLED(HAS_CLASSIC_JERK)) + #define MOTION_STEPS (MOTION_JERK + 1) + #define MOTION_FLOW (MOTION_STEPS + ENABLED(HAS_HOTEND)) + #define MOTION_TOTAL MOTION_FLOW + + switch (item) { + case MOTION_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Control, CONTROL_MOTION); + break; + case MOTION_HOMEOFFSETS: + if (draw) + Draw_Menu_Item(row, ICON_SetHome, F("Home Offsets"), nullptr, true); + else + Draw_Menu(HomeOffsets); + break; + case MOTION_SPEED: + if (draw) + Draw_Menu_Item(row, ICON_MaxSpeed, F("Max Speed"), nullptr, true); + else + Draw_Menu(MaxSpeed); + break; + case MOTION_ACCEL: + if (draw) + Draw_Menu_Item(row, ICON_MaxAccelerated, F("Max Acceleration"), nullptr, true); + else + Draw_Menu(MaxAcceleration); + break; + #if HAS_CLASSIC_JERK + case MOTION_JERK: + if (draw) + Draw_Menu_Item(row, ICON_MaxJerk, F("Max Jerk"), nullptr, true); + else + Draw_Menu(MaxJerk); + break; + #endif + case MOTION_STEPS: + if (draw) + Draw_Menu_Item(row, ICON_Step, F("Steps/mm"), nullptr, true); + else + Draw_Menu(Steps); + break; + #if HAS_HOTEND + case MOTION_FLOW: + if (draw) { + Draw_Menu_Item(row, ICON_Speed, F("Flow Rate")); + Draw_Float(planner.flow_percentage[0], row, false, 1); + } + else + Modify_Value(planner.flow_percentage[0], MIN_FLOW_RATE, MAX_FLOW_RATE, 1); + break; + #endif + } + break; + + case HomeOffsets: + + #define HOMEOFFSETS_BACK 0 + #define HOMEOFFSETS_XOFFSET (HOMEOFFSETS_BACK + 1) + #define HOMEOFFSETS_YOFFSET (HOMEOFFSETS_XOFFSET + 1) + #define HOMEOFFSETS_TOTAL HOMEOFFSETS_YOFFSET + + switch (item) { + case HOMEOFFSETS_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Motion, MOTION_HOMEOFFSETS); + break; + case HOMEOFFSETS_XOFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_StepX, F("X Offset")); + Draw_Float(home_offset.x, row, false, 100); + } + else + Modify_Value(home_offset.x, -MAX_XY_OFFSET, MAX_XY_OFFSET, 100); + break; + case HOMEOFFSETS_YOFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_StepY, F("Y Offset")); + Draw_Float(home_offset.y, row, false, 100); + } + else + Modify_Value(home_offset.y, -MAX_XY_OFFSET, MAX_XY_OFFSET, 100); + break; + } + break; + case MaxSpeed: + + #define SPEED_BACK 0 + #define SPEED_X (SPEED_BACK + 1) + #define SPEED_Y (SPEED_X + 1) + #define SPEED_Z (SPEED_Y + 1) + #define SPEED_E (SPEED_Z + ENABLED(HAS_HOTEND)) + #define SPEED_TOTAL SPEED_E + + switch (item) { + case SPEED_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Motion, MOTION_SPEED); + break; + case SPEED_X: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedX, F("X Axis")); + Draw_Float(planner.settings.max_feedrate_mm_s[X_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_feedrate_mm_s[X_AXIS], 0, default_max_feedrate[X_AXIS] * 2, 1); + break; + + #if HAS_Y_AXIS + case SPEED_Y: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedY, F("Y Axis")); + Draw_Float(planner.settings.max_feedrate_mm_s[Y_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_feedrate_mm_s[Y_AXIS], 0, default_max_feedrate[Y_AXIS] * 2, 1); + break; + #endif + + #if HAS_Z_AXIS + case SPEED_Z: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedZ, F("Z Axis")); + Draw_Float(planner.settings.max_feedrate_mm_s[Z_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_feedrate_mm_s[Z_AXIS], 0, default_max_feedrate[Z_AXIS] * 2, 1); + break; + #endif + + #if HAS_HOTEND + case SPEED_E: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedE, F("Extruder")); + Draw_Float(planner.settings.max_feedrate_mm_s[E_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_feedrate_mm_s[E_AXIS], 0, default_max_feedrate[E_AXIS] * 2, 1); + break; + #endif + } + break; + + case MaxAcceleration: + + #define ACCEL_BACK 0 + #define ACCEL_X (ACCEL_BACK + 1) + #define ACCEL_Y (ACCEL_X + 1) + #define ACCEL_Z (ACCEL_Y + 1) + #define ACCEL_E (ACCEL_Z + ENABLED(HAS_HOTEND)) + #define ACCEL_TOTAL ACCEL_E + + switch (item) { + case ACCEL_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Motion, MOTION_ACCEL); + break; + case ACCEL_X: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccX, F("X Axis")); + Draw_Float(planner.settings.max_acceleration_mm_per_s2[X_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_acceleration_mm_per_s2[X_AXIS], 0, default_max_acceleration[X_AXIS] * 2, 1); + break; + case ACCEL_Y: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccY, F("Y Axis")); + Draw_Float(planner.settings.max_acceleration_mm_per_s2[Y_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_acceleration_mm_per_s2[Y_AXIS], 0, default_max_acceleration[Y_AXIS] * 2, 1); + break; + case ACCEL_Z: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccZ, F("Z Axis")); + Draw_Float(planner.settings.max_acceleration_mm_per_s2[Z_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_acceleration_mm_per_s2[Z_AXIS], 0, default_max_acceleration[Z_AXIS] * 2, 1); + break; + #if HAS_HOTEND + case ACCEL_E: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccE, F("Extruder")); + Draw_Float(planner.settings.max_acceleration_mm_per_s2[E_AXIS], row, false, 1); + } + else + Modify_Value(planner.settings.max_acceleration_mm_per_s2[E_AXIS], 0, default_max_acceleration[E_AXIS] * 2, 1); + break; + #endif + } + break; + #if HAS_CLASSIC_JERK + case MaxJerk: + + #define JERK_BACK 0 + #define JERK_X (JERK_BACK + 1) + #define JERK_Y (JERK_X + 1) + #define JERK_Z (JERK_Y + 1) + #define JERK_E (JERK_Z + ENABLED(HAS_HOTEND)) + #define JERK_TOTAL JERK_E + + switch (item) { + case JERK_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Motion, MOTION_JERK); + break; + case JERK_X: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedJerkX, F("X Axis")); + Draw_Float(planner.max_jerk[X_AXIS], row, false, 10); + } + else + Modify_Value(planner.max_jerk[X_AXIS], 0, default_max_jerk[X_AXIS] * 2, 10); + break; + case JERK_Y: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedJerkY, F("Y Axis")); + Draw_Float(planner.max_jerk[Y_AXIS], row, false, 10); + } + else + Modify_Value(planner.max_jerk[Y_AXIS], 0, default_max_jerk[Y_AXIS] * 2, 10); + break; + case JERK_Z: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedJerkZ, F("Z Axis")); + Draw_Float(planner.max_jerk[Z_AXIS], row, false, 10); + } + else + Modify_Value(planner.max_jerk[Z_AXIS], 0, default_max_jerk[Z_AXIS] * 2, 10); + break; + #if HAS_HOTEND + case JERK_E: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeedJerkE, F("Extruder")); + Draw_Float(planner.max_jerk[E_AXIS], row, false, 10); + } + else + Modify_Value(planner.max_jerk[E_AXIS], 0, default_max_jerk[E_AXIS] * 2, 10); + break; + #endif + } + break; + #endif + case Steps: + + #define STEPS_BACK 0 + #define STEPS_X (STEPS_BACK + 1) + #define STEPS_Y (STEPS_X + 1) + #define STEPS_Z (STEPS_Y + 1) + #define STEPS_E (STEPS_Z + ENABLED(HAS_HOTEND)) + #define STEPS_TOTAL STEPS_E + + switch (item) { + case STEPS_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Motion, MOTION_STEPS); + break; + case STEPS_X: + if (draw) { + Draw_Menu_Item(row, ICON_StepX, F("X Axis")); + Draw_Float(planner.settings.axis_steps_per_mm[X_AXIS], row, false, 10); + } + else + Modify_Value(planner.settings.axis_steps_per_mm[X_AXIS], 0, default_steps[X_AXIS] * 2, 10); + break; + case STEPS_Y: + if (draw) { + Draw_Menu_Item(row, ICON_StepY, F("Y Axis")); + Draw_Float(planner.settings.axis_steps_per_mm[Y_AXIS], row, false, 10); + } + else + Modify_Value(planner.settings.axis_steps_per_mm[Y_AXIS], 0, default_steps[Y_AXIS] * 2, 10); + break; + case STEPS_Z: + if (draw) { + Draw_Menu_Item(row, ICON_StepZ, F("Z Axis")); + Draw_Float(planner.settings.axis_steps_per_mm[Z_AXIS], row, false, 10); + } + else + Modify_Value(planner.settings.axis_steps_per_mm[Z_AXIS], 0, default_steps[Z_AXIS] * 2, 10); + break; + #if HAS_HOTEND + case STEPS_E: + if (draw) { + Draw_Menu_Item(row, ICON_StepE, F("Extruder")); + Draw_Float(planner.settings.axis_steps_per_mm[E_AXIS], row, false, 10); + } + else + Modify_Value(planner.settings.axis_steps_per_mm[E_AXIS], 0, 1000, 10); + break; + #endif + } + break; + + case Visual: + + #define VISUAL_BACK 0 + #define VISUAL_BACKLIGHT (VISUAL_BACK + 1) + #define VISUAL_BRIGHTNESS (VISUAL_BACKLIGHT + 1) + #define VISUAL_TIME_FORMAT (VISUAL_BRIGHTNESS + 1) + #define VISUAL_COLOR_THEMES (VISUAL_TIME_FORMAT + 1) + #define VISUAL_TOTAL VISUAL_COLOR_THEMES + + switch (item) { + case VISUAL_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Control, CONTROL_VISUAL); + break; + case VISUAL_BACKLIGHT: + if (draw) + Draw_Menu_Item(row, ICON_Brightness, F("Display Off")); + else + ui.set_brightness(0); + break; + case VISUAL_BRIGHTNESS: + if (draw) { + Draw_Menu_Item(row, ICON_Brightness, F("LCD Brightness")); + Draw_Float(ui.brightness, row, false, 1); + } + else + Modify_Value(ui.brightness, LCD_BRIGHTNESS_MIN, LCD_BRIGHTNESS_MAX, 1, ui.refresh_brightness); + break; + case VISUAL_TIME_FORMAT: + if (draw) { + Draw_Menu_Item(row, ICON_PrintTime, F("Progress as __h__m")); + Draw_Checkbox(row, eeprom_settings.time_format_textual); + } + else { + eeprom_settings.time_format_textual = !eeprom_settings.time_format_textual; + Draw_Checkbox(row, eeprom_settings.time_format_textual); + } + break; + case VISUAL_COLOR_THEMES: + if (draw) + Draw_Menu_Item(row, ICON_MaxSpeed, F("UI Color Settings"), nullptr, true); + else + Draw_Menu(ColorSettings); + break; + } + break; + + case ColorSettings: + + #define COLORSETTINGS_BACK 0 + #define COLORSETTINGS_CURSOR (COLORSETTINGS_BACK + 1) + #define COLORSETTINGS_SPLIT_LINE (COLORSETTINGS_CURSOR + 1) + #define COLORSETTINGS_MENU_TOP_TXT (COLORSETTINGS_SPLIT_LINE + 1) + #define COLORSETTINGS_MENU_TOP_BG (COLORSETTINGS_MENU_TOP_TXT + 1) + #define COLORSETTINGS_HIGHLIGHT_BORDER (COLORSETTINGS_MENU_TOP_BG + 1) + #define COLORSETTINGS_PROGRESS_PERCENT (COLORSETTINGS_HIGHLIGHT_BORDER + 1) + #define COLORSETTINGS_PROGRESS_TIME (COLORSETTINGS_PROGRESS_PERCENT + 1) + #define COLORSETTINGS_PROGRESS_STATUS_BAR (COLORSETTINGS_PROGRESS_TIME + 1) + #define COLORSETTINGS_PROGRESS_STATUS_AREA (COLORSETTINGS_PROGRESS_STATUS_BAR + 1) + #define COLORSETTINGS_PROGRESS_COORDINATES (COLORSETTINGS_PROGRESS_STATUS_AREA + 1) + #define COLORSETTINGS_PROGRESS_COORDINATES_LINE (COLORSETTINGS_PROGRESS_COORDINATES + 1) + #define COLORSETTINGS_TOTAL COLORSETTINGS_PROGRESS_COORDINATES_LINE + + switch (item) { + case COLORSETTINGS_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Visual, VISUAL_COLOR_THEMES); + break; + case COLORSETTINGS_CURSOR: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Cursor")); + Draw_Option(eeprom_settings.cursor_color, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.cursor_color, color_names, Custom_Colors); + break; + case COLORSETTINGS_SPLIT_LINE: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Menu Split Line")); + Draw_Option(eeprom_settings.menu_split_line, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.menu_split_line, color_names, Custom_Colors); + break; + case COLORSETTINGS_MENU_TOP_TXT: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Menu Header Text")); + Draw_Option(eeprom_settings.menu_top_txt, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.menu_top_txt, color_names, Custom_Colors); + break; + case COLORSETTINGS_MENU_TOP_BG: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Menu Header Bg")); + Draw_Option(eeprom_settings.menu_top_bg, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.menu_top_bg, color_names, Custom_Colors); + break; + case COLORSETTINGS_HIGHLIGHT_BORDER: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Highlight Box")); + Draw_Option(eeprom_settings.highlight_box, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.highlight_box, color_names, Custom_Colors); + break; + case COLORSETTINGS_PROGRESS_PERCENT: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Progress Percent")); + Draw_Option(eeprom_settings.progress_percent, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.progress_percent, color_names, Custom_Colors); + break; + case COLORSETTINGS_PROGRESS_TIME: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Progress Time")); + Draw_Option(eeprom_settings.progress_time, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.progress_time, color_names, Custom_Colors); + break; + case COLORSETTINGS_PROGRESS_STATUS_BAR: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Status Bar Text")); + Draw_Option(eeprom_settings.status_bar_text, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.status_bar_text, color_names, Custom_Colors); + break; + case COLORSETTINGS_PROGRESS_STATUS_AREA: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Status Area Text")); + Draw_Option(eeprom_settings.status_area_text, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.status_area_text, color_names, Custom_Colors); + break; + case COLORSETTINGS_PROGRESS_COORDINATES: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Coordinates Text")); + Draw_Option(eeprom_settings.coordinates_text, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.coordinates_text, color_names, Custom_Colors); + break; + case COLORSETTINGS_PROGRESS_COORDINATES_LINE: + if (draw) { + Draw_Menu_Item(row, ICON_MaxSpeed, F("Coordinates Line")); + Draw_Option(eeprom_settings.coordinates_split_line, color_names, row, false, true); + } + else + Modify_Option(eeprom_settings.coordinates_split_line, color_names, Custom_Colors); + break; + } // switch (item) + break; + + case Advanced: + + #define ADVANCED_BACK 0 + #define ADVANCED_BEEPER (ADVANCED_BACK + ENABLED(SOUND_MENU_ITEM)) + #define ADVANCED_PROBE (ADVANCED_BEEPER + ENABLED(HAS_BED_PROBE)) + #define ADVANCED_CORNER (ADVANCED_PROBE + 1) + #define ADVANCED_LA (ADVANCED_CORNER + ENABLED(LIN_ADVANCE)) + #define ADVANCED_LOAD (ADVANCED_LA + ENABLED(ADVANCED_PAUSE_FEATURE)) + #define ADVANCED_UNLOAD (ADVANCED_LOAD + ENABLED(ADVANCED_PAUSE_FEATURE)) + #define ADVANCED_COLD_EXTRUDE (ADVANCED_UNLOAD + ENABLED(PREVENT_COLD_EXTRUSION)) + #define ADVANCED_FILSENSORENABLED (ADVANCED_COLD_EXTRUDE + ENABLED(FILAMENT_RUNOUT_SENSOR)) + #define ADVANCED_FILSENSORDISTANCE (ADVANCED_FILSENSORENABLED + ENABLED(HAS_FILAMENT_RUNOUT_DISTANCE)) + #define ADVANCED_POWER_LOSS (ADVANCED_FILSENSORDISTANCE + ENABLED(POWER_LOSS_RECOVERY)) + #define ADVANCED_TOTAL ADVANCED_POWER_LOSS + + switch (item) { + case ADVANCED_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Control, CONTROL_ADVANCED); + break; + + #if ENABLED(SOUND_MENU_ITEM) + case ADVANCED_BEEPER: + if (draw) { + Draw_Menu_Item(row, ICON_Version, F("LCD Beeper")); + Draw_Checkbox(row, ui.sound_on); + } + else { + ui.sound_on = !ui.sound_on; + Draw_Checkbox(row, ui.sound_on); + } + break; + #endif + + #if HAS_BED_PROBE + case ADVANCED_PROBE: + if (draw) + Draw_Menu_Item(row, ICON_StepX, F("Probe"), nullptr, true); + else + Draw_Menu(ProbeMenu); + break; + #endif + + case ADVANCED_CORNER: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccelerated, F("Bed Screw Inset")); + Draw_Float(corner_pos, row, false, 10); + } + else + Modify_Value(corner_pos, 1, 100, 10); + break; + + #if ENABLED(LIN_ADVANCE) + case ADVANCED_LA: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccelerated, F("Lin Advance Kp")); + Draw_Float(planner.extruder_advance_K[0], row, false, 100); + } + else + Modify_Value(planner.extruder_advance_K[0], 0, 10, 100); + break; + #endif + + #if ENABLED(ADVANCED_PAUSE_FEATURE) + case ADVANCED_LOAD: + if (draw) { + Draw_Menu_Item(row, ICON_WriteEEPROM, F("Load Length")); + Draw_Float(fc_settings[0].load_length, row, false, 1); + } + else + Modify_Value(fc_settings[0].load_length, 0, EXTRUDE_MAXLENGTH, 1); + break; + case ADVANCED_UNLOAD: + if (draw) { + Draw_Menu_Item(row, ICON_ReadEEPROM, F("Unload Length")); + Draw_Float(fc_settings[0].unload_length, row, false, 1); + } + else + Modify_Value(fc_settings[0].unload_length, 0, EXTRUDE_MAXLENGTH, 1); + break; + #endif // ADVANCED_PAUSE_FEATURE + + #if ENABLED(PREVENT_COLD_EXTRUSION) + case ADVANCED_COLD_EXTRUDE: + if (draw) { + Draw_Menu_Item(row, ICON_Cool, F("Min Extrusion T")); + Draw_Float(thermalManager.extrude_min_temp, row, false, 1); + } + else { + Modify_Value(thermalManager.extrude_min_temp, 0, MAX_E_TEMP, 1); + thermalManager.allow_cold_extrude = (thermalManager.extrude_min_temp == 0); + } + break; + #endif + + #if ENABLED(FILAMENT_RUNOUT_SENSOR) + case ADVANCED_FILSENSORENABLED: + if (draw) { + Draw_Menu_Item(row, ICON_Extruder, F("Filament Sensor")); + Draw_Checkbox(row, runout.enabled); + } + else { + runout.enabled = !runout.enabled; + Draw_Checkbox(row, runout.enabled); + } + break; + + #if ENABLED(HAS_FILAMENT_RUNOUT_DISTANCE) + case ADVANCED_FILSENSORDISTANCE: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccE, F("Runout Distance")); + Draw_Float(runout.runout_distance(), row, false, 10); + } + else + Modify_Value(runout.runout_distance(), 0, 999, 10); + break; + #endif + #endif // FILAMENT_RUNOUT_SENSOR + + #if ENABLED(POWER_LOSS_RECOVERY) + case ADVANCED_POWER_LOSS: + if (draw) { + Draw_Menu_Item(row, ICON_Motion, F("Power-loss recovery")); + Draw_Checkbox(row, recovery.enabled); + } + else { + recovery.enable(!recovery.enabled); + Draw_Checkbox(row, recovery.enabled); + } + break; + #endif + } + break; + + #if HAS_BED_PROBE + case ProbeMenu: + + #define PROBE_BACK 0 + #define PROBE_XOFFSET (PROBE_BACK + 1) + #define PROBE_YOFFSET (PROBE_XOFFSET + 1) + #define PROBE_TEST (PROBE_YOFFSET + 1) + #define PROBE_TEST_COUNT (PROBE_TEST + 1) + #define PROBE_TOTAL PROBE_TEST_COUNT + + static uint8_t testcount = 4; + + switch (item) { + case PROBE_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Advanced, ADVANCED_PROBE); + break; + + case PROBE_XOFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_StepX, F("Probe X Offset")); + Draw_Float(probe.offset.x, row, false, 10); + } + else + Modify_Value(probe.offset.x, -MAX_XY_OFFSET, MAX_XY_OFFSET, 10); + break; + case PROBE_YOFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_StepY, F("Probe Y Offset")); + Draw_Float(probe.offset.y, row, false, 10); + } + else + Modify_Value(probe.offset.y, -MAX_XY_OFFSET, MAX_XY_OFFSET, 10); + break; + case PROBE_TEST: + if (draw) + Draw_Menu_Item(row, ICON_StepY, F("M48 Probe Test")); + else { + sprintf_P(cmd, PSTR("G28O\nM48 X%s Y%s P%i"), dtostrf((X_BED_SIZE + X_MIN_POS) / 2.0f, 1, 3, str_1), dtostrf((Y_BED_SIZE + Y_MIN_POS) / 2.0f, 1, 3, str_2), testcount); + gcode.process_subcommands_now(cmd); + } + break; + case PROBE_TEST_COUNT: + if (draw) { + Draw_Menu_Item(row, ICON_StepY, F("Probe Test Count")); + Draw_Float(testcount, row, false, 1); + } + else + Modify_Value(testcount, 4, 50, 1); + break; + } + break; + #endif + + case InfoMain: + case Info: + + #define INFO_BACK 0 + #define INFO_PRINTCOUNT (INFO_BACK + ENABLED(PRINTCOUNTER)) + #define INFO_PRINTTIME (INFO_PRINTCOUNT + ENABLED(PRINTCOUNTER)) + #define INFO_SIZE (INFO_PRINTTIME + 1) + #define INFO_VERSION (INFO_SIZE + 1) + #define INFO_CONTACT (INFO_VERSION + 1) + #define INFO_TOTAL INFO_BACK + + switch (item) { + case INFO_BACK: + if (draw) { + Draw_Menu_Item(row, ICON_Back, F("Back")); + + #if ENABLED(PRINTCOUNTER) + char row1[50], row2[50], buf[32]; + printStatistics ps = print_job_timer.getStats(); + + sprintf_P(row1, PSTR("%i prints, %i finished"), ps.totalPrints, ps.finishedPrints); + sprintf_P(row2, PSTR("%s m filament used"), dtostrf(ps.filamentUsed / 1000, 1, 2, str_1)); + Draw_Menu_Item(INFO_PRINTCOUNT, ICON_HotendTemp, row1, row2, false, true); + + duration_t(print_job_timer.getStats().printTime).toString(buf); + sprintf_P(row1, PSTR("Printed: %s"), buf); + duration_t(print_job_timer.getStats().longestPrint).toString(buf); + sprintf_P(row2, PSTR("Longest: %s"), buf); + Draw_Menu_Item(INFO_PRINTTIME, ICON_PrintTime, row1, row2, false, true); + #endif + + Draw_Menu_Item(INFO_SIZE, ICON_PrintSize, F(MACHINE_SIZE), nullptr, false, true); + Draw_Menu_Item(INFO_VERSION, ICON_Version, F(SHORT_BUILD_VERSION), nullptr, false, true); + Draw_Menu_Item(INFO_CONTACT, ICON_Contact, F(CORP_WEBSITE), nullptr, false, true); + } + else { + if (menu == Info) + Draw_Menu(Control, CONTROL_INFO); + else + Draw_Main_Menu(3); + } + break; + } + break; + + #if HAS_MESH + case Leveling: + + #define LEVELING_BACK 0 + #define LEVELING_ACTIVE (LEVELING_BACK + 1) + #define LEVELING_GET_TILT (LEVELING_ACTIVE + BOTH(HAS_BED_PROBE, AUTO_BED_LEVELING_UBL)) + #define LEVELING_GET_MESH (LEVELING_GET_TILT + 1) + #define LEVELING_MANUAL (LEVELING_GET_MESH + 1) + #define LEVELING_VIEW (LEVELING_MANUAL + 1) + #define LEVELING_SETTINGS (LEVELING_VIEW + 1) + #define LEVELING_SLOT (LEVELING_SETTINGS + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_LOAD (LEVELING_SLOT + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_SAVE (LEVELING_LOAD + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_TOTAL LEVELING_SAVE + + switch (item) { + case LEVELING_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Main_Menu(3); + break; + case LEVELING_ACTIVE: + if (draw) { + Draw_Menu_Item(row, ICON_StockConfiguration, F("Leveling Active")); + Draw_Checkbox(row, planner.leveling_active); + } + else { + if (!planner.leveling_active) { + set_bed_leveling_enabled(!planner.leveling_active); + if (!planner.leveling_active) { + Confirm_Handler(LevelError); + break; + } + } + else + set_bed_leveling_enabled(!planner.leveling_active); + Draw_Checkbox(row, planner.leveling_active); + } + break; + #if BOTH(HAS_BED_PROBE, AUTO_BED_LEVELING_UBL) + case LEVELING_GET_TILT: + if (draw) + Draw_Menu_Item(row, ICON_Tilt, F("Autotilt Current Mesh")); + else { + if (bedlevel.storage_slot < 0) { + Popup_Handler(MeshSlot); + break; + } + Popup_Handler(Home); + gcode.home_all_axes(true); + Popup_Handler(Level); + if (mesh_conf.tilt_grid > 1) { + sprintf_P(cmd, PSTR("G29 J%i"), mesh_conf.tilt_grid); + gcode.process_subcommands_now(cmd); + } + else + gcode.process_subcommands_now(F("G29 J")); + planner.synchronize(); + Redraw_Menu(); + } + break; + #endif + case LEVELING_GET_MESH: + if (draw) + Draw_Menu_Item(row, ICON_Mesh, F("Create New Mesh")); + else { + Popup_Handler(Home); + gcode.home_all_axes(true); + #if ENABLED(AUTO_BED_LEVELING_UBL) + #if ENABLED(PREHEAT_BEFORE_LEVELING) + Popup_Handler(Heating); + probe.preheat_for_probing(LEVELING_NOZZLE_TEMP, LEVELING_BED_TEMP); + #endif + #if HAS_BED_PROBE + Popup_Handler(Level); + gcode.process_subcommands_now(F("G29 P0\nG29 P1")); + gcode.process_subcommands_now(F("G29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nG29 P3\nM420 S1")); + planner.synchronize(); + Update_Status("Probed all reachable points"); + Popup_Handler(SaveLevel); + #else + level_state = planner.leveling_active; + set_bed_leveling_enabled(false); + mesh_conf.goto_mesh_value = true; + mesh_conf.mesh_x = mesh_conf.mesh_y = 0; + Popup_Handler(MoveWait); + mesh_conf.manual_mesh_move(); + Draw_Menu(UBLMesh); + #endif + #elif HAS_BED_PROBE + Popup_Handler(Level); + gcode.process_subcommands_now(F("G29")); + planner.synchronize(); + Popup_Handler(SaveLevel); + #else + level_state = planner.leveling_active; + set_bed_leveling_enabled(false); + gridpoint = 1; + Popup_Handler(MoveWait); + gcode.process_subcommands_now(F("G29")); + planner.synchronize(); + Draw_Menu(ManualMesh); + #endif + } + break; + case LEVELING_MANUAL: + if (draw) + Draw_Menu_Item(row, ICON_Mesh, F("Manual Tuning"), nullptr, true); + else { + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + if (!leveling_is_valid()) { + Confirm_Handler(InvalidMesh); + break; + } + #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) + if (bedlevel.storage_slot < 0) { + Popup_Handler(MeshSlot); + break; + } + #endif + if (axes_should_home()) { + Popup_Handler(Home); + gcode.home_all_axes(true); + } + level_state = planner.leveling_active; + set_bed_leveling_enabled(false); + mesh_conf.goto_mesh_value = false; + #if ENABLED(PREHEAT_BEFORE_LEVELING) + Popup_Handler(Heating); + #if HAS_HOTEND + if (thermalManager.degTargetHotend(0) < LEVELING_NOZZLE_TEMP) + thermalManager.setTargetHotend(LEVELING_NOZZLE_TEMP, 0); + #endif + #if HAS_HEATED_BED + if (thermalManager.degTargetBed() < LEVELING_BED_TEMP) + thermalManager.setTargetBed(LEVELING_BED_TEMP); + #endif + TERN_(HAS_HOTEND, thermalManager.wait_for_hotend(0)); + TERN_(HAS_HEATED_BED, thermalManager.wait_for_bed_heating()); + #endif + Popup_Handler(MoveWait); + mesh_conf.manual_mesh_move(); + Draw_Menu(LevelManual); + } + break; + case LEVELING_VIEW: + if (draw) + Draw_Menu_Item(row, ICON_Mesh, GET_TEXT_F(MSG_MESH_VIEW), nullptr, true); + else { + #if ENABLED(AUTO_BED_LEVELING_UBL) + if (bedlevel.storage_slot < 0) { + Popup_Handler(MeshSlot); + break; + } + #endif + Draw_Menu(LevelView); + } + break; + case LEVELING_SETTINGS: + if (draw) + Draw_Menu_Item(row, ICON_Step, F("Leveling Settings"), nullptr, true); + else + Draw_Menu(LevelSettings); + break; + #if ENABLED(AUTO_BED_LEVELING_UBL) + case LEVELING_SLOT: + if (draw) { + Draw_Menu_Item(row, ICON_PrintSize, F("Mesh Slot")); + Draw_Float(bedlevel.storage_slot, row, false, 1); + } + else + Modify_Value(bedlevel.storage_slot, 0, settings.calc_num_meshes() - 1, 1); + break; + case LEVELING_LOAD: + if (draw) + Draw_Menu_Item(row, ICON_ReadEEPROM, F("Load Mesh")); + else { + if (bedlevel.storage_slot < 0) { + Popup_Handler(MeshSlot); + break; + } + gcode.process_subcommands_now(F("G29 L")); + planner.synchronize(); + AudioFeedback(true); + } + break; + case LEVELING_SAVE: + if (draw) + Draw_Menu_Item(row, ICON_WriteEEPROM, F("Save Mesh")); + else { + if (bedlevel.storage_slot < 0) { + Popup_Handler(MeshSlot); + break; + } + gcode.process_subcommands_now(F("G29 S")); + planner.synchronize(); + AudioFeedback(true); + } + break; + #endif + } + break; + + case LevelView: + + #define LEVELING_VIEW_BACK 0 + #define LEVELING_VIEW_MESH (LEVELING_VIEW_BACK + 1) + #define LEVELING_VIEW_TEXT (LEVELING_VIEW_MESH + 1) + #define LEVELING_VIEW_ASYMMETRIC (LEVELING_VIEW_TEXT + 1) + #define LEVELING_VIEW_TOTAL LEVELING_VIEW_ASYMMETRIC + + switch (item) { + case LEVELING_VIEW_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Leveling, LEVELING_VIEW); + break; + case LEVELING_VIEW_MESH: + if (draw) + Draw_Menu_Item(row, ICON_PrintSize, GET_TEXT_F(MSG_MESH_VIEW), nullptr, true); + else + Draw_Menu(MeshViewer); + break; + case LEVELING_VIEW_TEXT: + if (draw) { + Draw_Menu_Item(row, ICON_Contact, F("Viewer Show Values")); + Draw_Checkbox(row, mesh_conf.viewer_print_value); + } + else { + mesh_conf.viewer_print_value = !mesh_conf.viewer_print_value; + Draw_Checkbox(row, mesh_conf.viewer_print_value); + } + break; + case LEVELING_VIEW_ASYMMETRIC: + if (draw) { + Draw_Menu_Item(row, ICON_Axis, F("Viewer Asymmetric")); + Draw_Checkbox(row, mesh_conf.viewer_asymmetric_range); + } + else { + mesh_conf.viewer_asymmetric_range = !mesh_conf.viewer_asymmetric_range; + Draw_Checkbox(row, mesh_conf.viewer_asymmetric_range); + } + break; + } + break; + + case LevelSettings: + + #define LEVELING_SETTINGS_BACK 0 + #define LEVELING_SETTINGS_FADE (LEVELING_SETTINGS_BACK + 1) + #define LEVELING_SETTINGS_TILT (LEVELING_SETTINGS_FADE + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_SETTINGS_PLANE (LEVELING_SETTINGS_TILT + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_SETTINGS_ZERO (LEVELING_SETTINGS_PLANE + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_SETTINGS_UNDEF (LEVELING_SETTINGS_ZERO + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_SETTINGS_TOTAL LEVELING_SETTINGS_UNDEF + + switch (item) { + case LEVELING_SETTINGS_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Menu(Leveling, LEVELING_SETTINGS); + break; + case LEVELING_SETTINGS_FADE: + if (draw) { + Draw_Menu_Item(row, ICON_Fade, F("Fade Mesh within")); + Draw_Float(planner.z_fade_height, row, false, 1); + } + else { + Modify_Value(planner.z_fade_height, 0, Z_MAX_POS, 1); + planner.z_fade_height = -1; + set_z_fade_height(planner.z_fade_height); + } + break; + + #if ENABLED(AUTO_BED_LEVELING_UBL) + case LEVELING_SETTINGS_TILT: + if (draw) { + Draw_Menu_Item(row, ICON_Tilt, F("Tilting Grid Size")); + Draw_Float(mesh_conf.tilt_grid, row, false, 1); + } + else + Modify_Value(mesh_conf.tilt_grid, 1, 8, 1); + break; + case LEVELING_SETTINGS_PLANE: + if (draw) + Draw_Menu_Item(row, ICON_ResumeEEPROM, F("Convert Mesh to Plane")); + else { + if (mesh_conf.create_plane_from_mesh()) break; + gcode.process_subcommands_now(F("M420 S1")); + planner.synchronize(); + AudioFeedback(true); + } + break; + case LEVELING_SETTINGS_ZERO: + if (draw) + Draw_Menu_Item(row, ICON_Mesh, F("Zero Current Mesh")); + else + ZERO(bedlevel.z_values); + break; + case LEVELING_SETTINGS_UNDEF: + if (draw) + Draw_Menu_Item(row, ICON_Mesh, F("Clear Current Mesh")); + else + bedlevel.invalidate(); + break; + #endif // AUTO_BED_LEVELING_UBL + } + break; + + case MeshViewer: + #define MESHVIEW_BACK 0 + #define MESHVIEW_TOTAL MESHVIEW_BACK + + if (item == MESHVIEW_BACK) { + if (draw) { + Draw_Menu_Item(0, ICON_Back, F("Back")); + mesh_conf.Draw_Bed_Mesh(); + mesh_conf.Set_Mesh_Viewer_Status(); + } + else if (!mesh_conf.drawing_mesh) { + Draw_Menu(LevelView, LEVELING_VIEW_MESH); + Update_Status(""); + } + } + break; + + case LevelManual: + + #define LEVELING_M_BACK 0 + #define LEVELING_M_X (LEVELING_M_BACK + 1) + #define LEVELING_M_Y (LEVELING_M_X + 1) + #define LEVELING_M_NEXT (LEVELING_M_Y + 1) + #define LEVELING_M_OFFSET (LEVELING_M_NEXT + 1) + #define LEVELING_M_UP (LEVELING_M_OFFSET + 1) + #define LEVELING_M_DOWN (LEVELING_M_UP + 1) + #define LEVELING_M_GOTO_VALUE (LEVELING_M_DOWN + 1) + #define LEVELING_M_UNDEF (LEVELING_M_GOTO_VALUE + ENABLED(AUTO_BED_LEVELING_UBL)) + #define LEVELING_M_TOTAL LEVELING_M_UNDEF + + switch (item) { + case LEVELING_M_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else { + set_bed_leveling_enabled(level_state); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); + Draw_Menu(Leveling, LEVELING_MANUAL); + } + break; + case LEVELING_M_X: + if (draw) { + Draw_Menu_Item(row, ICON_MoveX, F("Mesh Point X")); + Draw_Float(mesh_conf.mesh_x, row, 0, 1); + } + else + Modify_Value(mesh_conf.mesh_x, 0, GRID_MAX_POINTS_X - 1, 1); + break; + case LEVELING_M_Y: + if (draw) { + Draw_Menu_Item(row, ICON_MoveY, F("Mesh Point Y")); + Draw_Float(mesh_conf.mesh_y, row, 0, 1); + } + else + Modify_Value(mesh_conf.mesh_y, 0, GRID_MAX_POINTS_Y - 1, 1); + break; + case LEVELING_M_NEXT: + if (draw) + Draw_Menu_Item(row, ICON_More, F("Next Point")); + else { + if (mesh_conf.mesh_x != (GRID_MAX_POINTS_X - 1) || mesh_conf.mesh_y != (GRID_MAX_POINTS_Y - 1)) { + if ((mesh_conf.mesh_x == (GRID_MAX_POINTS_X - 1) && mesh_conf.mesh_y % 2 == 0) || (mesh_conf.mesh_x == 0 && mesh_conf.mesh_y % 2 == 1)) + mesh_conf.mesh_y++; + else if (mesh_conf.mesh_y % 2 == 0) + mesh_conf.mesh_x++; + else + mesh_conf.mesh_x--; + mesh_conf.manual_mesh_move(); + } + } + break; + case LEVELING_M_OFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_SetZOffset, F("Point Z Offset")); + Draw_Float(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], row, false, 100); + } + else { + if (isnan(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y])) + bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] = 0; + Modify_Value(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], MIN_Z_OFFSET, MAX_Z_OFFSET, 100); + } + break; + case LEVELING_M_UP: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Microstep Up")); + else if (bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] < MAX_Z_OFFSET) { + bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] += 0.01; + gcode.process_subcommands_now(F("M290 Z0.01")); + planner.synchronize(); + current_position.z += 0.01f; + sync_plan_position(); + Draw_Float(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], row - 1, false, 100); + } + break; + case LEVELING_M_DOWN: + if (draw) + Draw_Menu_Item(row, ICON_AxisD, F("Microstep Down")); + else if (bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] > MIN_Z_OFFSET) { + bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] -= 0.01; + gcode.process_subcommands_now(F("M290 Z-0.01")); + planner.synchronize(); + current_position.z -= 0.01f; + sync_plan_position(); + Draw_Float(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], row - 2, false, 100); + } + break; + case LEVELING_M_GOTO_VALUE: + if (draw) { + Draw_Menu_Item(row, ICON_StockConfiguration, F("Go to Mesh Z Value")); + Draw_Checkbox(row, mesh_conf.goto_mesh_value); + } + else { + mesh_conf.goto_mesh_value = !mesh_conf.goto_mesh_value; + current_position.z = 0; + mesh_conf.manual_mesh_move(true); + Draw_Checkbox(row, mesh_conf.goto_mesh_value); + } + break; + #if ENABLED(AUTO_BED_LEVELING_UBL) + case LEVELING_M_UNDEF: + if (draw) + Draw_Menu_Item(row, ICON_ResumeEEPROM, F("Clear Point Value")); + else { + mesh_conf.manual_value_update(true); + Redraw_Menu(false); + } + break; + #endif + } + break; + #endif // HAS_MESH + + #if ENABLED(AUTO_BED_LEVELING_UBL) && !HAS_BED_PROBE + case UBLMesh: + + #define UBL_M_BACK 0 + #define UBL_M_NEXT (UBL_M_BACK + 1) + #define UBL_M_PREV (UBL_M_NEXT + 1) + #define UBL_M_OFFSET (UBL_M_PREV + 1) + #define UBL_M_UP (UBL_M_OFFSET + 1) + #define UBL_M_DOWN (UBL_M_UP + 1) + #define UBL_M_TOTAL UBL_M_DOWN + + switch (item) { + case UBL_M_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else { + set_bed_leveling_enabled(level_state); + Draw_Menu(Leveling, LEVELING_GET_MESH); + } + break; + case UBL_M_NEXT: + if (draw) { + if (mesh_conf.mesh_x != (GRID_MAX_POINTS_X - 1) || mesh_conf.mesh_y != (GRID_MAX_POINTS_Y - 1)) + Draw_Menu_Item(row, ICON_More, F("Next Point")); + else + Draw_Menu_Item(row, ICON_More, F("Save Mesh")); + } + else { + if (mesh_conf.mesh_x != (GRID_MAX_POINTS_X - 1) || mesh_conf.mesh_y != (GRID_MAX_POINTS_Y - 1)) { + if ((mesh_conf.mesh_x == (GRID_MAX_POINTS_X - 1) && mesh_conf.mesh_y % 2 == 0) || (mesh_conf.mesh_x == 0 && mesh_conf.mesh_y % 2 == 1)) + mesh_conf.mesh_y++; + else if (mesh_conf.mesh_y % 2 == 0) + mesh_conf.mesh_x++; + else + mesh_conf.mesh_x--; + mesh_conf.manual_mesh_move(); + } + else { + gcode.process_subcommands_now(F("G29 S")); + planner.synchronize(); + AudioFeedback(true); + Draw_Menu(Leveling, LEVELING_GET_MESH); + } + } + break; + case UBL_M_PREV: + if (draw) + Draw_Menu_Item(row, ICON_More, F("Previous Point")); + else { + if (mesh_conf.mesh_x != 0 || mesh_conf.mesh_y != 0) { + if ((mesh_conf.mesh_x == (GRID_MAX_POINTS_X - 1) && mesh_conf.mesh_y % 2 == 1) || (mesh_conf.mesh_x == 0 && mesh_conf.mesh_y % 2 == 0)) + mesh_conf.mesh_y--; + else if (mesh_conf.mesh_y % 2 == 0) + mesh_conf.mesh_x--; + else + mesh_conf.mesh_x++; + mesh_conf.manual_mesh_move(); + } + } + break; + case UBL_M_OFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_SetZOffset, F("Point Z Offset")); + Draw_Float(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], row, false, 100); + } + else { + if (isnan(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y])) + bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] = 0; + Modify_Value(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], MIN_Z_OFFSET, MAX_Z_OFFSET, 100); + } + break; + case UBL_M_UP: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Microstep Up")); + else if (bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] < MAX_Z_OFFSET) { + bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] += 0.01; + gcode.process_subcommands_now(F("M290 Z0.01")); + planner.synchronize(); + current_position.z += 0.01f; + sync_plan_position(); + Draw_Float(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], row - 1, false, 100); + } + break; + case UBL_M_DOWN: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Microstep Down")); + else if (bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] > MIN_Z_OFFSET) { + bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y] -= 0.01; + gcode.process_subcommands_now(F("M290 Z-0.01")); + planner.synchronize(); + current_position.z -= 0.01f; + sync_plan_position(); + Draw_Float(bedlevel.z_values[mesh_conf.mesh_x][mesh_conf.mesh_y], row - 2, false, 100); + } + break; + } + break; + #endif // AUTO_BED_LEVELING_UBL && !HAS_BED_PROBE + + #if ENABLED(PROBE_MANUALLY) + case ManualMesh: + + #define MMESH_BACK 0 + #define MMESH_NEXT (MMESH_BACK + 1) + #define MMESH_OFFSET (MMESH_NEXT + 1) + #define MMESH_UP (MMESH_OFFSET + 1) + #define MMESH_DOWN (MMESH_UP + 1) + #define MMESH_OLD (MMESH_DOWN + 1) + #define MMESH_TOTAL MMESH_OLD + + switch (item) { + case MMESH_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Cancel")); + else { + gcode.process_subcommands_now(F("G29 A")); + planner.synchronize(); + set_bed_leveling_enabled(level_state); + Draw_Menu(Leveling, LEVELING_GET_MESH); + } + break; + case MMESH_NEXT: + if (draw) { + if (gridpoint < GRID_MAX_POINTS) + Draw_Menu_Item(row, ICON_More, F("Next Point")); + else + Draw_Menu_Item(row, ICON_More, F("Save Mesh")); + } + else if (gridpoint < GRID_MAX_POINTS) { + Popup_Handler(MoveWait); + gcode.process_subcommands_now(F("G29")); + planner.synchronize(); + gridpoint++; + Redraw_Menu(); + } + else { + gcode.process_subcommands_now(F("G29")); + planner.synchronize(); + AudioFeedback(settings.save()); + Draw_Menu(Leveling, LEVELING_GET_MESH); + } + break; + case MMESH_OFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_SetZOffset, F("Z Position")); + current_position.z = MANUAL_PROBE_START_Z; + Draw_Float(current_position.z, row, false, 100); + } + else + Modify_Value(current_position.z, MIN_Z_OFFSET, MAX_Z_OFFSET, 100); + break; + case MMESH_UP: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Microstep Up")); + else if (current_position.z < MAX_Z_OFFSET) { + gcode.process_subcommands_now(F("M290 Z0.01")); + planner.synchronize(); + current_position.z += 0.01f; + sync_plan_position(); + Draw_Float(current_position.z, row - 1, false, 100); + } + break; + case MMESH_DOWN: + if (draw) + Draw_Menu_Item(row, ICON_AxisD, F("Microstep Down")); + else if (current_position.z > MIN_Z_OFFSET) { + gcode.process_subcommands_now(F("M290 Z-0.01")); + planner.synchronize(); + current_position.z -= 0.01f; + sync_plan_position(); + Draw_Float(current_position.z, row - 2, false, 100); + } + break; + case MMESH_OLD: + uint8_t mesh_x, mesh_y; + // 0,0 -> 1,0 -> 2,0 -> 2,1 -> 1,1 -> 0,1 -> 0,2 -> 1,2 -> 2,2 + mesh_y = (gridpoint - 1) / (GRID_MAX_POINTS_Y); + mesh_x = (gridpoint - 1) % (GRID_MAX_POINTS_X); + + if (mesh_y % 2 == 1) + mesh_x = (GRID_MAX_POINTS_X) - mesh_x - 1; + + const float currval = bedlevel.z_values[mesh_x][mesh_y]; + + if (draw) { + Draw_Menu_Item(row, ICON_Zoffset, F("Goto Mesh Value")); + Draw_Float(currval, row, false, 100); + } + else if (!isnan(currval)) { + current_position.z = currval; + planner.synchronize(); + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + planner.synchronize(); + Draw_Float(current_position.z, row - 3, false, 100); + } + break; + } + break; + #endif // PROBE_MANUALLY + + case Tune: + + #define TUNE_BACK 0 + #define TUNE_SPEED (TUNE_BACK + 1) + #define TUNE_FLOW (TUNE_SPEED + ENABLED(HAS_HOTEND)) + #define TUNE_HOTEND (TUNE_FLOW + ENABLED(HAS_HOTEND)) + #define TUNE_BED (TUNE_HOTEND + ENABLED(HAS_HEATED_BED)) + #define TUNE_FAN (TUNE_BED + ENABLED(HAS_FAN)) + #define TUNE_ZOFFSET (TUNE_FAN + ENABLED(HAS_ZOFFSET_ITEM)) + #define TUNE_ZUP (TUNE_ZOFFSET + ENABLED(HAS_ZOFFSET_ITEM)) + #define TUNE_ZDOWN (TUNE_ZUP + ENABLED(HAS_ZOFFSET_ITEM)) + #define TUNE_CHANGEFIL (TUNE_ZDOWN + ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)) + #define TUNE_FILSENSORENABLED (TUNE_CHANGEFIL + ENABLED(FILAMENT_RUNOUT_SENSOR)) + #define TUNE_BACKLIGHT_OFF (TUNE_FILSENSORENABLED + 1) + #define TUNE_BACKLIGHT (TUNE_BACKLIGHT_OFF + 1) + #define TUNE_TOTAL TUNE_BACKLIGHT + + switch (item) { + case TUNE_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Back")); + else + Draw_Print_Screen(); + break; + case TUNE_SPEED: + if (draw) { + Draw_Menu_Item(row, ICON_Speed, F("Print Speed")); + Draw_Float(feedrate_percentage, row, false, 1); + } + else + Modify_Value(feedrate_percentage, MIN_PRINT_SPEED, MAX_PRINT_SPEED, 1); + break; + + #if HAS_HOTEND + case TUNE_FLOW: + if (draw) { + Draw_Menu_Item(row, ICON_Speed, F("Flow Rate")); + Draw_Float(planner.flow_percentage[0], row, false, 1); + } + else + Modify_Value(planner.flow_percentage[0], MIN_FLOW_RATE, MAX_FLOW_RATE, 1); + break; + case TUNE_HOTEND: + if (draw) { + Draw_Menu_Item(row, ICON_SetEndTemp, F("Hotend")); + Draw_Float(thermalManager.temp_hotend[0].target, row, false, 1); + } + else + Modify_Value(thermalManager.temp_hotend[0].target, MIN_E_TEMP, MAX_E_TEMP, 1); + break; + #endif + + #if HAS_HEATED_BED + case TUNE_BED: + if (draw) { + Draw_Menu_Item(row, ICON_SetBedTemp, F("Bed")); + Draw_Float(thermalManager.temp_bed.target, row, false, 1); + } + else + Modify_Value(thermalManager.temp_bed.target, MIN_BED_TEMP, MAX_BED_TEMP, 1); + break; + #endif + + #if HAS_FAN + case TUNE_FAN: + if (draw) { + Draw_Menu_Item(row, ICON_FanSpeed, F("Fan")); + Draw_Float(thermalManager.fan_speed[0], row, false, 1); + } + else + Modify_Value(thermalManager.fan_speed[0], MIN_FAN_SPEED, MAX_FAN_SPEED, 1); + break; + #endif + + #if HAS_ZOFFSET_ITEM + case TUNE_ZOFFSET: + if (draw) { + Draw_Menu_Item(row, ICON_FanSpeed, F("Z-Offset")); + Draw_Float(zoffsetvalue, row, false, 100); + } + else + Modify_Value(zoffsetvalue, MIN_Z_OFFSET, MAX_Z_OFFSET, 100); + break; + case TUNE_ZUP: + if (draw) + Draw_Menu_Item(row, ICON_Axis, F("Z-Offset Up")); + else if (zoffsetvalue < MAX_Z_OFFSET) { + gcode.process_subcommands_now(F("M290 Z0.01")); + zoffsetvalue += 0.01; + Draw_Float(zoffsetvalue, row - 1, false, 100); + } + break; + case TUNE_ZDOWN: + if (draw) + Draw_Menu_Item(row, ICON_AxisD, F("Z-Offset Down")); + else if (zoffsetvalue > MIN_Z_OFFSET) { + gcode.process_subcommands_now(F("M290 Z-0.01")); + zoffsetvalue -= 0.01; + Draw_Float(zoffsetvalue, row - 2, false, 100); + } + break; + #endif + + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + case TUNE_CHANGEFIL: + if (draw) + Draw_Menu_Item(row, ICON_ResumeEEPROM, F("Change Filament")); + else + Popup_Handler(ConfFilChange); + break; + #endif + + #if ENABLED(FILAMENT_RUNOUT_SENSOR) + case TUNE_FILSENSORENABLED: + if (draw) { + Draw_Menu_Item(row, ICON_Extruder, F("Filament Sensor")); + Draw_Checkbox(row, runout.enabled); + } + else { + runout.enabled = !runout.enabled; + Draw_Checkbox(row, runout.enabled); + } + break; + #endif + + case TUNE_BACKLIGHT_OFF: + if (draw) + Draw_Menu_Item(row, ICON_Brightness, F("Display Off")); + else + ui.set_brightness(0); + break; + case TUNE_BACKLIGHT: + if (draw) { + Draw_Menu_Item(row, ICON_Brightness, F("LCD Brightness")); + Draw_Float(ui.brightness, row, false, 1); + } + else + Modify_Value(ui.brightness, LCD_BRIGHTNESS_MIN, LCD_BRIGHTNESS_MAX, 1, ui.refresh_brightness); + break; + } + break; + + #if HAS_PREHEAT && HAS_HOTEND + + case PreheatHotend: + + #define PREHEATHOTEND_BACK 0 + #define PREHEATHOTEND_CONTINUE (PREHEATHOTEND_BACK + 1) + #define PREHEATHOTEND_1 (PREHEATHOTEND_CONTINUE + (PREHEAT_COUNT >= 1)) + #define PREHEATHOTEND_2 (PREHEATHOTEND_1 + (PREHEAT_COUNT >= 2)) + #define PREHEATHOTEND_3 (PREHEATHOTEND_2 + (PREHEAT_COUNT >= 3)) + #define PREHEATHOTEND_4 (PREHEATHOTEND_3 + (PREHEAT_COUNT >= 4)) + #define PREHEATHOTEND_5 (PREHEATHOTEND_4 + (PREHEAT_COUNT >= 5)) + #define PREHEATHOTEND_CUSTOM (PREHEATHOTEND_5 + 1) + #define PREHEATHOTEND_TOTAL PREHEATHOTEND_CUSTOM + + switch (item) { + case PREHEATHOTEND_BACK: + if (draw) + Draw_Menu_Item(row, ICON_Back, F("Cancel")); + else { + thermalManager.setTargetHotend(0, 0); + thermalManager.set_fan_speed(0, 0); + Redraw_Menu(false, true, true); + } + break; + case PREHEATHOTEND_CONTINUE: + if (draw) + Draw_Menu_Item(row, ICON_SetEndTemp, F("Continue")); + else { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + switch (last_menu) { + case Prepare: + Popup_Handler(FilChange); + sprintf_P(cmd, PSTR("M600 B1 R%i"), thermalManager.temp_hotend[0].target); + gcode.process_subcommands_now(cmd); + break; + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + case ChangeFilament: + switch (last_selection) { + case CHANGEFIL_LOAD: + Popup_Handler(FilLoad); + gcode.process_subcommands_now(F("M701")); + planner.synchronize(); + Redraw_Menu(true, true, true); + break; + case CHANGEFIL_UNLOAD: + Popup_Handler(FilLoad, true); + gcode.process_subcommands_now(F("M702")); + planner.synchronize(); + Redraw_Menu(true, true, true); + break; + case CHANGEFIL_CHANGE: + Popup_Handler(FilChange); + sprintf_P(cmd, PSTR("M600 B1 R%i"), thermalManager.temp_hotend[0].target); + gcode.process_subcommands_now(cmd); + break; + } + break; + #endif + default: + Redraw_Menu(true, true, true); + break; + } + } + break; + + + #define _PREHEAT_HOTEND_CASE(N) \ + case PREHEATHOTEND_##N: \ + if (draw) Draw_Menu_Item(row, ICON_Temperature, F(PREHEAT_## N ##_LABEL)); \ + else ui.preheat_hotend_and_fan((N) - 1); \ + break; + + REPEAT_1(PREHEAT_COUNT, _PREHEAT_HOTEND_CASE) + + case PREHEATHOTEND_CUSTOM: + if (draw) { + Draw_Menu_Item(row, ICON_Temperature, F("Custom")); + Draw_Float(thermalManager.temp_hotend[0].target, row, false, 1); + } + else + Modify_Value(thermalManager.temp_hotend[0].target, EXTRUDE_MINTEMP, MAX_E_TEMP, 1); + break; + } + break; + + #endif // HAS_PREHEAT && HAS_HOTEND + } +} + +FSTR_P CrealityDWINClass::Get_Menu_Title(uint8_t menu) { + switch (menu) { + case MainMenu: return F("Main Menu"); + case Prepare: return F("Prepare"); + case HomeMenu: return F("Homing Menu"); + case Move: return F("Move"); + case ManualLevel: return F("Manual Leveling"); + #if HAS_ZOFFSET_ITEM + case ZOffset: return F("Z Offset"); + #endif + #if HAS_PREHEAT + case Preheat: return F("Preheat"); + #endif + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + case ChangeFilament: return F("Change Filament"); + #endif + #if HAS_CUSTOM_MENU + case MenuCustom: + #ifdef CUSTOM_MENU_CONFIG_TITLE + return F(CUSTOM_MENU_CONFIG_TITLE); + #else + return F("Custom Commands"); + #endif + #endif + case Control: return F("Control"); + case TempMenu: return F("Temperature"); + #if HAS_HOTEND || HAS_HEATED_BED + case PID: return F("PID Menu"); + #endif + #if HAS_HOTEND + case HotendPID: return F("Hotend PID Settings"); + #endif + #if HAS_HEATED_BED + case BedPID: return F("Bed PID Settings"); + #endif + #if HAS_PREHEAT + #define _PREHEAT_TITLE_CASE(N) case Preheat##N: return F(PREHEAT_## N ##_LABEL " Settings"); + REPEAT_1(PREHEAT_COUNT, _PREHEAT_TITLE_CASE) + #endif + case Motion: return F("Motion Settings"); + case HomeOffsets: return F("Home Offsets"); + case MaxSpeed: return F("Max Speed"); + case MaxAcceleration: return F("Max Acceleration"); + #if HAS_CLASSIC_JERK + case MaxJerk: return F("Max Jerk"); + #endif + case Steps: return F("Steps/mm"); + case Visual: return F("Visual Settings"); + case Advanced: return F("Advanced Settings"); + #if HAS_BED_PROBE + case ProbeMenu: return F("Probe Menu"); + #endif + case ColorSettings: return F("UI Color Settings"); + case Info: return F("Info"); + case InfoMain: return F("Info"); + #if HAS_MESH + case Leveling: return F("Leveling"); + case LevelView: return GET_TEXT_F(MSG_MESH_VIEW); + case LevelSettings: return F("Leveling Settings"); + case MeshViewer: return GET_TEXT_F(MSG_MESH_VIEW); + case LevelManual: return F("Manual Tuning"); + #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) && !HAS_BED_PROBE + case UBLMesh: return F("UBL Bed Leveling"); + #endif + #if ENABLED(PROBE_MANUALLY) + case ManualMesh: return F("Mesh Bed Leveling"); + #endif + case Tune: return F("Tune"); + case PreheatHotend: return F("Preheat Hotend"); + } + return F(""); +} + +uint8_t CrealityDWINClass::Get_Menu_Size(uint8_t menu) { + switch (menu) { + case Prepare: return PREPARE_TOTAL; + case HomeMenu: return HOME_TOTAL; + case Move: return MOVE_TOTAL; + case ManualLevel: return MLEVEL_TOTAL; + #if HAS_ZOFFSET_ITEM + case ZOffset: return ZOFFSET_TOTAL; + #endif + #if HAS_PREHEAT + case Preheat: return PREHEAT_TOTAL; + #endif + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + case ChangeFilament: return CHANGEFIL_TOTAL; + #endif + #if HAS_CUSTOM_MENU + case MenuCustom: return CUSTOM_MENU_TOTAL; + #endif + case Control: return CONTROL_TOTAL; + case TempMenu: return TEMP_TOTAL; + #if HAS_HOTEND || HAS_HEATED_BED + case PID: return PID_TOTAL; + #endif + #if HAS_HOTEND + case HotendPID: return HOTENDPID_TOTAL; + #endif + #if HAS_HEATED_BED + case BedPID: return BEDPID_TOTAL; + #endif + #if HAS_PREHEAT + case Preheat1 ... CAT(Preheat, PREHEAT_COUNT): + return PREHEAT_SUBMENU_TOTAL; + #endif + case Motion: return MOTION_TOTAL; + case HomeOffsets: return HOMEOFFSETS_TOTAL; + case MaxSpeed: return SPEED_TOTAL; + case MaxAcceleration: return ACCEL_TOTAL; + #if HAS_CLASSIC_JERK + case MaxJerk: return JERK_TOTAL; + #endif + case Steps: return STEPS_TOTAL; + case Visual: return VISUAL_TOTAL; + case Advanced: return ADVANCED_TOTAL; + #if HAS_BED_PROBE + case ProbeMenu: return PROBE_TOTAL; + #endif + case Info: return INFO_TOTAL; + case InfoMain: return INFO_TOTAL; + #if ENABLED(AUTO_BED_LEVELING_UBL) && !HAS_BED_PROBE + case UBLMesh: return UBL_M_TOTAL; + #endif + #if ENABLED(PROBE_MANUALLY) + case ManualMesh: return MMESH_TOTAL; + #endif + #if HAS_MESH + case Leveling: return LEVELING_TOTAL; + case LevelView: return LEVELING_VIEW_TOTAL; + case LevelSettings: return LEVELING_SETTINGS_TOTAL; + case MeshViewer: return MESHVIEW_TOTAL; + case LevelManual: return LEVELING_M_TOTAL; + #endif + case Tune: return TUNE_TOTAL; + + #if HAS_PREHEAT && HAS_HOTEND + case PreheatHotend: return PREHEATHOTEND_TOTAL; + #endif + + case ColorSettings: return COLORSETTINGS_TOTAL; + } + return 0; +} + +/* Popup Config */ + +void CrealityDWINClass::Popup_Handler(PopupID popupid, bool option/*=false*/) { + popup = last_popup = popupid; + switch (popupid) { + case Pause: Draw_Popup(F("Pause Print"), F(""), F(""), Popup); break; + case Stop: Draw_Popup(F("Stop Print"), F(""), F(""), Popup); break; + case Resume: Draw_Popup(F("Resume Print?"), F("Looks Like the last"), F("print was interrupted."), Popup); break; + case ConfFilChange: Draw_Popup(F("Confirm Filament Change"), F(""), F(""), Popup); break; + case PurgeMore: Draw_Popup(F("Purge more filament?"), F("(Cancel to finish process)"), F(""), Popup); break; + case SaveLevel: Draw_Popup(F("Leveling Complete"), F("Save to EEPROM?"), F(""), Popup); break; + case MeshSlot: Draw_Popup(F("Mesh slot not selected"), F("(Confirm to select slot 0)"), F(""), Popup); break; + case ETemp: Draw_Popup(F("Nozzle is too cold"), F("Open Preheat Menu?"), F(""), Popup); break; + case ManualProbing: Draw_Popup(F("Manual Probing"), F("(Confirm to probe)"), F("(cancel to exit)"), Popup); break; + case Level: Draw_Popup(F("Auto Bed Leveling"), F("Please wait until done."), F(""), Wait, ICON_AutoLeveling); break; + case Home: Draw_Popup(option ? F("Parking") : F("Homing"), F("Please wait until done."), F(""), Wait, ICON_BLTouch); break; + case MoveWait: Draw_Popup(F("Moving to Point"), F("Please wait until done."), F(""), Wait, ICON_BLTouch); break; + case Heating: Draw_Popup(F("Heating"), F("Please wait until done."), F(""), Wait, ICON_BLTouch); break; + case FilLoad: Draw_Popup(option ? F("Unloading Filament") : F("Loading Filament"), F("Please wait until done."), F(""), Wait, ICON_BLTouch); break; + case FilChange: Draw_Popup(F("Filament Change"), F("Please wait for prompt."), F(""), Wait, ICON_BLTouch); break; + case TempWarn: Draw_Popup(option ? F("Nozzle temp too low!") : F("Nozzle temp too high!"), F(""), F(""), Wait, option ? ICON_TempTooLow : ICON_TempTooHigh); break; + case Runout: Draw_Popup(F("Filament Runout"), F(""), F(""), Wait, ICON_BLTouch); break; + case PIDWait: Draw_Popup(F("PID Autotune"), F("in process"), F("Please wait until done."), Wait, ICON_BLTouch); break; + case Resuming: Draw_Popup(F("Resuming Print"), F("Please wait until done."), F(""), Wait, ICON_BLTouch); break; + case Custom: Draw_Popup(F("Running Custom GCode"), F("Please wait until done."), F(""), Wait, ICON_BLTouch); break; + default: break; + } +} + +void CrealityDWINClass::Confirm_Handler(PopupID popupid) { + popup = popupid; + switch (popupid) { + case FilInsert: Draw_Popup(F("Insert Filament"), F("Press to Continue"), F(""), Confirm); break; + case HeaterTime: Draw_Popup(F("Heater Timed Out"), F("Press to Reheat"), F(""), Confirm); break; + case UserInput: Draw_Popup(F("Waiting for Input"), F("Press to Continue"), F(""), Confirm); break; + case LevelError: Draw_Popup(F("Couldn't enable Leveling"), F("(Valid mesh must exist)"), F(""), Confirm); break; + case InvalidMesh: Draw_Popup(F("Valid mesh must exist"), F("before tuning can be"), F("performed"), Confirm); break; + default: break; + } +} + +/* Navigation and Control */ + +void CrealityDWINClass::Main_Menu_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_CW && selection < PAGE_COUNT - 1) { + selection++; // Select Down + Main_Menu_Icons(); + } + else if (encoder_diffState == ENCODER_DIFF_CCW && selection > 0) { + selection--; // Select Up + Main_Menu_Icons(); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) + switch (selection) { + case PAGE_PRINT: card.mount(); Draw_SD_List(); break; + case PAGE_PREPARE: Draw_Menu(Prepare); break; + case PAGE_CONTROL: Draw_Menu(Control); break; + case PAGE_INFO_LEVELING: Draw_Menu(TERN(HAS_MESH, Leveling, InfoMain)); break; + } + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::Menu_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_CW && selection < Get_Menu_Size(active_menu)) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + selection++; // Select Down + if (selection > scrollpos+MROWS) { + scrollpos++; + DWIN_Frame_AreaMove(1, 2, MLINE, Color_Bg_Black, 0, 31, DWIN_WIDTH, 349); + Menu_Item_Handler(active_menu, selection); + } + DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.cursor_color, Rectangle_Color), 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + } + else if (encoder_diffState == ENCODER_DIFF_CCW && selection > 0) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + selection--; // Select Up + if (selection < scrollpos) { + scrollpos--; + DWIN_Frame_AreaMove(1, 3, MLINE, Color_Bg_Black, 0, 31, DWIN_WIDTH, 349); + Menu_Item_Handler(active_menu, selection); + } + DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.cursor_color, Rectangle_Color), 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) + Menu_Item_Handler(active_menu, selection, false); + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::Value_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_CW) + tempvalue += EncoderRate.encoderMoveValue; + else if (encoder_diffState == ENCODER_DIFF_CCW) + tempvalue -= EncoderRate.encoderMoveValue; + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + process = Menu; + EncoderRate.enabled = false; + Draw_Float(tempvalue / valueunit, selection - scrollpos, false, valueunit); + DWIN_UpdateLCD(); + if (active_menu == ZOffset && liveadjust) { + planner.synchronize(); + current_position.z += (tempvalue / valueunit - zoffsetvalue); + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + current_position.z = 0; + sync_plan_position(); + } + else if (active_menu == Tune && selection == TUNE_ZOFFSET) { + sprintf_P(cmd, PSTR("M290 Z%s"), dtostrf((tempvalue / valueunit - zoffsetvalue), 1, 3, str_1)); + gcode.process_subcommands_now(cmd); + } + if (TERN0(HAS_HOTEND, valuepointer == &thermalManager.temp_hotend[0].pid.Ki) || TERN0(HAS_HEATED_BED, valuepointer == &thermalManager.temp_bed.pid.Ki)) + tempvalue = scalePID_i(tempvalue); + if (TERN0(HAS_HOTEND, valuepointer == &thermalManager.temp_hotend[0].pid.Kd) || TERN0(HAS_HEATED_BED, valuepointer == &thermalManager.temp_bed.pid.Kd)) + tempvalue = scalePID_d(tempvalue); + switch (valuetype) { + case 0: *(float*)valuepointer = tempvalue / valueunit; break; + case 1: *(uint8_t*)valuepointer = tempvalue / valueunit; break; + case 2: *(uint16_t*)valuepointer = tempvalue / valueunit; break; + case 3: *(int16_t*)valuepointer = tempvalue / valueunit; break; + case 4: *(uint32_t*)valuepointer = tempvalue / valueunit; break; + case 5: *(int8_t*)valuepointer = tempvalue / valueunit; break; + } + switch (active_menu) { + case Move: + planner.synchronize(); + planner.buffer_line(current_position, manual_feedrate_mm_s[selection - 1], active_extruder); + break; + #if HAS_MESH + case ManualMesh: + planner.synchronize(); + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + planner.synchronize(); + break; + case UBLMesh: mesh_conf.manual_mesh_move(true); break; + case LevelManual: mesh_conf.manual_mesh_move(selection == LEVELING_M_OFFSET); break; + #endif + } + if (valuepointer == &planner.flow_percentage[0]) + planner.refresh_e_factor(0); + if (funcpointer) funcpointer(); + return; + } + NOLESS(tempvalue, (valuemin * valueunit)); + NOMORE(tempvalue, (valuemax * valueunit)); + Draw_Float(tempvalue / valueunit, selection - scrollpos, true, valueunit); + DWIN_UpdateLCD(); + if (active_menu == Move && livemove) { + *(float*)valuepointer = tempvalue / valueunit; + planner.buffer_line(current_position, manual_feedrate_mm_s[selection - 1], active_extruder); + } +} + +void CrealityDWINClass::Option_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_CW) + tempvalue += EncoderRate.encoderMoveValue; + else if (encoder_diffState == ENCODER_DIFF_CCW) + tempvalue -= EncoderRate.encoderMoveValue; + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + process = Menu; + EncoderRate.enabled = false; + if (valuepointer == &color_names) { + switch (selection) { + case COLORSETTINGS_CURSOR: eeprom_settings.cursor_color = tempvalue; break; + case COLORSETTINGS_SPLIT_LINE: eeprom_settings.menu_split_line = tempvalue; break; + case COLORSETTINGS_MENU_TOP_BG: eeprom_settings.menu_top_bg = tempvalue; break; + case COLORSETTINGS_MENU_TOP_TXT: eeprom_settings.menu_top_txt = tempvalue; break; + case COLORSETTINGS_HIGHLIGHT_BORDER: eeprom_settings.highlight_box = tempvalue; break; + case COLORSETTINGS_PROGRESS_PERCENT: eeprom_settings.progress_percent = tempvalue; break; + case COLORSETTINGS_PROGRESS_TIME: eeprom_settings.progress_time = tempvalue; break; + case COLORSETTINGS_PROGRESS_STATUS_BAR: eeprom_settings.status_bar_text = tempvalue; break; + case COLORSETTINGS_PROGRESS_STATUS_AREA: eeprom_settings.status_area_text = tempvalue; break; + case COLORSETTINGS_PROGRESS_COORDINATES: eeprom_settings.coordinates_text = tempvalue; break; + case COLORSETTINGS_PROGRESS_COORDINATES_LINE: eeprom_settings.coordinates_split_line = tempvalue; break; + } + Redraw_Screen(); + } + else if (valuepointer == &preheat_modes) + preheatmode = tempvalue; + + Draw_Option(tempvalue, static_cast(valuepointer), selection - scrollpos, false, (valuepointer == &color_names)); + DWIN_UpdateLCD(); + return; + } + NOLESS(tempvalue, valuemin); + NOMORE(tempvalue, valuemax); + Draw_Option(tempvalue, static_cast(valuepointer), selection - scrollpos, true); + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::File_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + static uint8_t filescrl = 0; + if (encoder_diffState == ENCODER_DIFF_NO) { + if (selection > 0) { + card.getfilename_sorted(SD_ORDER(selection - 1, card.get_num_Files())); + char * const filename = card.longest_filename(); + size_t len = strlen(filename); + int8_t pos = len; + if (!card.flag.filenameIsDir) + while (pos && filename[pos] != '.') pos--; + if (pos > MENU_CHAR_LIMIT) { + static millis_t time = 0; + if (PENDING(millis(), time)) return; + time = millis() + 200; + pos -= filescrl; + len = _MIN(pos, MENU_CHAR_LIMIT); + char name[len + 1]; + if (pos >= 0) { + LOOP_L_N(i, len) name[i] = filename[i + filescrl]; + } + else { + LOOP_L_N(i, MENU_CHAR_LIMIT + pos) name[i] = ' '; + LOOP_S_L_N(i, MENU_CHAR_LIMIT + pos, MENU_CHAR_LIMIT) name[i] = filename[i - (MENU_CHAR_LIMIT + pos)]; + } + name[len] = '\0'; + DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28); + Draw_Menu_Item(selection - scrollpos, card.flag.filenameIsDir ? ICON_More : ICON_File, name); + if (-pos >= MENU_CHAR_LIMIT) filescrl = 0; + filescrl++; + DWIN_UpdateLCD(); + } + } + return; + } + if (encoder_diffState == ENCODER_DIFF_CW && selection < card.get_num_Files()) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + if (selection > 0) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28); + Draw_SD_Item(selection, selection - scrollpos); + } + filescrl = 0; + selection++; // Select Down + if (selection > scrollpos + MROWS) { + scrollpos++; + DWIN_Frame_AreaMove(1, 2, MLINE, Color_Bg_Black, 0, 31, DWIN_WIDTH, 349); + Draw_SD_Item(selection, selection - scrollpos); + } + DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.cursor_color, Rectangle_Color), 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + } + else if (encoder_diffState == ENCODER_DIFF_CCW && selection > 0) { + DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28); + Draw_SD_Item(selection, selection - scrollpos); + filescrl = 0; + selection--; // Select Up + if (selection < scrollpos) { + scrollpos--; + DWIN_Frame_AreaMove(1, 3, MLINE, Color_Bg_Black, 0, 31, DWIN_WIDTH, 349); + Draw_SD_Item(selection, selection - scrollpos); + } + DWIN_Draw_Rectangle(1, GetColor(eeprom_settings.cursor_color, Rectangle_Color), 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (selection == 0) { + if (card.flag.workDirIsRoot) { + process = Main; + Draw_Main_Menu(); + } + else { + card.cdup(); + Draw_SD_List(); + } + } + else { + card.getfilename_sorted(SD_ORDER(selection - 1, card.get_num_Files())); + if (card.flag.filenameIsDir) { + card.cd(card.filename); + Draw_SD_List(); + } + else { + card.openAndPrintFile(card.filename); + } + } + } + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::Print_Screen_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_CW && selection < PRINT_COUNT - 1) { + selection++; // Select Down + Print_Screen_Icons(); + } + else if (encoder_diffState == ENCODER_DIFF_CCW && selection > 0) { + selection--; // Select Up + Print_Screen_Icons(); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (selection) { + case PRINT_SETUP: + Draw_Menu(Tune); + Update_Status_Bar(true); + break; + case PRINT_PAUSE_RESUME: + if (paused) { + if (sdprint) { + wait_for_user = false; + #if ENABLED(PARK_HEAD_ON_PAUSE) + card.startOrResumeFilePrinting(); + TERN_(POWER_LOSS_RECOVERY, recovery.prepare()); + #else + char cmd[20]; + #if HAS_HEATED_BED + sprintf_P(cmd, PSTR("M140 S%i"), pausebed); + gcode.process_subcommands_now(cmd); + #endif + #if HAS_EXTRUDERS + sprintf_P(cmd, PSTR("M109 S%i"), pausetemp); + gcode.process_subcommands_now(cmd); + #endif + TERN_(HAS_FAN, thermalManager.fan_speed[0] = pausefan); + planner.synchronize(); + TERN_(SDSUPPORT, queue.inject(F("M24"))); + #endif + } + else { + TERN_(HOST_ACTION_COMMANDS, hostui.resume()); + } + Draw_Print_Screen(); + } + else + Popup_Handler(Pause); + break; + case PRINT_STOP: Popup_Handler(Stop); break; + } + } + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::Popup_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_CW && selection < 1) { + selection++; + Popup_Select(); + } + else if (encoder_diffState == ENCODER_DIFF_CCW && selection > 0) { + selection--; + Popup_Select(); + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (popup) { + case Pause: + if (selection == 0) { + if (sdprint) { + #if ENABLED(POWER_LOSS_RECOVERY) + if (recovery.enabled) recovery.save(true); + #endif + #if ENABLED(PARK_HEAD_ON_PAUSE) + Popup_Handler(Home, true); + #if ENABLED(SDSUPPORT) + if (IS_SD_PRINTING()) card.pauseSDPrint(); + #endif + planner.synchronize(); + queue.inject(F("M125")); + planner.synchronize(); + #else + queue.inject(F("M25")); + TERN_(HAS_HOTEND, pausetemp = thermalManager.temp_hotend[0].target); + TERN_(HAS_HEATED_BED, pausebed = thermalManager.temp_bed.target); + TERN_(HAS_FAN, pausefan = thermalManager.fan_speed[0]); + thermalManager.cooldown(); + #endif + } + else { + TERN_(HOST_ACTION_COMMANDS, hostui.pause()); + } + } + Draw_Print_Screen(); + break; + case Stop: + if (selection == 0) { + if (sdprint) { + ui.abort_print(); + thermalManager.cooldown(); + } + else { + TERN_(HOST_ACTION_COMMANDS, hostui.cancel()); + } + } + else + Draw_Print_Screen(); + break; + case Resume: + if (selection == 0) + queue.inject(F("M1000")); + else { + queue.inject(F("M1000 C")); + Draw_Main_Menu(); + } + break; + + #if HAS_HOTEND + case ETemp: + if (selection == 0) { + thermalManager.setTargetHotend(EXTRUDE_MINTEMP, 0); + thermalManager.set_fan_speed(0, MAX_FAN_SPEED); + Draw_Menu(PreheatHotend); + } + else + Redraw_Menu(true, true, false); + break; + #endif + + #if HAS_BED_PROBE + case ManualProbing: + if (selection == 0) { + char buf[80]; + const float dif = probe.probe_at_point(current_position.x, current_position.y, PROBE_PT_STOW, 0, false) - corner_avg; + sprintf_P(buf, dif > 0 ? PSTR("Corner is %smm high") : PSTR("Corner is %smm low"), dtostrf(abs(dif), 1, 3, str_1)); + Update_Status(buf); + } + else { + Redraw_Menu(true, true, false); + Update_Status(""); + } + break; + #endif + + #if ENABLED(ADVANCED_PAUSE_FEATURE) + case ConfFilChange: + if (selection == 0) { + if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp) + Popup_Handler(ETemp); + else { + if (thermalManager.temp_hotend[0].is_below_target(-2)) { + Popup_Handler(Heating); + thermalManager.wait_for_hotend(0); + } + Popup_Handler(FilChange); + sprintf_P(cmd, PSTR("M600 B1 R%i"), thermalManager.temp_hotend[0].target); + gcode.process_subcommands_now(cmd); + } + } + else + Redraw_Menu(true, true, false); + break; + case PurgeMore: + if (selection == 0) { + pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; + Popup_Handler(FilChange); + } + else { + pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; + if (printing) Popup_Handler(Resuming); + else Redraw_Menu(true, true, (active_menu==PreheatHotend)); + } + break; + #endif // ADVANCED_PAUSE_FEATURE + + #if HAS_MESH + case SaveLevel: + if (selection == 0) { + #if ENABLED(AUTO_BED_LEVELING_UBL) + gcode.process_subcommands_now(F("G29 S")); + planner.synchronize(); + AudioFeedback(true); + #else + AudioFeedback(settings.save()); + #endif + } + Draw_Menu(Leveling, LEVELING_GET_MESH); + break; + #endif + + #if ENABLED(AUTO_BED_LEVELING_UBL) + case MeshSlot: + if (selection == 0) bedlevel.storage_slot = 0; + Redraw_Menu(true, true); + break; + #endif + default: break; + } + } + DWIN_UpdateLCD(); +} + +void CrealityDWINClass::Confirm_Control() { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (popup) { + case Complete: + Draw_Main_Menu(); + break; + case FilInsert: + Popup_Handler(FilChange); + wait_for_user = false; + break; + case HeaterTime: + Popup_Handler(Heating); + wait_for_user = false; + break; + default: + Redraw_Menu(true, true, false); + wait_for_user = false; + break; + } + } + DWIN_UpdateLCD(); +} + +/* In-Menu Value Modification */ + +void CrealityDWINClass::Setup_Value(float value, float min, float max, float unit, uint8_t type) { + if (TERN0(HAS_HOTEND, valuepointer == &thermalManager.temp_hotend[0].pid.Ki) || TERN0(HAS_HEATED_BED, valuepointer == &thermalManager.temp_bed.pid.Ki)) + tempvalue = unscalePID_i(value) * unit; + else if (TERN0(HAS_HOTEND, valuepointer == &thermalManager.temp_hotend[0].pid.Kd) || TERN0(HAS_HEATED_BED, valuepointer == &thermalManager.temp_bed.pid.Kd)) + tempvalue = unscalePID_d(value) * unit; + else + tempvalue = value * unit; + valuemin = min; + valuemax = max; + valueunit = unit; + valuetype = type; + process = Value; + EncoderRate.enabled = true; + Draw_Float(tempvalue / unit, selection - scrollpos, true, valueunit); +} + +void CrealityDWINClass::Modify_Value(float &value, float min, float max, float unit, void (*f)()/*=nullptr*/) { + valuepointer = &value; + funcpointer = f; + Setup_Value((float)value, min, max, unit, 0); +} +void CrealityDWINClass::Modify_Value(uint8_t &value, float min, float max, float unit, void (*f)()/*=nullptr*/) { + valuepointer = &value; + funcpointer = f; + Setup_Value((float)value, min, max, unit, 1); +} +void CrealityDWINClass::Modify_Value(uint16_t &value, float min, float max, float unit, void (*f)()/*=nullptr*/) { + valuepointer = &value; + funcpointer = f; + Setup_Value((float)value, min, max, unit, 2); +} +void CrealityDWINClass::Modify_Value(int16_t &value, float min, float max, float unit, void (*f)()/*=nullptr*/) { + valuepointer = &value; + funcpointer = f; + Setup_Value((float)value, min, max, unit, 3); +} +void CrealityDWINClass::Modify_Value(uint32_t &value, float min, float max, float unit, void (*f)()/*=nullptr*/) { + valuepointer = &value; + funcpointer = f; + Setup_Value((float)value, min, max, unit, 4); +} +void CrealityDWINClass::Modify_Value(int8_t &value, float min, float max, float unit, void (*f)()/*=nullptr*/) { + valuepointer = &value; + funcpointer = f; + Setup_Value((float)value, min, max, unit, 5); +} + +void CrealityDWINClass::Modify_Option(uint8_t value, const char * const * options, uint8_t max) { + tempvalue = value; + valuepointer = const_cast(options); + valuemin = 0; + valuemax = max; + process = Option; + EncoderRate.enabled = true; + Draw_Option(value, options, selection - scrollpos, true); +} + +/* Main Functions */ + +void CrealityDWINClass::Update_Status(const char * const text) { + if (strncmp_P(text, PSTR(""), 3) == 0) { + LOOP_L_N(i, _MIN((size_t)LONG_FILENAME_LENGTH, strlen(text))) filename[i] = text[i + 3]; + filename[_MIN((size_t)LONG_FILENAME_LENGTH - 1, strlen(text))] = '\0'; + Draw_Print_Filename(true); + } + else { + LOOP_L_N(i, _MIN((size_t)64, strlen(text))) statusmsg[i] = text[i]; + statusmsg[_MIN((size_t)64, strlen(text))] = '\0'; + } +} + +void CrealityDWINClass::Start_Print(bool sd) { + sdprint = sd; + if (!printing) { + printing = true; + statusmsg[0] = '\0'; + if (sd) { + #if ENABLED(POWER_LOSS_RECOVERY) + if (recovery.valid()) { + SdFile *diveDir = nullptr; + const char * const fname = card.diveToFile(true, diveDir, recovery.info.sd_filename); + card.selectFileByName(fname); + } + #endif + strcpy(filename, card.longest_filename()); + } + else + strcpy_P(filename, PSTR("Host Print")); + TERN_(LCD_SET_PROGRESS_MANUALLY, ui.set_progress(0)); + TERN_(USE_M73_REMAINING_TIME, ui.set_remaining_time(0)); + Draw_Print_Screen(); + } +} + +void CrealityDWINClass::Stop_Print() { + printing = false; + sdprint = false; + thermalManager.cooldown(); + TERN_(LCD_SET_PROGRESS_MANUALLY, ui.set_progress(100 * (PROGRESS_SCALE))); + TERN_(USE_M73_REMAINING_TIME, ui.set_remaining_time(0)); + Draw_Print_confirm(); +} + +void CrealityDWINClass::Update() { + State_Update(); + Screen_Update(); + switch (process) { + case Main: Main_Menu_Control(); break; + case Menu: Menu_Control(); break; + case Value: Value_Control(); break; + case Option: Option_Control(); break; + case File: File_Control(); break; + case Print: Print_Screen_Control(); break; + case Popup: Popup_Control(); break; + case Confirm: Confirm_Control(); break; + } +} + +void MarlinUI::update() { CrealityDWIN.Update(); } + +#if HAS_LCD_BRIGHTNESS + void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); } +#endif + +void CrealityDWINClass::State_Update() { + if ((print_job_timer.isRunning() || print_job_timer.isPaused()) != printing) { + if (!printing) Start_Print(card.isFileOpen() || TERN0(POWER_LOSS_RECOVERY, recovery.valid())); + else Stop_Print(); + } + if (print_job_timer.isPaused() != paused) { + paused = print_job_timer.isPaused(); + if (process == Print) Print_Screen_Icons(); + if (process == Wait && !paused) Redraw_Menu(true, true); + } + if (wait_for_user && !(process == Confirm) && !print_job_timer.isPaused()) + Confirm_Handler(UserInput); + #if ENABLED(ADVANCED_PAUSE_FEATURE) + if (process == Popup && popup == PurgeMore) { + if (pause_menu_response == PAUSE_RESPONSE_EXTRUDE_MORE) + Popup_Handler(FilChange); + else if (pause_menu_response == PAUSE_RESPONSE_RESUME_PRINT) { + if (printing) Popup_Handler(Resuming); + else Redraw_Menu(true, true, (active_menu==PreheatHotend)); + } + } + #endif + #if ENABLED(FILAMENT_RUNOUT_SENSOR) + static bool ranout = false; + if (runout.filament_ran_out != ranout) { + ranout = runout.filament_ran_out; + if (ranout) Popup_Handler(Runout); + } + #endif +} + +void CrealityDWINClass::Screen_Update() { + const millis_t ms = millis(); + static millis_t scrltime = 0; + if (ELAPSED(ms, scrltime)) { + scrltime = ms + 200; + Update_Status_Bar(); + if (process == Print) Draw_Print_Filename(); + } + + static millis_t statustime = 0; + if (ELAPSED(ms, statustime)) { + statustime = ms + 500; + Draw_Status_Area(); + } + + static millis_t printtime = 0; + if (ELAPSED(ms, printtime)) { + printtime = ms + 1000; + if (process == Print) { + Draw_Print_ProgressBar(); + Draw_Print_ProgressElapsed(); + TERN_(USE_M73_REMAINING_TIME, Draw_Print_ProgressRemain()); + } + } + + static bool mounted = card.isMounted(); + if (mounted != card.isMounted()) { + mounted = card.isMounted(); + if (process == File) + Draw_SD_List(); + } + + #if HAS_HOTEND + static int16_t hotendtarget = -1; + #endif + #if HAS_HEATED_BED + static int16_t bedtarget = -1; + #endif + #if HAS_FAN + static int16_t fanspeed = -1; + #endif + + #if HAS_ZOFFSET_ITEM + static float lastzoffset = zoffsetvalue; + if (zoffsetvalue != lastzoffset) { + lastzoffset = zoffsetvalue; + #if HAS_BED_PROBE + probe.offset.z = zoffsetvalue; + #else + set_home_offset(Z_AXIS, -zoffsetvalue); + #endif + } + + #if HAS_BED_PROBE + if (probe.offset.z != lastzoffset) + zoffsetvalue = lastzoffset = probe.offset.z; + #else + if (-home_offset.z != lastzoffset) + zoffsetvalue = lastzoffset = -home_offset.z; + #endif + #endif // HAS_ZOFFSET_ITEM + + if (process == Menu || process == Value) { + switch (active_menu) { + case TempMenu: + #if HAS_HOTEND + if (thermalManager.temp_hotend[0].target != hotendtarget) { + hotendtarget = thermalManager.temp_hotend[0].target; + if (scrollpos <= TEMP_HOTEND && TEMP_HOTEND <= scrollpos + MROWS) { + if (process != Value || selection != TEMP_HOTEND - scrollpos) + Draw_Float(thermalManager.temp_hotend[0].target, TEMP_HOTEND - scrollpos, false, 1); + } + } + #endif + #if HAS_HEATED_BED + if (thermalManager.temp_bed.target != bedtarget) { + bedtarget = thermalManager.temp_bed.target; + if (scrollpos <= TEMP_BED && TEMP_BED <= scrollpos + MROWS) { + if (process != Value || selection != TEMP_HOTEND - scrollpos) + Draw_Float(thermalManager.temp_bed.target, TEMP_BED - scrollpos, false, 1); + } + } + #endif + #if HAS_FAN + if (thermalManager.fan_speed[0] != fanspeed) { + fanspeed = thermalManager.fan_speed[0]; + if (scrollpos <= TEMP_FAN && TEMP_FAN <= scrollpos + MROWS) { + if (process != Value || selection != TEMP_HOTEND - scrollpos) + Draw_Float(thermalManager.fan_speed[0], TEMP_FAN - scrollpos, false, 1); + } + } + #endif + break; + case Tune: + #if HAS_HOTEND + if (thermalManager.temp_hotend[0].target != hotendtarget) { + hotendtarget = thermalManager.temp_hotend[0].target; + if (scrollpos <= TUNE_HOTEND && TUNE_HOTEND <= scrollpos + MROWS) { + if (process != Value || selection != TEMP_HOTEND - scrollpos) + Draw_Float(thermalManager.temp_hotend[0].target, TUNE_HOTEND - scrollpos, false, 1); + } + } + #endif + #if HAS_HEATED_BED + if (thermalManager.temp_bed.target != bedtarget) { + bedtarget = thermalManager.temp_bed.target; + if (scrollpos <= TUNE_BED && TUNE_BED <= scrollpos + MROWS) { + if (process != Value || selection != TEMP_HOTEND - scrollpos) + Draw_Float(thermalManager.temp_bed.target, TUNE_BED - scrollpos, false, 1); + } + } + #endif + #if HAS_FAN + if (thermalManager.fan_speed[0] != fanspeed) { + fanspeed = thermalManager.fan_speed[0]; + if (scrollpos <= TUNE_FAN && TUNE_FAN <= scrollpos + MROWS) { + if (process != Value || selection != TEMP_HOTEND - scrollpos) + Draw_Float(thermalManager.fan_speed[0], TUNE_FAN - scrollpos, false, 1); + } + } + #endif + break; + } + } +} + +void CrealityDWINClass::AudioFeedback(const bool success/*=true*/) { + if (ui.sound_on) + DONE_BUZZ(success); + else + Update_Status(success ? "Success" : "Failed"); +} + +void CrealityDWINClass::Save_Settings(char *buff) { + TERN_(AUTO_BED_LEVELING_UBL, eeprom_settings.tilt_grid_size = mesh_conf.tilt_grid - 1); + eeprom_settings.corner_pos = corner_pos * 10; + memcpy(buff, &eeprom_settings, _MIN(sizeof(eeprom_settings), eeprom_data_size)); +} + +void CrealityDWINClass::Load_Settings(const char *buff) { + memcpy(&eeprom_settings, buff, _MIN(sizeof(eeprom_settings), eeprom_data_size)); + TERN_(AUTO_BED_LEVELING_UBL, mesh_conf.tilt_grid = eeprom_settings.tilt_grid_size + 1); + if (eeprom_settings.corner_pos == 0) eeprom_settings.corner_pos = 325; + corner_pos = eeprom_settings.corner_pos / 10.0f; + Redraw_Screen(); + #if ENABLED(POWER_LOSS_RECOVERY) + static bool init = true; + if (init) { + init = false; + queue.inject(F("M1000 S")); + } + #endif +} + +void CrealityDWINClass::Reset_Settings() { + eeprom_settings.time_format_textual = false; + TERN_(AUTO_BED_LEVELING_UBL, eeprom_settings.tilt_grid_size = 0); + eeprom_settings.corner_pos = 325; + eeprom_settings.cursor_color = 0; + eeprom_settings.menu_split_line = 0; + eeprom_settings.menu_top_bg = 0; + eeprom_settings.menu_top_txt = 0; + eeprom_settings.highlight_box = 0; + eeprom_settings.progress_percent = 0; + eeprom_settings.progress_time = 0; + eeprom_settings.status_bar_text = 0; + eeprom_settings.status_area_text = 0; + eeprom_settings.coordinates_text = 0; + eeprom_settings.coordinates_split_line = 0; + TERN_(AUTO_BED_LEVELING_UBL, mesh_conf.tilt_grid = eeprom_settings.tilt_grid_size + 1); + corner_pos = eeprom_settings.corner_pos / 10.0f; + TERN_(SOUND_MENU_ITEM, ui.sound_on = ENABLED(SOUND_ON_DEFAULT)); + Redraw_Screen(); +} + +void MarlinUI::init_lcd() { + delay(800); + SERIAL_ECHOPGM("\nDWIN handshake "); + if (DWIN_Handshake()) SERIAL_ECHOLNPGM("ok."); else SERIAL_ECHOLNPGM("error."); + DWIN_Frame_SetDir(1); // Orientation 90° + DWIN_UpdateLCD(); // Show bootscreen (first image) + Encoder_Configuration(); + for (uint16_t t = 0; t <= 100; t += 2) { + DWIN_ICON_Show(ICON, ICON_Bar, 15, 260); + DWIN_Draw_Rectangle(1, Color_Bg_Black, 15 + t * 242 / 100, 260, 257, 280); + DWIN_UpdateLCD(); + delay(20); + } + + DWIN_JPG_ShowAndCache(3); + DWIN_JPG_CacheTo1(Language_English); + CrealityDWIN.Redraw_Screen(); +} + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + void MarlinUI::pause_show_message(const PauseMessage message, const PauseMode mode/*=PAUSE_MODE_SAME*/, const uint8_t extruder/*=active_extruder*/) { + switch (message) { + case PAUSE_MESSAGE_INSERT: CrealityDWIN.Confirm_Handler(FilInsert); break; + case PAUSE_MESSAGE_PURGE: + case PAUSE_MESSAGE_OPTION: CrealityDWIN.Popup_Handler(PurgeMore); break; + case PAUSE_MESSAGE_HEAT: CrealityDWIN.Confirm_Handler(HeaterTime); break; + case PAUSE_MESSAGE_WAITING: CrealityDWIN.Draw_Print_Screen(); break; + default: break; + } + } +#endif + +#endif // DWIN_CREALITY_LCD_JYERSUI diff --git a/src/lcd/e3v2/jyersui/dwin.h b/src/lcd/e3v2/jyersui/dwin.h new file mode 100644 index 0000000..8985647 --- /dev/null +++ b/src/lcd/e3v2/jyersui/dwin.h @@ -0,0 +1,245 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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/e3v2/jyersui/dwin.h + */ + +#include "dwin_lcd.h" +#include "../common/dwin_set.h" +#include "../common/dwin_font.h" +#include "../common/dwin_color.h" +#include "../common/encoder.h" +#include "../../../libs/BL24CXX.h" + +#include "../../../inc/MarlinConfigPre.h" + +//#define DWIN_CREALITY_LCD_CUSTOM_ICONS + +enum processID : uint8_t { + Main, Print, Menu, Value, Option, File, Popup, Confirm, Wait +}; + +enum PopupID : uint8_t { + Pause, Stop, Resume, SaveLevel, ETemp, ConfFilChange, PurgeMore, MeshSlot, + Level, Home, MoveWait, Heating, FilLoad, FilChange, TempWarn, Runout, PIDWait, Resuming, ManualProbing, + FilInsert, HeaterTime, UserInput, LevelError, InvalidMesh, UI, Complete, Custom +}; + +enum menuID : uint8_t { + MainMenu, + Prepare, + Move, + HomeMenu, + ManualLevel, + ZOffset, + Preheat, + ChangeFilament, + MenuCustom, + Control, + TempMenu, + PID, + HotendPID, + BedPID, + #if HAS_PREHEAT + #define _PREHEAT_ID(N) Preheat##N, + REPEAT_1(PREHEAT_COUNT, _PREHEAT_ID) + #endif + Motion, + HomeOffsets, + MaxSpeed, + MaxAcceleration, + MaxJerk, + Steps, + Visual, + ColorSettings, + Advanced, + ProbeMenu, + Info, + Leveling, + LevelManual, + LevelView, + MeshViewer, + LevelSettings, + ManualMesh, + UBLMesh, + InfoMain, + Tune, + PreheatHotend +}; + +// Custom icons +#if ENABLED(DWIN_CREALITY_LCD_CUSTOM_ICONS) + // index of every custom icon should be >= CUSTOM_ICON_START + #define CUSTOM_ICON_START ICON_Checkbox_F + #define ICON_Checkbox_F 200 + #define ICON_Checkbox_T 201 + #define ICON_Fade 202 + #define ICON_Mesh 203 + #define ICON_Tilt 204 + #define ICON_Brightness 205 + #define ICON_AxisD 249 + #define ICON_AxisBR 250 + #define ICON_AxisTR 251 + #define ICON_AxisBL 252 + #define ICON_AxisTL 253 + #define ICON_AxisC 254 +#else + #define ICON_Fade ICON_Version + #define ICON_Mesh ICON_Version + #define ICON_Tilt ICON_Version + #define ICON_Brightness ICON_Version + #define ICON_AxisD ICON_Axis + #define ICON_AxisBR ICON_Axis + #define ICON_AxisTR ICON_Axis + #define ICON_AxisBL ICON_Axis + #define ICON_AxisTL ICON_Axis + #define ICON_AxisC ICON_Axis +#endif + +enum colorID : uint8_t { + Default, White, Green, Cyan, Blue, Magenta, Red, Orange, Yellow, Brown, Black +}; + +#define Custom_Colors 10 +#define Color_Aqua RGB(0x00,0x3F,0x1F) +#define Color_Light_White 0xBDD7 +#define Color_Green RGB(0x00,0x3F,0x00) +#define Color_Light_Green 0x3460 +#define Color_Cyan 0x07FF +#define Color_Light_Cyan 0x04F3 +#define Color_Blue 0x015F +#define Color_Light_Blue 0x3A6A +#define Color_Magenta 0xF81F +#define Color_Light_Magenta 0x9813 +#define Color_Light_Red 0x8800 +#define Color_Orange 0xFA20 +#define Color_Light_Orange 0xFBC0 +#define Color_Light_Yellow 0x8BE0 +#define Color_Brown 0xCC27 +#define Color_Light_Brown 0x6204 +#define Color_Black 0x0000 +#define Color_Grey 0x18E3 +#define Check_Color 0x4E5C // Check-box check color +#define Confirm_Color 0x34B9 +#define Cancel_Color 0x3186 + +class CrealityDWINClass { +public: + static constexpr size_t eeprom_data_size = 48; + static struct EEPROM_Settings { // use bit fields to save space, max 48 bytes + bool time_format_textual : 1; + #if ENABLED(AUTO_BED_LEVELING_UBL) + uint8_t tilt_grid_size : 3; + #endif + uint16_t corner_pos : 10; + uint8_t cursor_color : 4; + uint8_t menu_split_line : 4; + uint8_t menu_top_bg : 4; + uint8_t menu_top_txt : 4; + uint8_t highlight_box : 4; + uint8_t progress_percent : 4; + uint8_t progress_time : 4; + uint8_t status_bar_text : 4; + uint8_t status_area_text : 4; + uint8_t coordinates_text : 4; + uint8_t coordinates_split_line : 4; + } eeprom_settings; + + static constexpr const char * const color_names[11] = { "Default", "White", "Green", "Cyan", "Blue", "Magenta", "Red", "Orange", "Yellow", "Brown", "Black" }; + static constexpr const char * const preheat_modes[3] = { "Both", "Hotend", "Bed" }; + + static void Clear_Screen(uint8_t e=3); + static void Draw_Float(float value, uint8_t row, bool selected=false, uint8_t minunit=10); + static void Draw_Option(uint8_t value, const char * const * options, uint8_t row, bool selected=false, bool color=false); + static uint16_t GetColor(uint8_t color, uint16_t original, bool light=false); + static void Draw_Checkbox(uint8_t row, bool value); + static void Draw_Title(const char * title); + static void Draw_Title(FSTR_P const title); + static void Draw_Menu_Item(uint8_t row, uint8_t icon=0, const char * const label1=nullptr, const char * const label2=nullptr, bool more=false, bool centered=false); + static void Draw_Menu_Item(uint8_t row, uint8_t icon=0, FSTR_P const flabel1=nullptr, FSTR_P const flabel2=nullptr, bool more=false, bool centered=false); + static void Draw_Menu(uint8_t menu, uint8_t select=0, uint8_t scroll=0); + static void Redraw_Menu(bool lastprocess=true, bool lastselection=false, bool lastmenu=false); + static void Redraw_Screen(); + + static void Main_Menu_Icons(); + static void Draw_Main_Menu(uint8_t select=0); + static void Print_Screen_Icons(); + static void Draw_Print_Screen(); + static void Draw_Print_Filename(const bool reset=false); + static void Draw_Print_ProgressBar(); + #if ENABLED(USE_M73_REMAINING_TIME) + static void Draw_Print_ProgressRemain(); + #endif + static void Draw_Print_ProgressElapsed(); + static void Draw_Print_confirm(); + static void Draw_SD_Item(uint8_t item, uint8_t row); + static void Draw_SD_List(bool removed=false); + static void Draw_Status_Area(bool icons=false); + static void Draw_Popup(FSTR_P const line1, FSTR_P const line2, FSTR_P const line3, uint8_t mode, uint8_t icon=0); + static void Popup_Select(); + static void Update_Status_Bar(bool refresh=false); + + #if ENABLED(AUTO_BED_LEVELING_UBL) + static void Draw_Bed_Mesh(int16_t selected = -1, uint8_t gridline_width = 1, uint16_t padding_x = 8, uint16_t padding_y_top = 40 + 53 - 7); + static void Set_Mesh_Viewer_Status(); + #endif + + static FSTR_P Get_Menu_Title(uint8_t menu); + static uint8_t Get_Menu_Size(uint8_t menu); + static void Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw=true); + + static void Popup_Handler(PopupID popupid, bool option = false); + static void Confirm_Handler(PopupID popupid); + + static void Main_Menu_Control(); + static void Menu_Control(); + static void Value_Control(); + static void Option_Control(); + static void File_Control(); + static void Print_Screen_Control(); + static void Popup_Control(); + static void Confirm_Control(); + + static void Setup_Value(float value, float min, float max, float unit, uint8_t type); + static void Modify_Value(float &value, float min, float max, float unit, void (*f)()=nullptr); + static void Modify_Value(uint8_t &value, float min, float max, float unit, void (*f)()=nullptr); + static void Modify_Value(uint16_t &value, float min, float max, float unit, void (*f)()=nullptr); + static void Modify_Value(int16_t &value, float min, float max, float unit, void (*f)()=nullptr); + static void Modify_Value(uint32_t &value, float min, float max, float unit, void (*f)()=nullptr); + static void Modify_Value(int8_t &value, float min, float max, float unit, void (*f)()=nullptr); + static void Modify_Option(uint8_t value, const char * const * options, uint8_t max); + + static void Update_Status(const char * const text); + static void Start_Print(bool sd); + static void Stop_Print(); + static void Update(); + static void State_Update(); + static void Screen_Update(); + static void AudioFeedback(const bool success=true); + static void Save_Settings(char *buff); + static void Load_Settings(const char *buff); + static void Reset_Settings(); +}; + +extern CrealityDWINClass CrealityDWIN; diff --git a/src/lcd/e3v2/jyersui/dwin_lcd.cpp b/src/lcd/e3v2/jyersui/dwin_lcd.cpp new file mode 100644 index 0000000..04889e9 --- /dev/null +++ b/src/lcd/e3v2/jyersui/dwin_lcd.cpp @@ -0,0 +1,64 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/******************************************************************************** + * @file lcd/e3v2/jyersui/dwin_lcd.cpp + * @brief DWIN screen control functions + ********************************************************************************/ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_CREALITY_LCD_JYERSUI) + +#include "dwin_lcd.h" + +/*-------------------------------------- System variable function --------------------------------------*/ + +void DWIN_Startup() {} + +/*---------------------------------------- Drawing functions ----------------------------------------*/ + +// Draw the degree (°) symbol +// Color: color +// x/y: Upper-left coordinate of the first pixel +void DWIN_Draw_DegreeSymbol(uint16_t Color, uint16_t x, uint16_t y) { + DWIN_Draw_Point(Color, 1, 1, x + 1, y); + DWIN_Draw_Point(Color, 1, 1, x + 2, y); + DWIN_Draw_Point(Color, 1, 1, x, y + 1); + DWIN_Draw_Point(Color, 1, 1, x + 3, y + 1); + DWIN_Draw_Point(Color, 1, 1, x, y + 2); + DWIN_Draw_Point(Color, 1, 1, x + 3, y + 2); + DWIN_Draw_Point(Color, 1, 1, x + 1, y + 3); + DWIN_Draw_Point(Color, 1, 1, x + 2, y + 3); +} + +/*---------------------------------------- Picture related functions ----------------------------------------*/ + +// Draw an Icon +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + DWIN_ICON_Show(true, false, false, libID, picID, x, y); +} + +#endif // DWIN_CREALITY_LCD_JYERSUI diff --git a/src/lcd/e3v2/jyersui/dwin_lcd.h b/src/lcd/e3v2/jyersui/dwin_lcd.h new file mode 100644 index 0000000..f76cfb5 --- /dev/null +++ b/src/lcd/e3v2/jyersui/dwin_lcd.h @@ -0,0 +1,34 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/******************************************************************************** + * @file lcd/e3v2/jyersui/dwin_lcd.h + * @brief DWIN screen control functions + ********************************************************************************/ + +#include "../common/dwin_api.h" + +// Draw the degree (°) symbol +// Color: color +// x/y: Upper-left coordinate of the first pixel +void DWIN_Draw_DegreeSymbol(uint16_t Color, uint16_t x, uint16_t y); diff --git a/src/lcd/e3v2/marlinui/dwin_lcd.cpp b/src/lcd/e3v2/marlinui/dwin_lcd.cpp new file mode 100644 index 0000000..7154270 --- /dev/null +++ b/src/lcd/e3v2/marlinui/dwin_lcd.cpp @@ -0,0 +1,63 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/******************************************************************************** + * @file lcd/e3v2/marlinui/dwin_lcd.cpp + * @brief DWIN screen control functions + ********************************************************************************/ + +#include "../../../inc/MarlinConfigPre.h" + +#if IS_DWIN_MARLINUI + +#include "../../../inc/MarlinConfig.h" + +#include "dwin_lcd.h" +#include // for memset + +//#define DEBUG_OUT 1 +#include "../../../core/debug_out.h" + +/*-------------------------------------- System variable function --------------------------------------*/ + +void DWIN_Startup() { + DEBUG_ECHOPGM("\r\nDWIN handshake "); + delay(750); // Delay here or init later in the boot process + const bool success = DWIN_Handshake(); + if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error."); + DWIN_Frame_SetDir(TERN(DWIN_MARLINUI_LANDSCAPE, 0, 1)); + DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here + DWIN_JPG_ShowAndCache(3); + DWIN_UpdateLCD(); +} + +/*---------------------------------------- Picture related functions ----------------------------------------*/ + +// Draw an Icon +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + DWIN_ICON_Show(true, false, false, libID, picID, x, y); +} + +#endif // IS_DWIN_MARLINUI diff --git a/src/lcd/e3v2/marlinui/dwin_lcd.h b/src/lcd/e3v2/marlinui/dwin_lcd.h new file mode 100644 index 0000000..dc6c79b --- /dev/null +++ b/src/lcd/e3v2/marlinui/dwin_lcd.h @@ -0,0 +1,82 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/******************************************************************************** + * @file lcd/e3v2/marlinui/dwin_lcd.h + * @brief DWIN screen control functions + ********************************************************************************/ + +#include "../../../inc/MarlinConfigPre.h" + +#include "../common/dwin_api.h" + +// Picture ID +#define DWIN_Boot_Horiz 0 +#define DWIN_Boot_Vert 1 +#define DWIN_MarlinUI_Assets 2 + +// ICON ID +#define BOOT_ICON 3 // Icon set file 3.ICO +#define ICON 4 // Icon set file 4.ICO + +// MarlinUI Boot Icons from Set 3 +#define ICON_MarlinBoot 0 +#define ICON_OpenSource 1 +#define ICON_GitHubURL 2 +#define ICON_MarlinURL 3 +#define ICON_Copyright 4 + +// MarlinUI Icons from Set 4 +#define ICON_LOGO_Marlin 0 +#define ICON_HotendOff 1 +#define ICON_HotendOn 2 +#define ICON_BedOff 3 +#define ICON_BedOn 4 +#define ICON_Fan0 5 +#define ICON_Fan1 6 +#define ICON_Fan2 7 +#define ICON_Fan3 8 +#define ICON_Halted 9 +#define ICON_Question 10 +#define ICON_Alert 11 +#define ICON_RotateCW 12 +#define ICON_RotateCCW 13 +#define ICON_UpArrow 14 +#define ICON_DownArrow 15 +#define ICON_BedLine 16 +#define ICON_BedLevelOff 17 +#define ICON_BedLevelOn 18 + +#include "../common/dwin_font.h" + +#define DWIN_FONT_MENU font10x20 +#define DWIN_FONT_STAT font14x28 +#define DWIN_FONT_ALERT font14x28 + +#include "../common/dwin_color.h" + +#define Color_Bg_Heading 0x3344 // Static Heading + +// Character matrix width x height +//#define LCD_WIDTH ((DWIN_WIDTH) / 8) +//#define LCD_HEIGHT ((DWIN_HEIGHT) / 12) diff --git a/src/lcd/e3v2/marlinui/dwin_string.cpp b/src/lcd/e3v2/marlinui/dwin_string.cpp new file mode 100644 index 0000000..38a8eaf --- /dev/null +++ b/src/lcd/e3v2/marlinui/dwin_string.cpp @@ -0,0 +1,182 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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/MarlinConfig.h" + +#if IS_DWIN_MARLINUI + +#include "dwin_string.h" +//#include "../../fontutils.h" + +char DWIN_String::data[]; +uint16_t DWIN_String::span; +uint8_t DWIN_String::length; + +void DWIN_String::set() { + //*data = 0x00; + memset(data, 0x00, sizeof(data)); + span = 0; + length = 0; +} + +uint8_t read_byte(const uint8_t *byte) { return *byte; } + +/** + * Add a string, applying substitutions for the following characters: + * + * $ displays the clipped string given by fstr or cstr + * = displays '0'....'10' for indexes 0 - 10 + * ~ displays '1'....'11' for indexes 0 - 10 + * * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL) + * @ displays an axis name such as XYZUVW, or E for an extruder + */ +void DWIN_String::add(const char *tpl, const int8_t index, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/) { + lchar_t wc; + + while (*tpl) { + tpl = get_utf8_value_cb(tpl, read_byte, wc); + if (wc > 255) wc |= 0x0080; + const uint8_t ch = uint8_t(wc & 0x00FF); + + if (ch == '=' || ch == '~' || ch == '*') { + if (index >= 0) { + int8_t inum = index + ((ch == '=') ? 0 : LCD_FIRST_TOOL); + if (ch == '*') add_character('E'); + if (inum >= 10) { add_character('0' + (inum / 10)); inum %= 10; } + add_character('0' + inum); + } + else + add(index == -2 ? GET_TEXT_F(MSG_CHAMBER) : GET_TEXT_F(MSG_BED)); + } + else if (ch == '$' && fstr) + add(fstr); + else if (ch == '$' && cstr) + add(cstr); + else if (ch == '@') + add_character(AXIS_CHAR(index)); + else + add_character(ch); + } + eol(); +} + +void DWIN_String::add(const char *cstr, uint8_t max_len/*=MAX_STRING_LENGTH*/) { + lchar_t wc; + while (*cstr && max_len) { + cstr = get_utf8_value_cb(cstr, read_byte, wc); + /* + if (wc > 255) wc |= 0x0080; + const uint8_t ch = uint8_t(wc & 0x00FF); + add_character(ch); + */ + add(wc); + max_len--; + } + eol(); +} + +void DWIN_String::add(const lchar_t &wc) { + int ret; + size_t idx = 0; + dwin_charmap_t pinval; + dwin_charmap_t *copy_address = nullptr; + pinval.uchar = wc; + pinval.idx = -1; + + // For 8-bit ASCII just print the single character + char str[] = { '?', 0 }; + if (wc < 255) { + str[0] = (char)wc; + } + else { + copy_address = nullptr; + ret = pf_bsearch_r((void *)g_dwin_charmap_device, COUNT(g_dwin_charmap_device), pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx); + if (ret >= 0) { + copy_address = (dwin_charmap_t*)(g_dwin_charmap_device + idx); + } + else { + ret = pf_bsearch_r((void *)g_dwin_charmap_common, COUNT(g_dwin_charmap_common), pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx); + if (ret >= 0) + copy_address = (dwin_charmap_t*)(g_dwin_charmap_common + idx); + } + if (ret >= 0) { + dwin_charmap_t localval; + memcpy_P(&localval, copy_address, sizeof(localval)); + str[0] = localval.idx; + str[1] = localval.idx2; + } + } + if (str[0]) add_character(str[0]); + if (str[1]) add_character(str[1]); +} + +void DWIN_String::add_character(const char character) { + if (length < MAX_STRING_LENGTH) { + data[length] = character; + length++; + //span += glyph(character)->DWidth; + } +} + +void DWIN_String::rtrim(const char character) { + while (length) { + if (data[length - 1] == 0x20 || data[length - 1] == character) { + length--; + //span -= glyph(data[length])->DWidth; + eol(); + } + else + break; + } +} + +void DWIN_String::ltrim(const char character) { + uint16_t i, j; + for (i = 0; (i < length) && (data[i] == 0x20 || data[i] == character); i++) { + //span -= glyph(data[i])->DWidth; + } + if (i == 0) return; + for (j = 0; i < length; data[j++] = data[i++]); + length = j; + eol(); +} + +void DWIN_String::trim(const char character) { + rtrim(character); + ltrim(character); +} + +/* return v1 - v2 */ +int dwin_charmap_compare(dwin_charmap_t *v1, dwin_charmap_t *v2) { + return (v1->uchar < v2->uchar) ? -1 : (v1->uchar > v2->uchar) ? 1 : 0; +} + +int pf_bsearch_cb_comp_dwinmap_pgm(void *userdata, size_t idx, void * data_pin) { + dwin_charmap_t localval; + dwin_charmap_t *p_dwin_charmap = (dwin_charmap_t *)userdata; + memcpy_P(&localval, p_dwin_charmap + idx, sizeof(localval)); + return dwin_charmap_compare(&localval, (dwin_charmap_t *)data_pin); +} + +DWIN_String dwin_string; + +#endif // IS_DWIN_MARLINUI diff --git a/src/lcd/e3v2/marlinui/dwin_string.h b/src/lcd/e3v2/marlinui/dwin_string.h new file mode 100644 index 0000000..686b1aa --- /dev/null +++ b/src/lcd/e3v2/marlinui/dwin_string.h @@ -0,0 +1,1050 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +// TODO: Make AVR-compatible with separate ROM / RAM string methods + +#include "../../fontutils.h" +#include "../../marlinui.h" + +#include + +typedef struct _dwin_charmap_t { + lchar_t uchar; // the unicode char + uint8_t idx; // the glyph of the char in the ROM + uint8_t idx2; // the char used to be combined with the idx to simulate a single char +} dwin_charmap_t; + +#define MAX_STRING_LENGTH 64 + +#define S(V) (char*)(V) + +class DWIN_String { + private: + //static glyph_t *glyphs[256]; + //static font_t *font_header; + + static char data[MAX_STRING_LENGTH + 1]; + static uint16_t span; // in pixels + + static void add_character(const char character); + static void eol() { data[length] = 0x00; } + + public: + static uint8_t length; // in characters + //static void set_font(const uint8_t *font); + //static void add_glyphs(const uint8_t *font); + + //static font_t *font() { return font_header; }; + //static uint16_t font_height() { return font_header->FontAscent - font_header->FontDescent; } + //static glyph_t *glyph(uint8_t character) { return glyphs[character] ?: glyphs[0x3F]; } /* Use '?' for unknown glyphs */ + //static glyph_t *glyph(uint8_t *character) { return glyph(*character); } + + /** + * @brief Set the string empty + */ + static void set(); + + //static void add(const char character) { add_character(character); eol(); } + + /** + * @brief Append a UTF-8 character + * + * @param wc The UTF-8 character + */ + static void add(const lchar_t &wc); + static void set(const lchar_t &wc) { set(); add(wc); } + + /** + * @brief Append / Set C-string + * + * @param cstr The string + * @param max_len Character limit + */ + static void add(const char *cstr, uint8_t max_len=MAX_STRING_LENGTH); + static void set(const char *cstr) { set(); add(cstr); } + + /** + * @brief Append / Set F-string + * + * @param fstr The string + * @param max_len Character limit + */ + static void add(FSTR_P const fstr, uint8_t max_len=MAX_STRING_LENGTH) { add(FTOP(fstr), max_len); } + static void set(FSTR_P const fstr) { set(FTOP(fstr)); } + + /** + * @brief Append / Set C-string with optional substitution + * + * @param tpl A string with optional substitution + * @param index An index + * @param cstr An SRAM C-string to use for $ substitution + * @param fstr A ROM F-string to use for $ substitution + */ + static void add(const char *tpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr); + static void set(const char *tpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { set(); add(tpl, index, cstr, fstr); } + + /** + * @brief Append / Set F-string with optional substitution + * + * @param ftpl A ROM F-string with optional substitution + * @param index An index + * @param cstr An SRAM C-string to use for $ substitution + * @param fstr A ROM F-string to use for $ substitution + */ + static void add(FSTR_P const ftpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { add(FTOP(ftpl), index, cstr, fstr); } + static void set(FSTR_P const ftpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { set(); add(ftpl, index, cstr, fstr); } + + // Common string ops + static void trim(const char character=' '); + static void rtrim(const char character=' '); + static void ltrim(const char character=' '); + static void truncate(const uint8_t maxlen) { if (length > maxlen) { length = maxlen; eol(); } } + + // Accessors + static char *string() { return data; } + static uint16_t width() { return span; } + static uint16_t center(const uint16_t width) { return span > width ? 0 : (width - span) / 2; } +}; + +int dwin_charmap_compare(dwin_charmap_t *v1, dwin_charmap_t *v2); +int pf_bsearch_cb_comp_dwinmap_pgm(void *userdata, size_t idx, void *data_pin); + +extern DWIN_String dwin_string; + +#ifdef __AVR__ + #define IV(a) U##a +#else + #define IV(a) L##a +#endif + +const dwin_charmap_t g_dwin_charmap_device[] PROGMEM = { + // sorted by uchar: + #if DISPLAY_CHARSET_HD44780 == JAPANESE + + {IV('¢'), 0xEC, 0}, // A2 + {IV('°'), 0xDF, 0}, // B0, Marlin special: '°' LCD_STR_DEGREE (0x09) + {IV('ä'), 0xE1, 0}, // E4 + {IV('ö'), 0xEF, 0}, // F6 + {IV('÷'), 0xFD, 0}, // 00F7 + {IV('ü'), 0xF5, 0}, // 00FC + {IV('ˣ'), 0xEB, 0}, // 02E3 + + {IV('·'), 0xA5, 0}, // 0387 + {IV('Ώ'), 0xF4, 0}, // 038F + {IV('Θ'), 0xF2, 0}, // 0398, Theta + {IV('Ξ'), 0xE3, 0}, // 039E, Xi + {IV('Σ'), 0xF6, 0}, // 03A3, Sigma + {IV('Ω'), 0xF4, 0}, // 03A9, Omega + {IV('ά'), 0xE0, 0}, // 03AC + {IV('έ'), 0xE3, 0}, // 03AD + {IV('α'), 0xE0, 0}, // 03B1, alpha + {IV('β'), 0xE2, 0}, // 03B2, beta + {IV('ε'), 0xE3, 0}, // 03B5, epsilon + {IV('θ'), 0xF2, 0}, // 03B8, theta + {IV('μ'), 0xE4, 0}, // 03BC, mu + {IV('ξ'), 0xE3, 0}, // 03BE, xi + {IV('π'), 0xF7, 0}, // 03C0, pi + {IV('ρ'), 0xE6, 0}, // 03C1, rho + {IV('σ'), 0xE5, 0}, // 03C3, sigma + + {IV('←'), 0x7F, 0}, // 2190 + {IV('→'), 0x7E, 0}, // 2192, Marlin special: '⮈⮉⮊⮋➤→' LCD_STR_ARROW_RIGHT (0x03) + {IV('√'), 0xE8, 0}, // 221A + {IV('∞'), 0xF3, 0}, // 221E + {IV('█'), 0xFF, 0}, // 2588 + + //{IV(''), 0xA0, 0}, + {IV('。'), 0xA1, 0}, + {IV('「'), 0xA2, 0}, + {IV('」'), 0xA3, 0}, + {IV('゛'), 0xDE, 0}, // ‶ + {IV('゜'), 0xDF, 0}, // '〫' + {IV('゠'), '=', 0}, + {IV('ァ'), 0xA7, 0}, + {IV('ア'), 0xB1, 0}, + {IV('ィ'), 0xA8, 0}, + {IV('イ'), 0xB2, 0}, + {IV('ゥ'), 0xA9, 0}, + {IV('ウ'), 0xB3, 0}, + {IV('ェ'), 0xAA, 0}, + {IV('エ'), 0xB4, 0}, + {IV('ォ'), 0xAB, 0}, + + {IV('オ'), 0xB5, 0}, + {IV('カ'), 0xB6, 0}, + {IV('ガ'), 0xB6, 0xDE}, + {IV('キ'), 0xB7, 0}, + {IV('ギ'), 0xB7, 0xDE}, + {IV('ク'), 0xB8, 0}, + {IV('グ'), 0xB8, 0xDE}, + {IV('ケ'), 0xB9, 0}, + {IV('ゲ'), 0xB9, 0xDE}, + {IV('コ'), 0xBA, 0}, + {IV('ゴ'), 0xBA, 0xDE}, + {IV('サ'), 0xBB, 0}, + {IV('ザ'), 0xBB, 0xDE}, + {IV('シ'), 0xBC, 0}, + {IV('ジ'), 0xBC, 0xDE}, + {IV('ス'), 0xBD, 0}, + {IV('ズ'), 0xBD, 0xDE}, + {IV('セ'), 0xBE, 0}, + {IV('ゼ'), 0xBE, 0xDE}, + {IV('ソ'), 0xBF, 0}, + {IV('ゾ'), 0xBF, 0xDE}, + + {IV('タ'), 0xC0, 0}, + {IV('ダ'), 0xC0, 0xDE}, + {IV('チ'), 0xC1, 0}, + {IV('ヂ'), 0xC1, 0xDE}, + {IV('ッ'), 0xAF, 0}, + {IV('ツ'), 0xC2, 0}, + {IV('ヅ'), 0xC2, 0xDE}, + {IV('テ'), 0xC3, 0}, + {IV('デ'), 0xC3, 0xDE}, + {IV('ト'), 0xC4, 0}, + {IV('ド'), 0xC4, 0xDE}, + {IV('ナ'), 0xC5, 0}, + {IV('ニ'), 0xC6, 0}, + {IV('ヌ'), 0xC7, 0}, + {IV('ネ'), 0xC8, 0}, + {IV('ノ'), 0xC9, 0}, + {IV('ハ'), 0xCA, 0}, + {IV('バ'), 0xCA, 0xDE}, + {IV('パ'), 0xCA, 0xDF}, + {IV('ヒ'), 0xCB, 0}, + {IV('ビ'), 0xCB, 0xDE}, + {IV('ピ'), 0xCB, 0xDF}, + {IV('フ'), 0xCC, 0}, + {IV('ブ'), 0xCC, 0xDE}, + {IV('プ'), 0xCC, 0xDF}, + {IV('ヘ'), 0xCD, 0}, + {IV('ベ'), 0xCD, 0xDE}, + {IV('ペ'), 0xCD, 0xDF}, + {IV('ホ'), 0xCE, 0}, + {IV('ボ'), 0xCE, 0xDE}, + {IV('ポ'), 0xCE, 0xDF}, + {IV('マ'), 0xCF, 0}, + + {IV('ミ'), 0xD0, 0}, + {IV('ム'), 0xD1, 0}, + {IV('メ'), 0xD2, 0}, + {IV('モ'), 0xD3, 0}, + {IV('ャ'), 0xAC, 0}, + {IV('ヤ'), 0xD4, 0}, + {IV('ュ'), 0xAD, 0}, + {IV('ユ'), 0xD5, 0}, + {IV('ョ'), 0xAE, 0}, + {IV('ヨ'), 0xD6, 0}, + {IV('ラ'), 0xD7, 0}, + {IV('リ'), 0xD8, 0}, + {IV('ル'), 0xD9, 0}, + {IV('レ'), 0xDA, 0}, + {IV('ロ'), 0xDB, 0}, + {IV('ワ'), 0xDC, 0}, + {IV('ヲ'), 0xA6, 0}, + {IV('ン'), 0xDD, 0}, + {IV('ヴ'), 0xB3, 0xDE}, + {IV('ヷ'), 0xDC, 0xDE}, + {IV('ヺ'), 0xA6, 0xDE}, + {IV('・'), 0xA5, 0}, + {IV('ー'), 0xB0, 0}, + {IV('ヽ'), 0xA4, 0}, + + //{IV('g'), 0xE7, 0}, // error + //{IV(''), 0xE9, 0}, + //{IV('j'), 0xEA, 0}, // error + //{IV(''), 0xED, 0}, + //{IV(''), 0xEE, 0}, + + //{IV('p'), 0xF0, 0}, // error + //{IV('q'), 0xF1, 0}, // error + //{IV(''), 0xF8, 0}, + //{IV('y'), 0xF9, 0}, // error + {IV('万'), 0xFB, 0}, + {IV('円'), 0xFC, 0}, + {IV('千'), 0xFA, 0}, + //{IV(''), 0xFE, 0}, + + //、・ヲァィゥェォャュョッー + {IV('、'), 0xA4, 0}, //ヽ + {IV('・'), 0xA5, 0}, //・ + {IV('ヲ'), 0xA6, 0}, //ヲ + {IV('ァ'), 0xA7, 0}, //ァ + {IV('ィ'), 0xA8, 0}, //ィ + {IV('ゥ'), 0xA9, 0}, //ゥ + {IV('ェ'), 0xAA, 0}, //ェ + {IV('ォ'), 0xAB, 0}, //ォ + {IV('ャ'), 0xAC, 0}, //ャ + {IV('ュ'), 0xAD, 0}, //ュ + {IV('ョ'), 0xAE, 0}, //ョ + {IV('ッ'), 0xAF, 0}, //ッ + {IV('ー'), 0xB0, 0}, //ー + + //アイウエオカキクケコサシスセ + {IV('ア'), 0xB1, 0}, //ア + {IV('イ'), 0xB2, 0}, //イ + {IV('ウ'), 0xB3, 0}, //ウ + {IV('エ'), 0xB4, 0}, //エ + {IV('オ'), 0xB5, 0}, //オ + {IV('カ'), 0xB6, 0}, //カ + {IV('キ'), 0xB7, 0}, //キ + {IV('ク'), 0xB8, 0}, //ク + {IV('ケ'), 0xB9, 0}, //ケ + {IV('コ'), 0xBA, 0}, //コ + {IV('サ'), 0xBB, 0}, //サ + {IV('シ'), 0xBC, 0}, //シ + {IV('ス'), 0xBD, 0}, //ス + {IV('セ'), 0xBE, 0}, //セ + + //ソタチツテトナニヌネノハヒフ + {IV('ソ'), 0xBF, 0}, //ソ + {IV('タ'), 0xC0, 0}, //タ + {IV('チ'), 0xC1, 0}, //チ + {IV('ツ'), 0xC2, 0}, //ツ + {IV('テ'), 0xC3, 0}, //テ + {IV('ト'), 0xC4, 0}, //ト + {IV('ナ'), 0xC5, 0}, //ナ + {IV('ニ'), 0xC6, 0}, //ニ + {IV('ヌ'), 0xC7, 0}, //ヌ + {IV('ネ'), 0xC8, 0}, //ネ + {IV('ノ'), 0xC9, 0}, //ノ + {IV('ハ'), 0xCA, 0}, //ハ + {IV('ヒ'), 0xCB, 0}, //ヒ + {IV('フ'), 0xCC, 0}, //フ + + //ヘホマミムメモヤユヨラリルレロワン゙゚ + {IV('ヘ'), 0xCD, 0}, //ヘ + {IV('ホ'), 0xCE, 0}, //ホ + {IV('マ'), 0xCF, 0}, //マ + {IV('ミ'), 0xD0, 0}, //ミ + {IV('ム'), 0xD1, 0}, //ム + {IV('メ'), 0xD2, 0}, //メ + {IV('モ'), 0xD3, 0}, //モ + {IV('ヤ'), 0xD4, 0}, //ヤ + {IV('ユ'), 0xD5, 0}, //ユ + {IV('ヨ'), 0xD6, 0}, //ヨ + {IV('ラ'), 0xD7, 0}, //ラ + {IV('リ'), 0xD8, 0}, //リ + {IV('ル'), 0xD9, 0}, //ル + {IV('レ'), 0xDA, 0}, //レ + {IV('ロ'), 0xDB, 0}, //ロ + {IV('ワ'), 0xDC, 0}, //ワ + {IV('ン'), 0xDD, 0}, //ン + {IV('゙'), 0xDE, 0}, // ゛ + {IV('゚'), 0xDF, 0}, // ゜ + + {IV('¥'), 0x5C, 0}, + + #elif DISPLAY_CHARSET_HD44780 == WESTERN + // 0x10 -- 0x1F (except 0x1C) + // 0x80 -- 0xFF (except 0xA7,0xB0,0xB1,0xB3,0xB4,0xBF,0xD1,0xF8,0xFA,0xFC-0xFF) + + {IV('¡'), 0xA9, 0}, + {IV('¢'), 0xA4, 0}, + {IV('£'), 0xA5, 0}, + {IV('¥'), 0xA6, 0}, + {IV('§'), 0xD2, 0}, // section sign + {IV('©'), 0xCF, 0}, + + {IV('ª'), 0x9D, 0}, + {IV('«'), 0xBB, 0}, + {IV('®'), 0xCE, 0}, + + {IV('°'), 0xB2, 0}, // Marlin special: '°' LCD_STR_DEGREE (0x09) + //{IV(''), 0xD1, 0}, + {IV('±'), 0x10, 0}, //∓± + //{'='), 0x1C, 0}, // error + {IV('²'), 0x1E, 0}, + {IV('³'), 0x1F, 0}, + {IV('¶'), 0xD3, 0}, // pilcrow sign + {IV('º'), 0x9E, 0}, + {IV('»'), 0xBC, 0}, // 00BB + //{IV(''), 0xB3, 0}, // error + //{IV(''), 0xB4, 0}, // error + {IV('¼'), 0xB6, 0}, // 00BC + {IV('½'), 0xB5, 0}, // 00BD + //{IV('¾'), '3', 0}, // 00BE + {IV('¿'), 0x9F, 0}, // 00BF + + {IV('Â'), 0x8F, 0}, + {IV('Ã'), 0xAA, 0}, + {IV('Ä'), 0x8E, 0}, + {IV('Æ'), 0x92, 0}, + {IV('Ç'), 0x80, 0}, + {IV('É'), 0x90, 0}, + {IV('Ñ'), 0x9C, 0}, + {IV('Õ'), 0xAC, 0}, + {IV('Ö'), 0x99, 0}, + {IV('×'), 0xB7, 0}, + {IV('Ø'), 0xAE, 0}, + {IV('Ü'), 0x9A, 0}, + {IV('à'), 0x85, 0}, + {IV('á'), 0xA0, 0}, + {IV('â'), 0x83, 0}, + {IV('ã'), 0xAB, 0}, + {IV('ä'), 0x84, 0}, + {IV('å'), 0x86, 0}, + {IV('æ'), 0x91, 0}, + {IV('ç'), 0x87, 0}, + {IV('è'), 0x8A, 0}, + {IV('é'), 0x82, 0}, + {IV('ê'), 0x88, 0}, + {IV('ë'), 0x89, 0}, + {IV('ì'), 0x8D, 0}, + {IV('í'), 0xA1, 0}, + {IV('î'), 0x8C, 0}, + {IV('ï'), 0x8B, 0}, + + {IV('ñ'), 0x9B, 0}, + {IV('ò'), 0x95, 0}, + {IV('ó'), 0xA2, 0}, + {IV('ô'), 0x93, 0}, + {IV('õ'), 0xAD, 0}, + {IV('ö'), 0x94, 0}, + {IV('÷'), 0xB8, 0}, + {IV('ø'), 0xAF, 0}, + {IV('ù'), 0x97, 0}, + {IV('ú'), 0xA3, 0}, + {IV('û'), 0x96, 0}, + {IV('ü'), 0x81, 0}, + {IV('ÿ'), 0x98, 0}, + + //{IV(''), 0xB0, 0}, // error + //{IV(''), 0xB1, 0}, // error + {IV('ƒ'), 0xA8, 0}, // 0192 + + {IV('Ύ'), 0xDB, 0}, // 038E + {IV('Ώ'), 0xDE, 0}, // 038F + {IV('ΐ'), 0xE7, 0}, // 0390 + + {IV('Γ'), 0xD4, 0}, // 0393, Gamma + {IV('Δ'), 0xD5, 0}, // 0394, Delta, ◿ + {IV('Θ'), 0xD6, 0}, // 0398, Theta + {IV('Λ'), 0xD7, 0}, // 039B, Lambda + {IV('Ξ'), 0xD8, 0}, // 039E, Xi + {IV('Π'), 0xD9, 0}, // Pi + {IV('Σ'), 0xDA, 0}, // Sigma + {IV('Υ'), 0xDB, 0}, // Upsilon + {IV('Φ'), 0xDC, 0}, // Phi + {IV('Ψ'), 0xDD, 0}, // Psi + {IV('Ω'), 0xDE, 0}, // Omega + + {IV('ά'), 0xDF, 0}, // 03AC + {IV('έ'), 0xE3, 0}, // 03AD + {IV('ή'), 0xE5, 0}, // 03AE + {IV('ί'), 0xE7, 0}, // 03AF + {IV('ΰ'), 0xF1, 0}, // 03B0 + + {IV('α'), 0xDF, 0}, // alpha + {IV('β'), 0xE0, 0}, // beta + {IV('γ'), 0xE1, 0}, // gamma + {IV('δ'), 0xE2, 0}, // delta + {IV('ε'), 0xE3, 0}, // epsilon + {IV('ζ'), 0xE4, 0}, // zeta + {IV('η'), 0xE5, 0}, // eta + {IV('θ'), 0xE6, 0}, // theta + {IV('ι'), 0xE7, 0}, // lota + {IV('κ'), 0xE8, 0}, // kappa + {IV('λ'), 0xE9, 0}, // lambda + {IV('μ'), 0xEA, 0}, // mu + {IV('ν'), 0xEB, 0}, // nu + {IV('ξ'), 0xEC, 0}, // xi + {IV('π'), 0xED, 0}, // pi + {IV('ρ'), 0xEE, 0}, // rho + {IV('σ'), 0xEF, 0}, // sigma + + {IV('τ'), 0xF0, 0}, // tau + {IV('υ'), 0xF1, 0}, // upsilon + {IV('χ'), 0xF2, 0}, // chi + {IV('ψ'), 0xF3, 0}, // psi + {IV('ω'), 0xF4, 0}, // 03C9, omega + {IV('ϊ'), 0xE7, 0}, // 03CA + {IV('ϋ'), 0xF1, 0}, // 03CB + {IV('ύ'), 0xF1, 0}, // 03CD + {IV('ώ'), 0xF4, 0}, // 03CE + + {IV('•'), 0xCD, 0}, // · + {IV('℞'), 0xA7, 0}, // ℞ Pt ASCII 158 + {IV('™'), 0xD0, 0}, + {IV('↤'), 0xF9, 0}, // ⟻ + {IV('↵'), 0xC4, 0}, + {IV('↻'), 0x04, 0}, // Marlin special: '↻↺⟳⟲' LCD_STR_REFRESH (0x01) + {IV('⇥'), 0xFB, 0}, + {IV('√'), 0xBE, 0}, // √ + {IV('∞'), 0xC2, 0}, // infinity + {IV('∫'), 0x1B, 0}, + {IV('∼'), 0x1D, 0}, + {IV('≈'), 0x1A, 0}, + {IV('≠'), 0xBD, 0}, + {IV('≡'), 0x11, 0}, + {IV('≤'), 0xB9, 0},// ≤≥ ⩽⩾ + {IV('≥'), 0xBA, 0}, + //{IV(''), 0xBF, 0}, // error + + {IV('⌠'), 0xC0, 0}, + {IV('⌡'), 0xC1, 0}, + + {IV('⎧'), 0x14, 0}, + {IV('⎩'), 0x15, 0}, + {IV('⎫'), 0x16, 0}, + {IV('⎭'), 0x17, 0}, + {IV('⎰'), 0x18, 0}, + {IV('⎱'), 0x19, 0}, + + {IV('⎲'), 0x12, 0}, + {IV('⎳'), 0x13, 0}, + + {IV('⏱'), 0x07, 0}, // Marlin special: '🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛🕜🕝🕞🕟🕠🕡🕢🕣🕤🕥🕦🕧 ⌚⌛⏰⏱⏳⧖⧗' LCD_STR_CLOCK (0x05) + {IV('┌'), 0xC9, 0}, + {IV('┐'), 0xCA, 0}, + {IV('└'), 0xCB, 0}, + {IV('┘'), 0xCC, 0}, + {IV('◸'), 0xC3, 0}, // ◿ + {IV('⭠'), 0xC8, 0}, + {IV('⭡'), 0xC5, 0}, + {IV('⭢'), 0xC7, 0}, + {IV('⭣'), 0xC6, 0}, + + + {IV('⯆'), 0xF5, 0}, + {IV('⯇'), 0xF7, 0}, // ⯅ + {IV('⯈'), 0xF6, 0}, + //{IV(''), 0xF8, 0}, // error + //{IV(''), 0xFA, 0}, // error + //{IV(''), 0xFC, 0}, // error + //{IV(''), 0xFD, 0}, // error + //{IV(''), 0xFE, 0}, // error + //{IV(''), 0xFF, 0}, // error + + #elif DISPLAY_CHARSET_HD44780 == CYRILLIC + + {IV('¢'), 0x5C, 0}, // 00A2 + {IV('£'), 0xCF, 0}, // 00A3 + {IV('°'), 0x01, 0}, // 00B0, Marlin special: '°' LCD_STR_DEGREE (0x09) + + //{IV(''), 0x80, 0}, + //{IV(''), 0x81, 0}, + //{IV(''), 0x82, 0}, + //{IV(''), 0x83, 0}, + //{IV(''), 0x84, 0}, + //{IV(''), 0x85, 0}, + //{IV(''), 0x86, 0}, + //{IV(''), 0x87, 0}, + //{IV(''), 0x88, 0}, + //{IV(''), 0x89, 0}, + //{IV(''), 0x8A, 0}, + //{IV(''), 0x8B, 0}, + //{IV(''), 0x8C, 0}, + //{IV(''), 0x8D, 0}, + //{IV(''), 0x8E, 0}, + //{IV(''), 0x8F, 0}, + + //{IV(''), 0x90, 0}, + //{IV(''), 0x91, 0}, + //{IV(''), 0x92, 0}, + //{IV(''), 0x93, 0}, + //{IV(''), 0x94, 0}, + //{IV(''), 0x95, 0}, + //{IV(''), 0x96, 0}, + //{IV(''), 0x97, 0}, + //{IV(''), 0x98, 0}, + //{IV(''), 0x99, 0}, + //{IV(''), 0x9A, 0}, + //{IV(''), 0x9B, 0}, + //{IV(''), 0x9C, 0}, + //{IV(''), 0x9D, 0}, + //{IV(''), 0x9E, 0}, + //{IV(''), 0x9F, 0}, + + + {IV('¼'), 0xF0, 0}, // 00BC + {IV('⅓'), 0xF1, 0}, + {IV('½'), 0xF2, 0}, // 00BD + {IV('¾'), 0xF3, 0}, // 00BE + {IV('¿'), 0xCD, 0}, // 00BF + + #if ENABLED(DISPLAY_CHARSET_ISO10646_5) + + // Map Cyrillic to HD44780 extended CYRILLIC where possible + {IV('Ё'), 0xA2, 0}, // 0401 + {IV('А'), 'A', 0}, // 0410 + {IV('Б'), 0xA0, 0}, + {IV('В'), 'B', 0}, + {IV('Г'), 0xA1, 0}, + {IV('Д'), 0xE0, 0}, + {IV('Е'), 'E', 0}, + {IV('Ж'), 0xA3, 0}, + {IV('З'), 0xA4, 0}, + {IV('И'), 0xA5, 0}, + {IV('Й'), 0xA6, 0}, + {IV('К'), 'K', 0}, + {IV('Л'), 0xA7, 0}, + {IV('М'), 'M', 0}, + {IV('Н'), 'H', 0}, + {IV('О'), 'O', 0}, + {IV('П'), 0xA8, 0}, + {IV('Р'), 'P', 0}, + {IV('С'), 'C', 0}, + {IV('Т'), 'T', 0}, + {IV('У'), 0xA9, 0}, + {IV('Ф'), 0xAA, 0}, + {IV('Х'), 'X', 0}, + {IV('Ц'), 0xE1, 0}, + {IV('Ч'), 0xAB, 0}, + {IV('Ш'), 0xAC, 0}, + {IV('Щ'), 0xE2, 0}, + {IV('Ъ'), 0xAD, 0}, + {IV('Ы'), 0xAE, 0}, + {IV('Ь'), 'b', 0}, + {IV('Э'), 0xAF, 0}, + {IV('Ю'), 0xB0, 0}, + {IV('Я'), 0xB1, 0}, + {IV('а'), 'a', 0}, + + {IV('б'), 0xB2, 0}, + {IV('в'), 0xB3, 0}, + {IV('г'), 0xB4, 0}, + {IV('д'), 0xE3, 0}, + {IV('е'), 'e', 0}, + {IV('ж'), 0xB6, 0}, + {IV('з'), 0xB7, 0}, + {IV('и'), 0xB8, 0}, + {IV('й'), 0xB9, 0}, + {IV('к'), 0xBA, 0}, //клмноп + {IV('л'), 0xBB, 0}, + {IV('м'), 0xBC, 0}, + {IV('н'), 0xBD, 0}, + {IV('о'), 'o', 0}, + {IV('п'), 0xBE, 0}, + {IV('р'), 'p', 0}, + {IV('с'), 'c', 0}, + {IV('т'), 0xBF, 0}, + + {IV('у'), 'y', 0}, + {IV('ф'), 0xE4, 0}, + {IV('х'), 'x', 0}, + {IV('ц'), 0xE5, 0}, + {IV('ч'), 0xC0, 0}, + {IV('ш'), 0xC1, 0}, + {IV('щ'), 0xE6, 0}, + {IV('ъ'), 0xC2, 0}, + {IV('ы'), 0xC3, 0}, + {IV('ь'), 0xC4, 0}, + {IV('э'), 0xC5, 0}, + {IV('ю'), 0xC6, 0}, + {IV('я'), 0xC7, 0}, // 044F + {IV('ё'), 0xB5, 0}, // 0451 + //{IV(''), 0xC8, 0}, + //{IV(''), 0xC9, 0}, + //{IV(''), 0xCA, 0}, + //{IV(''), 0xCB, 0}, + //{IV(''), 0xCC, 0}, + //{IV(''), 0xCD, 0}, + //{IV(''), 0xCE, 0}, + + //{IV(''), 0xD0, 0}, + //{IV(''), 0xD1, 0}, + //{IV(''), 0xD2, 0}, + //{IV(''), 0xD3, 0}, + //{IV(''), 0xD4, 0}, + //{IV(''), 0xD5, 0}, + //{IV(''), 0xD6, 0}, + //{IV(''), 0xD7, 0}, + //{IV(''), 0xD8, 0}, + //{IV(''), 0xDB, 0}, + //{IV(''), 0xDC, 0}, + //{IV(''), 0xDD, 0}, + //{IV(''), 0xDE, 0}, + //{IV(''), 0xDF, 0}, + + //{IV(''), 0xE7, 0}, + //{IV(''), 0xE8, 0}, + //{IV(''), 0xE9, 0}, + //{IV(''), 0xEA, 0}, + //{IV(''), 0xEB, 0}, + //{IV(''), 0xEC, 0}, + //{IV(''), 0xED, 0}, + //{IV(''), 0xEE, 0}, + //{IV(''), 0xEF, 0}, + + //{IV(''), 0xF4, 0}, + //{IV(''), 0xF5, 0}, + //{IV(''), 0xF6, 0}, + //{IV(''), 0xF7, 0}, + //{IV(''), 0xF8, 0}, + //{IV(''), 0xF9, 0}, + //{IV(''), 0xFA, 0}, + //{IV(''), 0xFB, 0}, + //{IV(''), 0xFC, 0}, + //{IV(''), 0xFD, 0}, + //{IV(''), 0xFE, 0}, + //{IV(''), 0xFF, 0}, + + #endif + + {IV('↑'), 0xD9, 0}, // 2191 ←↑→↓ + {IV('↓'), 0xDA, 0}, // 2193 + #endif +}; + +// ASCII replacement for various characters +const dwin_charmap_t g_dwin_charmap_common[] PROGMEM = { + {IV('¡'), 'i', 0}, // A1 + {IV('¢'), 'c', 0}, // A2 + {IV('°'), 0x09, 0}, // B0 Marlin special: '°' LCD_STR_DEGREE (0x09) + + // Map WESTERN code to plain ASCII + {IV('Á'), 'A', 0}, // C1 + {IV('Â'), 'A', 0}, // C2 + {IV('Ã'), 'A', 0}, // C3 + {IV('Ä'), 'A', 0}, // C4 + {IV('Å'), 'A', 0}, // C5 + {IV('Æ'), 'A', 'E'}, // C6 + {IV('Ç'), 'C', 0}, // C7 + {IV('È'), 'E', 0}, // C8 + {IV('É'), 'E', 0}, // C9 + {IV('Í'), 'I', 0}, // CD + {IV('Ñ'), 'N', 0}, // D1 + {IV('Õ'), 'O', 0}, // D5 + {IV('Ö'), 'O', 0}, // D6 + {IV('×'), 'x', 0}, // D7 + {IV('Ü'), 'U', 0}, // DC + {IV('Ý'), 'Y', 0}, // DD + {IV('à'), 'a', 0}, // E0 + {IV('á'), 'a', 0}, + {IV('â'), 'a', 0}, + {IV('ã'), 'a', 0}, + {IV('ä'), 'a', 0}, + {IV('å'), 'a', 0}, + {IV('æ'), 'a', 'e'}, + {IV('ç'), 'c', 0}, + {IV('è'), 'e', 0}, // 00E8 + {IV('é'), 'e', 0}, + {IV('ê'), 'e', 0}, + {IV('ë'), 'e', 0}, + {IV('ì'), 'i', 0}, // 00EC + {IV('í'), 'i', 0}, + {IV('î'), 'i', 0}, + {IV('ï'), 'i', 0}, // 00EF + + {IV('ñ'), 'n', 0}, // 00F1 + {IV('ò'), 'o', 0}, + {IV('ó'), 'o', 0}, + {IV('ô'), 'o', 0}, + {IV('õ'), 'o', 0}, + {IV('ö'), 'o', 0}, + //{IV('÷'), 0xB8, 0}, + {IV('ø'), 'o', 0}, + {IV('ù'), 'u', 0}, + {IV('ú'), 'u', 0}, + {IV('û'), 'u', 0}, + {IV('ü'), 'u', 0}, // FC + {IV('ý'), 'y', 0}, // FD + {IV('ÿ'), 'y', 0}, // FF + + {IV('Ą'), 'A', 0}, // 0104 + {IV('ą'), 'a', 0}, // 0105 + {IV('Ć'), 'C', 0}, // 0106 + {IV('ć'), 'c', 0}, // 0107 + {IV('Č'), 'C', 0}, // 010C + {IV('č'), 'c', 0}, // 010D + {IV('Ď'), 'D', 0}, // 010E + {IV('ď'), 'd', 0}, // 010F + {IV('đ'), 'd', 0}, // 0111 + {IV('ę'), 'e', 0}, // 0119 + {IV('Ě'), 'E', 0}, // 011A + {IV('ě'), 'e', 0}, // 011B + {IV('ğ'), 'g', 0}, // 011F + {IV('İ'), 'I', 0}, // 0130 + {IV('ı'), 'i', 0}, // 0131 + + {IV('Ł'), 'L', 0}, // 0141 + {IV('ł'), 'l', 0}, // 0142 + {IV('Ń'), 'N', 0}, // 0143 + {IV('ń'), 'n', 0}, // 0144 + {IV('ň'), 'n', 0}, // 0148 + + {IV('Ř'), 'R', 0}, // 0158 + {IV('ř'), 'r', 0}, // 0159 + {IV('Ś'), 'S', 0}, // 015A + {IV('ś'), 's', 0}, // 015B + {IV('ş'), 's', 0}, // 015F + {IV('Š'), 'S', 0}, // 0160 + {IV('š'), 's', 0}, // 0161 + {IV('ť'), 't', 0}, // 0165 + {IV('ů'), 'u', 0}, // 016F + {IV('ż'), 'z', 0}, // 017C + {IV('Ž'), 'Z', 0}, // 017D + {IV('ž'), 'z', 0}, // 017E + {IV('ƒ'), 'f', 0}, // 0192 + + {IV('ˣ'), 'x', 0}, // 02E3 + + #if ENABLED(DISPLAY_CHARSET_ISO10646_VI) + + // Map Vietnamese phonetics + + //{IV('à'), 'a', 0}, {IV('À'), 'A', 0}, + {IV('ạ'), 'a', 0}, {IV('Ạ'), 'A', 0}, + {IV('ả'), 'a', 0}, {IV('Ả'), 'A', 0}, + //{IV('ã'), 'a', 0}, {IV('Ã'), 'A', 0}, + //{IV('á'), 'á', 0}, {IV('Á'), 'A', 0}, + {IV('Ạ'), 'A', 0}, + {IV('ă'), 'a', 0}, {IV('Ă'), 'A', 0}, + {IV('ằ'), 'a', 0}, {IV('Ằ'), 'A', 0}, + {IV('ẳ'), 'a', 0}, {IV('Ẳ'), 'A', 0}, + {IV('ẵ'), 'a', 0}, {IV('Ẵ'), 'A', 0}, + {IV('ắ'), 'a', 0}, {IV('Ắ'), 'A', 0}, + {IV('ặ'), 'a', 0}, {IV('Ặ'), 'A', 0}, + {IV('â'), 'a', 0}, {IV('Â'), 'A', 0}, + {IV('ầ'), 'a', 0}, {IV('Ầ'), 'A', 0}, + {IV('ẩ'), 'a', 0}, {IV('Ẩ'), 'A', 0}, + {IV('ẫ'), 'a', 0}, {IV('Ẫ'), 'A', 0}, + {IV('ấ'), 'a', 0}, {IV('Ấ'), 'A', 0}, + {IV('ậ'), 'a', 0}, {IV('Ậ'), 'A', 0}, + //{IV('đ'), 'd', 0}, + {IV('Đ'), 'D', 0}, + {IV('e'), 'e', 0}, {IV('E'), 'E', 0}, + {IV('è'), 'e', 0}, {IV('È'), 'E', 0}, + {IV('ẻ'), 'e', 0}, {IV('Ẻ'), 'E', 0}, + {IV('ẽ'), 'e', 0}, {IV('Ẽ'), 'E', 0}, + {IV('é'), 'e', 0}, {IV('É'), 'E', 0}, + {IV('ẹ'), 'e', 0}, {IV('Ẹ'), 'E', 0}, + {IV('ê'), 'e', 0}, {IV('Ê'), 'E', 0}, + {IV('ề'), 'e', 0}, {IV('Ề'), 'E', 0}, + {IV('ể'), 'e', 0}, {IV('Ể'), 'E', 0}, + {IV('ễ'), 'e', 0}, {IV('Ễ'), 'E', 0}, + {IV('ế'), 'e', 0}, {IV('Ế'), 'E', 0}, + {IV('ệ'), 'e', 0}, {IV('Ệ'), 'E', 0}, + {IV('i'), 'i', 0}, {IV('I'), 'I', 0}, + //{IV('ì'), 'ì', 0}, {IV('Ì'), 'Ì', 0}, + {IV('ỉ'), 'ỉ', 0}, {IV('Ỉ'), 'Ỉ', 0}, + {IV('ĩ'), 'ĩ', 0}, {IV('Ĩ'), 'Ĩ', 0}, + {IV('í'), 'í', 0}, {IV('Í'), 'Í', 0}, + {IV('ị'), 'ị', 0}, {IV('Ị'), 'Ị', 0}, + {IV('o'), 'o', 0}, {IV('O'), 'O', 0}, + {IV('ò'), 'o', 0}, {IV('Ò'), 'O', 0}, + {IV('ỏ'), 'o', 0}, {IV('Ỏ'), 'O', 0}, + {IV('õ'), 'o', 0}, {IV('Õ'), 'O', 0}, + {IV('ó'), 'o', 0}, {IV('Ó'), 'O', 0}, + {IV('ọ'), 'o', 0}, {IV('Ọ'), 'O', 0}, + {IV('ô'), 'o', 0}, {IV('Ô'), 'O', 0}, + {IV('ồ'), 'o', 0}, {IV('Ồ'), 'O', 0}, + {IV('ổ'), 'o', 0}, {IV('Ổ'), 'O', 0}, + {IV('ỗ'), 'o', 0}, {IV('Ỗ'), 'O', 0}, + {IV('ố'), 'o', 0}, {IV('Ố'), 'O', 0}, + {IV('ộ'), 'o', 0}, {IV('Ộ'), 'O', 0}, + {IV('ơ'), 'o', 0}, {IV('Ơ'), 'O', 0}, + {IV('ờ'), 'o', 0}, {IV('Ờ'), 'O', 0}, + {IV('ở'), 'o', 0}, {IV('Ở'), 'O', 0}, + {IV('ỡ'), 'o', 0}, {IV('Ỡ'), 'O', 0}, + {IV('ớ'), 'o', 0}, {IV('Ớ'), 'O', 0}, + {IV('ợ'), 'o', 0}, {IV('Ợ'), 'O', 0}, + {IV('ù'), 'u', 0}, {IV('Ù'), 'U', 0}, + {IV('ủ'), 'u', 0}, {IV('Ủ'), 'U', 0}, + {IV('ũ'), 'u', 0}, {IV('Ũ'), 'U', 0}, + //{IV('ú'), 'u', 0}, {IV('Ú'), 'U', 0}, + {IV('ụ'), 'u', 0}, {IV('Ụ'), 'U', 0}, + {IV('ư'), 'u', 0}, {IV('Ư'), 'U', 0}, + {IV('ừ'), 'u', 0}, {IV('Ừ'), 'U', 0}, + {IV('ử'), 'u', 0}, {IV('Ử'), 'U', 0}, + {IV('ữ'), 'u', 0}, {IV('Ữ'), 'U', 0}, + {IV('ứ'), 'u', 0}, {IV('Ứ'), 'U', 0}, + {IV('ự'), 'u', 0}, {IV('Ự'), 'U', 0}, + {IV('y'), 'y', 0}, {IV('Y'), 'Y', 0}, + + #endif + + #if ENABLED(DISPLAY_CHARSET_ISO10646_GREEK) + + {IV('΄'), '\'', 0}, // 0384 + {IV('΅'), '\'', 0}, // 0385 + {IV('Ά'), 'A', 0}, // 0386 + {IV('·'), '.', 0}, // 0387 + {IV('Έ'), 'E', 0}, // 0388 + {IV('Ή'), 'H', 0}, // 0389 + {IV('Ί'), 'I', 0}, // 038A + {IV('Ό'), 'O', 0}, // 038C + {IV('Ύ'), 'Y', 0}, // 038E + {IV('Ώ'), 'O', 0}, // 038F + {IV('ΐ'), 'i', 0}, // 0390 + {IV('Α'), 'A', 0}, // 0391 + {IV('Β'), 'B', 0}, // 0392 + {IV('Γ'), 'T', 0}, // 0393, Gamma + {IV('Δ'), '4', 0}, // 0394, Delta, ◿ + {IV('Ε'), 'E', 0}, // 0395 + {IV('Ζ'), 'Z', 0}, // 0396 + {IV('Η'), 'H', 0}, // 0397 + {IV('Θ'), '0', 0}, // 0398, Theta + {IV('Ι'), 'I', 0}, // 0399 + {IV('Κ'), 'K', 0}, // 039A + {IV('Λ'), '^', 0}, // 039B, Lambda + {IV('Μ'), 'M', 0}, // 039C + {IV('Ν'), 'N', 0}, // 039D + {IV('Ξ'), '3', 0}, // 039E, Xi + {IV('Ο'), 'O', 0}, // 039F + {IV('Π'), 'n', 0}, // 03A0, Pi + {IV('Ρ'), 'P', 0}, // 03A1 + {IV('Σ'), 'E', 0}, // 03A3, Sigma + {IV('Τ'), 'T', 0}, // 03A4 + {IV('Υ'), 'Y', 0}, // 03A5, Upsilon + {IV('Φ'), 'p', 0}, // 03A6, Phi + {IV('Χ'), 'X', 0}, // 03A7 + {IV('Ψ'), 'P', 0}, // 03A8, Psi + {IV('Ω'), 'O', 0}, // 03A9, Omega + {IV('Ϊ'), 'I', 0}, // 03AA + {IV('Ϋ'), 'Y', 0}, // 03AB + {IV('ά'), 'a', 0}, // 03AC + {IV('έ'), 'e', 0}, // 03AD + {IV('ή'), 'n', 0}, // 03AE + {IV('ί'), 'i', 0}, // 03AF + {IV('ΰ'), 'v', 0}, // 03B0 + {IV('α'), 'a', 0}, // 03B1, alpha + {IV('β'), 'B', 0}, // 03B2, beta + {IV('γ'), 'v', 0}, // 03B3, gamma + {IV('δ'), 'd', 0}, // 03B4, delta + {IV('ε'), 'e', 0}, // 03B5, epsilon + {IV('ζ'), 'Z', 0}, // 03B6, zeta + {IV('η'), 'n', 0}, // 03B7, eta + {IV('θ'), '0', 0}, // 03B8, theta + {IV('ι'), 'i', 0}, // 03B9, lota + {IV('κ'), 'k', 0}, // 03BA, kappa + {IV('λ'), 'L', 0}, // 03BB, lambda + {IV('μ'), 'u', 0}, // 03BC, mu + {IV('ν'), 'v', 0}, // 03BD, nu + {IV('ξ'), 'e', 0}, // 03BE, xi + {IV('ο'), 'o', 0}, // 03BF + {IV('π'), 'n', 0}, // 03C0, pi + {IV('ρ'), 'p', 0}, // 03C1, rho + {IV('ς'), 'c', 0}, // 03C2 + {IV('σ'), 'o', 0}, // 03C3, sigma + {IV('τ'), 't', 0}, // 03C4, tau + {IV('υ'), 'v', 0}, // 03C5, upsilon + {IV('φ'), 'p', 0}, // 03C6 + {IV('χ'), 'X', 0}, // 03C7, chi + {IV('ψ'), 'W', 0}, // 03C8, psi + {IV('ω'), 'w', 0}, // 03C9, omega + {IV('ϊ'), 'i', 0}, // 03CA + {IV('ϋ'), 'v', 0}, // 03CB + {IV('ό'), 'o', 0}, // 03CC + {IV('ύ'), 'v', 0}, // 03CD + {IV('ώ'), 'w', 0}, // 03CE + + #endif + + #if ENABLED(DISPLAY_CHARSET_ISO10646_5) + // Map CYRILLIC code to plain ASCII + {IV('Ё'), 'E', 0}, // 0401 + {IV('А'), 'A', 0}, // 0410 + {IV('Б'), 'b', 0}, // 0411 + {IV('В'), 'B', 0}, // 0412 + {IV('Г'), 'T', 0}, // 0413 + {IV('Д'), 'Q', 0}, // 0414 + {IV('Е'), 'E', 0}, // 0415 + {IV('Ж'), '*', 0}, // 0416 + {IV('З'), 'E', 0}, // 0417 + {IV('И'), 'N', 0}, // 0418 + {IV('Й'), 'N', 0}, // 0419 + {IV('К'), 'K', 0}, // 041A + {IV('Л'), 'T', 0}, // 041B + {IV('М'), 'M', 0}, // 041C + {IV('Н'), 'H', 0}, // 041D + {IV('О'), 'O', 0}, // 041E + {IV('П'), 'n', 0}, // 041F + {IV('Р'), 'P', 0}, // 0420 + {IV('С'), 'C', 0}, // 0421 + {IV('Т'), 'T', 0}, // 0422 + {IV('У'), 'Y', 0}, + {IV('Ф'), 'o', 0}, + {IV('Х'), 'X', 0}, + {IV('Ц'), 'U', 0}, + {IV('Ч'), 'y', 0}, + {IV('Ш'), 'W', 0}, + {IV('Щ'), 'W', 0}, + {IV('Ъ'), 'b', 0}, + {IV('Ы'), 'b', '|'}, + {IV('Ь'), 'b'}, + {IV('Э'), 'e'}, + {IV('Ю'), '|', 'O'}, + {IV('Я'), '9', '|'}, // 042F + + {IV('а'), 'a', 0}, // 0430 + {IV('б'), '6', 0}, // 0431 + {IV('в'), 'B', 0}, // 0432, + {IV('г'), 'r', 0}, // 0433 + {IV('д'), 'a', 0}, // 0434, + {IV('е'), 'e', 0}, // 0435 + {IV('ж'), '*', 0}, // 0436 + {IV('з'), 'e', 0}, // 0437, + {IV('и'), 'u', 0}, // 0438 + {IV('й'), 'u', 0}, // 0439, + {IV('к'), 'k', 0}, // 043A + {IV('л'), 'n', 0}, + {IV('м'), 'm', 0}, + {IV('н'), 'H', 0}, + {IV('о'), 'o', 0}, + {IV('п'), 'n', 0}, + {IV('р'), 'p', 0}, + {IV('с'), 'c', 0}, + {IV('т'), 't', 0}, + {IV('у'), 'y', 0}, + {IV('ф'), 'q', 'p'}, + {IV('х'), 'x', 0}, + {IV('ц'), 'u', 0}, + {IV('ч'), 'y', 0}, + {IV('ш'), 'w', 0}, + {IV('щ'), 'w', 0}, + {IV('ъ'), 'b', 0}, + {IV('ы'), 'b', '|'}, + {IV('ь'), 'b', 0}, + {IV('э'), 'e', 0}, + {IV('ю'), '|', 'o'}, + {IV('я'), 'g', 0}, // 044F + {IV('ё'), 'e', 0}, // 0451 + #endif + + {IV('•'), '.', 0}, // 2022 · + {IV('℞'), 'P', 'x'}, // 211E ℞ Pt ASCII 158 + {IV('™'), 'T', 'M'}, // 2122 + {IV('←'), '<', '-'}, // 2190 + {IV('→'), '-', '>'}, // 2192, Marlin special: '⮈⮉⮊⮋➤→⏵➟➠➡' LCD_STR_ARROW_RIGHT (0x03) + //{IV('↰'), '<', 0}, // 21B0, Marlin special: '⮥⮭⮉⇧↑↰⤴' LCD_STR_UPLEVEL (0x04) + {IV('↰'), 0x03, 0}, // 21B0, Marlin special: '⮥⮭⮉⇧↑↰⤴' LCD_STR_UPLEVEL (0x04) + {IV('↻'), 0x04, 0}, // 21BB Marlin special: '↻↺⟳⟲' LCD_STR_REFRESH (0x01) + {IV('∼'), '~', 0}, // 223C + {IV('≈'), '~', '='}, // 2248 + {IV('≠'), '!', '='}, // 2260 + {IV('≡'), '=', 0}, // 2261 + {IV('≤'), '<', '='},// 2264, ≤≥ ⩽⩾ + {IV('≥'), '>', '='}, // 2265 + {IV('⏱'), 0x07, 0}, // 23F1, Marlin special: '🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛🕜🕝🕞🕟🕠🕡🕢🕣🕤🕥🕦🕧 ⌚⌛⏰⏱⏳⧖⧗' LCD_STR_CLOCK (0x05) + + {IV('゠'), '=', 0}, // 30A0 + + // ⏰⏱⏲⏳◴◵◶◷ + // ⏻⏼♁♂ + //{IV(''), 0x00, 0}, // Marlin special: '' LCD_STR_BEDTEMP (0x07) + {IV('🌡'), 0x02, 0}, // D83CDF21 Marlin special: '🌡' LCD_STR_THERMOMETER (0x08) + {IV('📂'), 0x05, 0}, // D83DDCC2 Marlin special: '📁📂' LCD_STR_FOLDER (0x02) + //{IV(''), 0x06, 0}, // Marlin special: '' LCD_STR_FEEDRATE (0x06) +}; diff --git a/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp b/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp new file mode 100644 index 0000000..e603882 --- /dev/null +++ b/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp @@ -0,0 +1,190 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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/e3v2/marlinui/lcdprint_dwin.cpp + * + * Due to DWIN hardware limitations simplified characters are used + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if IS_DWIN_MARLINUI + +#include "lcdprint_dwin.h" +#include "dwin_lcd.h" +#include "dwin_string.h" + +#include "../../marlinui.h" +#include "../../../MarlinCore.h" + +#include + +cursor_t cursor; + +extern dwin_font_t dwin_font; + +void lcd_moveto_xy(const lcd_uint_t x, const lcd_uint_t y) { cursor.x = x; cursor.y = y; } + +void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { + lcd_moveto_xy(col * dwin_font.width, row * (dwin_font.height + EXTRA_ROW_HEIGHT) + EXTRA_ROW_HEIGHT / 2); +} + +inline void lcd_advance_cursor(const uint8_t len=1) { cursor.x += len * dwin_font.width; } + +void lcd_put_int(const int i) { + // TODO: Draw an int at the cursor position, advance the cursor +} + +int lcd_put_dwin_string() { + DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string()); + lcd_advance_cursor(dwin_string.length); + return dwin_string.length; +} + +// return < 0 on error +// return the advanced cols +int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) { + dwin_string.set(c); + dwin_string.truncate(max_length); + // Draw the char(s) at the cursor and advance the cursor + DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string()); + lcd_advance_cursor(dwin_string.length); + return dwin_string.length; +} + +/** + * @brief Draw a UTF-8 string + * + * @param utf8_str : the UTF-8 string + * @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM) + * @param max_length : the pixel length of the string allowed (or number of slots in HD44780) + * + * @return the number of pixels advanced + * + * Draw a UTF-8 string + */ +static int lcd_put_u8str_max_cb(const char * utf8_str, read_byte_cb_t cb_read_byte, const pixel_len_t max_length) { + const uint8_t *p = (uint8_t *)utf8_str; + dwin_string.set(); + while (dwin_string.length < max_length) { + lchar_t wc; + p = get_utf8_value_cb(p, cb_read_byte, wc); + if (!wc) break; + dwin_string.add(wc); + } + DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string()); + lcd_advance_cursor(dwin_string.length); + return dwin_string.length; +} + +int lcd_put_u8str_max(const char * utf8_str, const pixel_len_t max_length) { + return lcd_put_u8str_max_cb(utf8_str, read_byte_ram, max_length); +} + +int lcd_put_u8str_max_P(PGM_P utf8_pstr, const pixel_len_t max_length) { + return lcd_put_u8str_max_cb(utf8_pstr, read_byte_rom, max_length); +} + +lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char * const cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) { + dwin_string.set(ptpl, ind, cstr, fstr); + dwin_string.truncate(maxlen); + DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string()); + lcd_advance_cursor(dwin_string.length); + return dwin_string.length; +} + +#if ENABLED(DEBUG_LCDPRINT) + + int test_dwin_charmap(dwin_charmap_t *data, size_t size, char *name, char flg_show_contents) { + int ret; + size_t idx = 0; + dwin_charmap_t preval = { 0, 0, 0 }; + dwin_charmap_t pinval = { 0, 0, 0 }; + char flg_error = 0; + + int i; + + TRACE("Test %s\n", name); + + for (i = 0; i < size; i ++) { + memcpy_P(&pinval, &(data[i]), sizeof(pinval)); + + if (flg_show_contents) { + #if 1 + TRACE("[% 4d] % 6" PRIu32 "(0x%04" PRIX32 ") --> 0x%02X,0x%02X%s\n", i, pinval.uchar, pinval.uchar, (unsigned int)(pinval.idx), (unsigned int)(pinval.idx2), (preval.uchar < pinval.uchar?"":" <--- ERROR")); + #else + TRACE("[% 4d]", i); + TRACE("% 6" PRIu32 "(0x%04" PRIX32 "),", pinval.uchar, pinval.uchar); + TRACE("0x%02X,", (unsigned int)(pinval.idx)); + TRACE("0x%02X,", (unsigned int)(pinval.idx2)); + TRACE("%s", (preval.uchar < pinval.uchar?"":" <--- ERROR")); + #endif + } + if (preval.uchar >= pinval.uchar) { + flg_error = 1; + //TRACE("Error: out of order in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar); + //return -1; + } + memcpy(&preval, &pinval, sizeof(pinval)); + + ret = pf_bsearch_r((void *)data, size, pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx); + if (ret < 0) { + flg_error = 1; + TRACE("Error: not found item in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar); + //return -1; + } + if (idx != i) { + flg_error = 1; + TRACE("Error: wrong index found item in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar); + //return -1; + } + } + if (flg_error) { + TRACE("\nError: in array %s\n\n", name); + return -1; + } + TRACE("\nPASS array %s\n\n", name); + return 0; + } + + int test_dwin_charmap_all() { + int flg_error = 0; + if (test_dwin_charmap(g_dwin_charmap_device, COUNT(g_dwin_charmap_device), "g_dwin_charmap_device", 0) < 0) { + flg_error = 1; + test_dwin_charmap(g_dwin_charmap_device, COUNT(g_dwin_charmap_device), "g_dwin_charmap_device", 1); + } + if (test_dwin_charmap(g_dwin_charmap_common, COUNT(g_dwin_charmap_common), "g_dwin_charmap_common", 0) < 0) { + flg_error = 1; + test_dwin_charmap(g_dwin_charmap_common, COUNT(g_dwin_charmap_common), "g_dwin_charmap_common", 1); + } + if (flg_error) { + TRACE("\nFAILED in dwin tests!\n"); + return -1; + } + TRACE("\nPASS in dwin tests.\n"); + return 0; + } + +#endif // DEBUG_LCDPRINT + +#endif // IS_DWIN_MARLINUI diff --git a/src/lcd/e3v2/marlinui/lcdprint_dwin.h b/src/lcd/e3v2/marlinui/lcdprint_dwin.h new file mode 100644 index 0000000..692f448 --- /dev/null +++ b/src/lcd/e3v2/marlinui/lcdprint_dwin.h @@ -0,0 +1,30 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 "../../lcdprint.h" + +typedef struct { int16_t x, y; } cursor_t; +extern cursor_t cursor; + +int lcd_put_dwin_string(); +void lcd_moveto_xy(const lcd_uint_t, const lcd_uint_t); diff --git a/src/lcd/e3v2/marlinui/marlinui_dwin.h b/src/lcd/e3v2/marlinui/marlinui_dwin.h new file mode 100644 index 0000000..a91cd19 --- /dev/null +++ b/src/lcd/e3v2/marlinui/marlinui_dwin.h @@ -0,0 +1,146 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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/e3v2/marlinui/lcdprint_dwin.h + */ + +#include "../../../inc/MarlinConfigPre.h" +#include "dwin_lcd.h" + +typedef uint16_t dwin_coord_t; // Screen can be pretty big +typedef uint16_t lcd_uint_t; +typedef int16_t lcd_int_t; + +typedef struct { + uint8_t index, width, height; + uint16_t fg, bg; + bool solid; +} dwin_font_t; + +extern dwin_font_t dwin_font; + +// Only Western languages support big / small fonts +//#if DISABLED(DISPLAY_CHARSET_ISO10646_1) +// #undef USE_BIG_EDIT_FONT +// #undef USE_SMALL_INFOFONT +//#endif + +#if ENABLED(USE_BIG_EDIT_FONT) + #define DWIN_FONT_EDIT font10x20 +#else + #define DWIN_FONT_EDIT font8x16 +#endif + +#define DWIN_FONT_INFO font8x16 + +#if DWIN_FONT_MENU == font6x12 + #define MENU_FONT_WIDTH 6 + #define MENU_FONT_ASCENT 10 + #define MENU_FONT_DESCENT 2 +#elif DWIN_FONT_MENU == font8x16 + #define MENU_FONT_WIDTH 8 + #define MENU_FONT_ASCENT 13 + #define MENU_FONT_DESCENT 3 +#elif DWIN_FONT_MENU == font10x20 + #define MENU_FONT_WIDTH 10 + #define MENU_FONT_ASCENT 16 + #define MENU_FONT_DESCENT 4 +#endif +#define MENU_FONT_HEIGHT (MENU_FONT_ASCENT + MENU_FONT_DESCENT) + +#define EXTRA_ROW_HEIGHT 8 +#define MENU_LINE_HEIGHT (MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT) + +#if DWIN_FONT_EDIT == font6x12 + #define EDIT_FONT_WIDTH 6 + #define EDIT_FONT_ASCENT 10 + #define EDIT_FONT_DESCENT 2 +#elif DWIN_FONT_EDIT == font8x16 + #define EDIT_FONT_WIDTH 8 + #define EDIT_FONT_ASCENT 13 + #define EDIT_FONT_DESCENT 3 +#elif DWIN_FONT_EDIT == font10x20 + #define EDIT_FONT_WIDTH 10 + #define EDIT_FONT_ASCENT 16 + #define EDIT_FONT_DESCENT 4 +#endif +#define EDIT_FONT_HEIGHT (EDIT_FONT_ASCENT + EDIT_FONT_DESCENT) + +#if DWIN_FONT_INFO == font6x12 + #define INFO_FONT_WIDTH 6 + #define INFO_FONT_ASCENT 10 + #define INFO_FONT_DESCENT 2 +#elif DWIN_FONT_INFO == font8x16 + #define INFO_FONT_WIDTH 8 + #define INFO_FONT_ASCENT 13 + #define INFO_FONT_DESCENT 3 +#elif DWIN_FONT_INFO == font10x20 + #define INFO_FONT_WIDTH 10 + #define INFO_FONT_ASCENT 16 + #define INFO_FONT_DESCENT 4 +#endif +#define INFO_FONT_HEIGHT (INFO_FONT_ASCENT + INFO_FONT_DESCENT) + +#if DWIN_FONT_STAT == font6x12 + #define STAT_FONT_WIDTH 6 + #define STAT_FONT_ASCENT 10 + #define STAT_FONT_DESCENT 2 +#elif DWIN_FONT_STAT == font8x16 + #define STAT_FONT_WIDTH 8 + #define STAT_FONT_ASCENT 13 + #define STAT_FONT_DESCENT 3 +#elif DWIN_FONT_STAT == font10x20 + #define STAT_FONT_WIDTH 10 + #define STAT_FONT_ASCENT 16 + #define STAT_FONT_DESCENT 4 +#elif DWIN_FONT_STAT == font12x24 + #define STAT_FONT_WIDTH 12 + #define STAT_FONT_ASCENT 19 + #define STAT_FONT_DESCENT 5 +#elif DWIN_FONT_STAT == font14x28 + #define STAT_FONT_WIDTH 14 + #define STAT_FONT_ASCENT 22 + #define STAT_FONT_DESCENT 6 +#elif DWIN_FONT_STAT == font16x32 + #define STAT_FONT_WIDTH 16 + #define STAT_FONT_ASCENT 26 + #define STAT_FONT_DESCENT 6 +#elif DWIN_FONT_STAT == font20x40 + #define STAT_FONT_WIDTH 20 + #define STAT_FONT_ASCENT 32 + #define STAT_FONT_DESCENT 8 +#elif DWIN_FONT_STAT == font24x48 + #define STAT_FONT_WIDTH 24 + #define STAT_FONT_ASCENT 38 + #define STAT_FONT_DESCENT 10 +#elif DWIN_FONT_STAT == font28x56 + #define STAT_FONT_WIDTH 28 + #define STAT_FONT_ASCENT 44 + #define STAT_FONT_DESCENT 12 +#elif DWIN_FONT_STAT == font32x64 + #define STAT_FONT_WIDTH 32 + #define STAT_FONT_ASCENT 50 + #define STAT_FONT_DESCENT 14 +#endif +#define STAT_FONT_HEIGHT (STAT_FONT_ASCENT + STAT_FONT_DESCENT) diff --git a/src/lcd/e3v2/marlinui/ui_common.cpp b/src/lcd/e3v2/marlinui/ui_common.cpp new file mode 100644 index 0000000..ab21c7b --- /dev/null +++ b/src/lcd/e3v2/marlinui/ui_common.cpp @@ -0,0 +1,594 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 IS_DWIN_MARLINUI + +#include "marlinui_dwin.h" +#include "dwin_lcd.h" +#include "dwin_string.h" + +//#include "../../lcdprint.h" +#include "lcdprint_dwin.h" +#include "../../fontutils.h" +#include "../../../libs/numtostr.h" +#include "../../marlinui.h" + +#include "../../../sd/cardreader.h" +#include "../../../module/motion.h" +#include "../../../module/temperature.h" +#include "../../../module/printcounter.h" + +#if ENABLED(SDSUPPORT) + #include "../../../libs/duration_t.h" +#endif + +#if ENABLED(AUTO_BED_LEVELING_UBL) + #include "../../../feature/bedlevel/bedlevel.h" +#endif + +// DWIN printing specifies the font on each string operation +// but we'll make the font modal for Marlin +dwin_font_t dwin_font = { font8x16, 8, 16, Color_White, Color_Bg_Black, true }; +void MarlinUI::set_font(const uint8_t font_nr) { + if (font_nr != dwin_font.index) { + dwin_font.index = font_nr; + uint8_t w, h; + switch (font_nr) { + default: + case font6x12: w = 6; h = 12; break; + case font8x16: w = 8; h = 16; break; + case font10x20: w = 10; h = 20; break; + case font12x24: w = 12; h = 24; break; + case font14x28: w = 14; h = 28; break; + case font16x32: w = 16; h = 32; break; + case font20x40: w = 20; h = 40; break; + case font24x48: w = 24; h = 48; break; + case font28x56: w = 28; h = 56; break; + case font32x64: w = 32; h = 64; break; + } + dwin_font.width = w; + dwin_font.height = h; + // TODO: Array with dimensions, auto fit menu items, + // update char width / height of the screen based on + // new (fixed-width) font size. + } +} + +// This display is always detected +bool MarlinUI::detected() { return true; } + +// Initialize or re-initialize the LCD +void MarlinUI::init_lcd() { DWIN_Startup(); } + +// This LCD should clear where it will draw anew +void MarlinUI::clear_lcd() { + DWIN_ICON_AnimationControl(0x0000); // disable all icon animations + DWIN_JPG_ShowAndCache(3); + DWIN_Frame_Clear(Color_Bg_Black); + DWIN_UpdateLCD(); + + did_first_redraw = false; +} + +#if ENABLED(SHOW_BOOTSCREEN) + + void MarlinUI::show_bootscreen() { + dwin_string.set(F(SHORT_BUILD_VERSION)); + + #if ENABLED(SHOW_CUSTOM_BOOTSCREEN) && !defined(CUSTOM_BOOTSCREEN_TIMEOUT) + #define CUSTOM_BOOTSCREEN_TIMEOUT 3000 + #endif + + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + #define LOGO_CENTER ((LCD_PIXEL_WIDTH) / 2) + #define INFO_CENTER LOGO_CENTER + #define VERSION_Y 330 + #else + #define LOGO_CENTER (280 / 2) + #define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2) + #define VERSION_Y 84 + #endif + + DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length * 10) / 2, VERSION_Y, S(dwin_string.string())); + TERN_(SHOW_CUSTOM_BOOTSCREEN, safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT)); + clear_lcd(); + + DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15); + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, LOGO_CENTER - 174 / 2, 280); + DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL, LOGO_CENTER - 180 / 2, 420); + DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL, LOGO_CENTER - 100 / 2, 440); + DWIN_ICON_Show(BOOT_ICON, ICON_Copyright, LOGO_CENTER - 126 / 2, 460); + #else + DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15); + DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, INFO_CENTER - 174 / 2, 60); + DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL, INFO_CENTER - 180 / 2, 130); + DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL, INFO_CENTER - 100 / 2, 152); + DWIN_ICON_Show(BOOT_ICON, ICON_Copyright, INFO_CENTER - 126 / 2, 200); + #endif + DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length * 10) / 2, VERSION_Y, S(dwin_string.string())); + DWIN_UpdateLCD(); + } + + void MarlinUI::bootscreen_completion(const millis_t sofar) { + if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar); + clear_lcd(); + } + +#endif + +// The kill screen is displayed for unrecoverable conditions +void MarlinUI::draw_kill_screen() { + set_font(DWIN_FONT_ALERT); + DWIN_Frame_Clear(Color_Bg_Black); + dwin_font.fg = Color_Error_Red; + dwin_font.solid = false; + DWIN_Draw_Rectangle(1, Color_Bg_Window, 20, 20, LCD_PIXEL_WIDTH - 20, LCD_PIXEL_HEIGHT - 20); + // make the frame a few pixels thick + DWIN_Draw_Rectangle(0, Color_Yellow, 20, 20, LCD_PIXEL_WIDTH - 20, LCD_PIXEL_HEIGHT - 20); + DWIN_Draw_Rectangle(0, Color_Yellow, 21, 21, LCD_PIXEL_WIDTH - 21, LCD_PIXEL_HEIGHT - 21); + DWIN_Draw_Rectangle(0, Color_Yellow, 22, 22, LCD_PIXEL_WIDTH - 22, LCD_PIXEL_HEIGHT - 22); + + uint8_t cx = (LCD_PIXEL_WIDTH / dwin_font.width / 2), + cy = (LCD_PIXEL_HEIGHT / dwin_font.height / 2); + + #if ENABLED(DWIN_MARLINUI_LANDSCAPE) + cx += (96 / 2 / dwin_font.width); + DWIN_ICON_Show(ICON, ICON_Halted, 40, (LCD_PIXEL_HEIGHT - 96) / 2); + #else + DWIN_ICON_Show(ICON, ICON_Halted, (LCD_PIXEL_WIDTH - 96) / 2, 40); + #endif + + uint8_t slen = utf8_strlen(status_message); + lcd_moveto(cx - (slen / 2), cy - 1); + lcd_put_u8str(status_message); + + slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED))); + lcd_moveto(cx - (slen / 2), cy); + lcd_put_u8str(GET_TEXT_F(MSG_HALTED)); + + slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED))); + lcd_moveto(cx - (slen / 2), cy + 1); + lcd_put_u8str(GET_TEXT_F(MSG_HALTED)); +} + +// +// Status Message +// +void MarlinUI::draw_status_message(const bool blink) { + set_font(DWIN_FONT_STAT); + dwin_font.solid = true; + dwin_font.fg = Color_White; + dwin_font.bg = Color_Bg_Black; + lcd_moveto_xy(0, LCD_PIXEL_HEIGHT - (STAT_FONT_HEIGHT) - 1); + + constexpr uint8_t max_status_chars = (LCD_PIXEL_WIDTH) / (STAT_FONT_WIDTH); + + auto status_changed = []{ + static uint16_t old_hash = 0x0000; + uint16_t hash = 0x0000; + for (uint8_t i = 0; i < MAX_MESSAGE_LENGTH; i++) { + const char c = ui.status_message[i]; + if (!c) break; + hash = ((hash << 1) | (hash >> 15)) ^ c; + } + const bool hash_changed = hash != old_hash; + old_hash = hash; + return hash_changed || !ui.did_first_redraw; + }; + + #if ENABLED(STATUS_MESSAGE_SCROLLING) + static bool last_blink = false; + + // Get the UTF8 character count of the string + uint8_t slen = utf8_strlen(status_message); + + // If the string fits into the LCD, just print it and do not scroll it + if (slen <= max_status_chars) { + + if (status_changed()) { + + // The string isn't scrolling and may not fill the screen + lcd_put_u8str(status_message); + + // Fill the rest with spaces + while (slen < max_status_chars) { lcd_put_lchar(' '); ++slen; } + } + } + else { + // String is larger than the available line space + + // Get a pointer to the next valid UTF8 character + // and the string remaining length + uint8_t rlen; + const char *stat = status_and_len(rlen); + lcd_put_u8str_max(stat, max_status_chars); + + // If the string doesn't completely fill the line... + if (rlen < max_status_chars) { + lcd_put_lchar('.'); // Always at 1+ spaces left, draw a dot + uint8_t chars = max_status_chars - rlen; // Amount of space left in characters + if (--chars) { // Draw a second dot if there's space + lcd_put_lchar('.'); + if (--chars) + lcd_put_u8str_max(status_message, chars); // Print a second copy of the message + } + } + + if (last_blink != blink) { + last_blink = blink; + advance_status_scroll(); + } + } + + #else + + UNUSED(blink); + + if (status_changed()) { + // Get the UTF8 character count of the string + uint8_t slen = utf8_strlen(status_message); + + // Just print the string to the LCD + lcd_put_u8str_max(status_message, max_status_chars); + + // Fill the rest with spaces if there are missing spaces + while (slen < max_status_chars) { lcd_put_lchar(' '); ++slen; } + } + + #endif +} + +#if HAS_LCD_BRIGHTNESS + void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); } +#endif + +#if HAS_MARLINUI_MENU + + #include "../../menu/menu.h" + + #if ENABLED(ADVANCED_PAUSE_FEATURE) + + void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) { + + dwin_font.solid = false; + dwin_font.fg = Color_White; + dwin_string.set('E'); + dwin_string.add('1' + extruder); + dwin_string.add(' '); + dwin_string.add(i16tostr3rj(thermalManager.degHotend(extruder))); + dwin_string.add('/'); + if (get_blink() || !thermalManager.heater_idle[thermalManager.idle_index_for_id(extruder)].timed_out) + dwin_string.add(i16tostr3rj(thermalManager.degTargetHotend(extruder))); + else + dwin_string.add(F(" ")); + + lcd_moveto(LCD_WIDTH - dwin_string.length, row); + lcd_put_dwin_string(); + } + + #endif + + // Set the colors for a menu item based on whether it is selected + static bool mark_as_selected(const uint8_t row, const bool sel, const bool is_static=false) { + const dwin_coord_t y = row * (MENU_LINE_HEIGHT) + 1; + if (y >= LCD_PIXEL_HEIGHT) return false; + + if (is_static && sel) + DWIN_Draw_Box(1, Color_Bg_Heading, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1); + else { + #if ENABLED(MENU_HOLLOW_FRAME) + DWIN_Draw_Box(1, Color_Bg_Black, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1); + if (sel) DWIN_Draw_Box(0, Select_Color, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1); + #else + DWIN_Draw_Box(1, sel ? Select_Color : Color_Bg_Black, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1); + #endif + } + + return true; + } + + // Draw a static line of text in the same idiom as a menu item + + void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) { + // Call mark_as_selected to draw a bigger selection box + // and draw the text without a background + if (mark_as_selected(row, (bool)(style & SS_INVERT), true)) { + ui.set_font(DWIN_FONT_MENU); + dwin_font.solid = false; + dwin_font.fg = Color_White; + + dwin_string.set(); + const int8_t plen = ftpl ? utf8_strlen(ftpl) : 0, + vlen = vstr ? utf8_strlen(vstr) : 0; + if (style & SS_CENTER) { + int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2; + while (--pad) dwin_string.add(' '); + } + + if (plen) dwin_string.add(ftpl, itemIndex, itemStringC, itemStringF); + if (vlen) dwin_string.add(vstr); + if (style & SS_CENTER) { + int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2; + while (--pad) dwin_string.add(' '); + } + + lcd_moveto(1, row); + lcd_put_dwin_string(); + } + } + + // Draw a generic menu item + void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char, const char post_char) { + if (mark_as_selected(row, sel)) { + ui.set_font(DWIN_FONT_MENU); + dwin_font.solid = false; + dwin_font.fg = Color_White; + + dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF); + + pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length; + while (--n > 1) dwin_string.add(' '); + + dwin_string.add(post_char); + + lcd_moveto(1, row); + lcd_put_dwin_string(); + } + } + + // + // Draw a menu item with an editable value + // + void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) { + if (mark_as_selected(row, sel)) { + ui.set_font(DWIN_FONT_MENU); + dwin_font.solid = false; + dwin_font.fg = Color_White; + + const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(S(inStr))); + + dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF); + if (vallen) dwin_string.add(':'); + + lcd_moveto(1, row); + lcd_put_dwin_string(); + + if (vallen) { + dwin_font.fg = Color_Yellow; + dwin_string.set(inStr); + lcd_moveto(LCD_WIDTH - vallen - 1, row); + lcd_put_dwin_string(); + } + } + } + + // + // Draw an edit screen with label and current value + // + void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char* const value/*=nullptr*/) { + ui.encoder_direction_normal(); + + const dwin_coord_t labellen = utf8_strlen(fstr), vallen = utf8_strlen(value); + + dwin_string.set(FTOP(fstr), itemIndex); + if (vallen) dwin_string.add(':'); // If a value is included, add a colon + + // Assume the label is alpha-numeric (with a descender) + const uint16_t row = (LCD_HEIGHT / 2) - 1; + + dwin_font.fg = Color_White; + dwin_font.solid = true; + lcd_moveto((LCD_WIDTH - labellen + !!vallen) / 2, row); + lcd_put_dwin_string(); + + // If a value is included, print the value in larger text below the label + if (vallen) { + dwin_string.set(value); + + const dwin_coord_t by = (row * MENU_LINE_HEIGHT) + MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT / 2; + DWIN_Draw_String(true, font16x32, Color_Yellow, Color_Bg_Black, (LCD_PIXEL_WIDTH - vallen * 16) / 2, by, S(dwin_string.string())); + + if (ui.can_show_slider()) { + + const dwin_coord_t slider_length = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_LANDSCAPE, 120, 20), + slider_height = 16, + slider_x = (LCD_PIXEL_WIDTH - slider_length) / 2, + slider_y = by + 32 + 4, + amount = ui.encoderPosition * slider_length / maxEditValue; + + DWIN_Draw_Rectangle(1, Color_Bg_Window, slider_x - 1, slider_y - 1, slider_x - 1 + slider_length + 2 - 1, slider_y - 1 + slider_height + 2 - 1); + if (amount > 0) + DWIN_Draw_Box(1, BarFill_Color, slider_x, slider_y, amount, slider_height); + if (amount < slider_length) + DWIN_Draw_Box(1, Color_Bg_Black, slider_x + amount, slider_y, slider_length - amount, slider_height); + } + } + } + + inline void draw_boxed_string(const bool yesopt, FSTR_P const fstr, const bool inv) { + const uint8_t len = utf8_strlen(fstr), + mar = TERN(DWIN_MARLINUI_PORTRAIT, 1, 4), + col = yesopt ? LCD_WIDTH - mar - len : mar, + row = (LCD_HEIGHT >= 8 ? LCD_HEIGHT / 2 + 3 : LCD_HEIGHT - 1); + lcd_moveto(col, row); + DWIN_Draw_Box(1, inv ? Select_Color : Color_Bg_Black, cursor.x - dwin_font.width, cursor.y + 1, dwin_font.width * (len + 2), dwin_font.height + 2); + lcd_put_u8str(col, row, fstr); + } + + void MenuItem_confirm::draw_select_screen( + FSTR_P const yes, FSTR_P const no, const bool yesno, + FSTR_P const pref, const char * const string/*=nullptr*/, FSTR_P const suff/*=nullptr*/ + ) { + ui.set_font(DWIN_FONT_MENU); + dwin_font.solid = false; + dwin_font.fg = Color_White; + ui.draw_select_screen_prompt(pref, string, suff); + if (no) draw_boxed_string(false, no, !yesno); + if (yes) draw_boxed_string(true, yes, yesno); + } + + #if ENABLED(SDSUPPORT) + + void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) { + if (mark_as_selected(row, sel)) { + dwin_string.set(); + + uint8_t maxlen = LCD_WIDTH - 1; + if (isDir) { + dwin_string.add(LCD_STR_FOLDER " "); + maxlen -= 2; + } + + dwin_string.add(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen); + uint8_t n = maxlen - dwin_string.length; + while (n > 0) { dwin_string.add(' '); --n; } + lcd_moveto(1, row); + lcd_put_dwin_string(); + } + } + + #endif // SDSUPPORT + + #if ENABLED(AUTO_BED_LEVELING_UBL) + + /** + * UBL LCD "radar" map data + */ + #define MAP_UPPER_LEFT_CORNER_X 5 // These probably should be moved to the .h file But for now, + #define MAP_UPPER_LEFT_CORNER_Y 5 // it is easier to play with things having them here + #define MAP_MAX_PIXELS_X 262 // 272 - 10 + #define MAP_MAX_PIXELS_Y 262 + + void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) { + // Scale the box pixels appropriately + dwin_coord_t x_map_pixels = ((MAP_MAX_PIXELS_X - 4) / (GRID_MAX_POINTS_X)) * (GRID_MAX_POINTS_X), + y_map_pixels = ((MAP_MAX_PIXELS_Y - 4) / (GRID_MAX_POINTS_Y)) * (GRID_MAX_POINTS_Y), + + pixels_per_x_mesh_pnt = x_map_pixels / (GRID_MAX_POINTS_X), + pixels_per_y_mesh_pnt = y_map_pixels / (GRID_MAX_POINTS_Y), + + x_offset = MAP_UPPER_LEFT_CORNER_X + 1 + (MAP_MAX_PIXELS_X - x_map_pixels - 2) / 2, + y_offset = MAP_UPPER_LEFT_CORNER_Y + 1 + (MAP_MAX_PIXELS_Y - y_map_pixels - 2) / 2; + + // Clear the Mesh Map + + // First draw the bigger box in White so we have a border around the mesh map box + DWIN_Draw_Rectangle(1, Color_White, x_offset - 2, y_offset - 2, x_offset + 2 + x_map_pixels, y_offset + 2 + y_map_pixels); + // Now actually clear the mesh map box + DWIN_Draw_Rectangle(1, Color_Bg_Black, x_offset, y_offset, x_offset + x_map_pixels, y_offset + y_map_pixels); + + // Fill in the Specified Mesh Point + + const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot; // The origin is typically in the lower right corner. We need to + // invert the Y to get it to plot in the right location. + + const dwin_coord_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt; + DWIN_Draw_Rectangle(1, Select_Color, + x_offset + (x_plot * pixels_per_x_mesh_pnt), by, + x_offset + (x_plot * pixels_per_x_mesh_pnt) + pixels_per_x_mesh_pnt, by + pixels_per_y_mesh_pnt + ); + + // Display Mesh Point Locations + const dwin_coord_t sx = x_offset + pixels_per_x_mesh_pnt / 2; + dwin_coord_t y = y_offset + pixels_per_y_mesh_pnt / 2; + for (uint8_t j = 0; j < (GRID_MAX_POINTS_Y); j++, y += pixels_per_y_mesh_pnt) + for (uint8_t i = 0, x = sx; i < (GRID_MAX_POINTS_X); i++, x += pixels_per_x_mesh_pnt) + DWIN_Draw_Point(Color_White, 1, 1, x, y); + + // Put Relevant Text on Display + + // Show X and Y positions at top of screen + dwin_font.fg = Color_White; + dwin_font.solid = true; + const xy_pos_t pos = { bedlevel.get_mesh_x(x_plot), bedlevel.get_mesh_y(y_plot) }, + lpos = pos.asLogical(); + + lcd_moveto( + TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, 1), + TERN(DWIN_MARLINUI_LANDSCAPE, 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1) + ); + lcd_put_u8str_P(X_LBL); + lcd_put_u8str(ftostr52(lpos.x)); + lcd_moveto( + TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, 1), + TERN(DWIN_MARLINUI_LANDSCAPE, 3, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2) + ); + lcd_put_u8str_P(Y_LBL); + lcd_put_u8str(ftostr52(lpos.y)); + + // Print plot position + dwin_string.set('('); + dwin_string.add(i8tostr3rj(x_plot)); + dwin_string.add(','); + dwin_string.add(i8tostr3rj(y_plot)); + dwin_string.add(')'); + lcd_moveto( + TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length), + TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 2, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1) + ); + lcd_put_dwin_string(); + + // Show the location value + dwin_string.set(Z_LBL); + if (!isnan(bedlevel.z_values[x_plot][y_plot])) + dwin_string.add(ftostr43sign(bedlevel.z_values[x_plot][y_plot])); + else + dwin_string.add(F(" -----")); + lcd_moveto( + TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length), + TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2) + ); + lcd_put_dwin_string(); + } + + #endif // AUTO_BED_LEVELING_UBL + + #if EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY) + + void MarlinUI::zoffset_overlay(const int8_t dir) { + const int rot_up = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCCW, ICON_RotateCW), + rot_down = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCW, ICON_RotateCCW); + + const int nozzle = (LCD_PIXEL_WIDTH / 2) - 20; + + // Draw a representation of the nozzle + DWIN_Draw_Box(1, Color_Bg_Black, nozzle + 3, 8, 48, 52); // 'clear' the area where the nozzle is drawn in case it was moved up/down + DWIN_ICON_Show(ICON, ICON_HotendOff, nozzle + 3, 10 - dir); + DWIN_ICON_Show(ICON, ICON_BedLine, nozzle, 10 + 36); + + // Draw cw/ccw indicator and up/down arrows + const int arrow_y = LCD_PIXEL_HEIGHT / 2 - 24; + DWIN_ICON_Show(ICON, ICON_DownArrow, 0, arrow_y - dir); + DWIN_ICON_Show(ICON, rot_down, 48, arrow_y); + + DWIN_ICON_Show(ICON, ICON_UpArrow, LCD_PIXEL_WIDTH - 10 - (48*2), arrow_y - dir); + DWIN_ICON_Show(ICON, rot_up, LCD_PIXEL_WIDTH - 10 - 48, arrow_y); + } + + #endif // BABYSTEP_ZPROBE_GFX_OVERLAY || MESH_EDIT_GFX_OVERLAY + +#endif // HAS_MARLINUI_MENU + +#endif // IS_DWIN_MARLINUI diff --git a/src/lcd/e3v2/marlinui/ui_status_480x272.cpp b/src/lcd/e3v2/marlinui/ui_status_480x272.cpp new file mode 100644 index 0000000..8024085 --- /dev/null +++ b/src/lcd/e3v2/marlinui/ui_status_480x272.cpp @@ -0,0 +1,474 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 IS_DWIN_MARLINUI + +#include "marlinui_dwin.h" +#include "dwin_lcd.h" +#include "dwin_string.h" +#include "lcdprint_dwin.h" + +#include "../../fontutils.h" +#include "../../../libs/numtostr.h" +#include "../../marlinui.h" + +#include "../../../sd/cardreader.h" +#include "../../../module/motion.h" +#include "../../../module/temperature.h" +#include "../../../module/printcounter.h" +#include "../../../module/planner.h" + +#if ENABLED(SDSUPPORT) + #include "../../../libs/duration_t.h" +#endif + +#if ENABLED(LCD_SHOW_E_TOTAL) + #include "../../../MarlinCore.h" // for printingIsActive +#endif + +#if ENABLED(DWIN_MARLINUI_PORTRAIT) + #define STATUS_HEATERS_X 15 + #define STATUS_HEATERS_Y 56 +#else + #define STATUS_HEATERS_X 154 + #define STATUS_HEATERS_Y 10 +#endif +#define STATUS_HEATERS_XSPACE 64 +#define STATUS_FAN_WIDTH 48 +#define STATUS_FAN_HEIGHT 48 +#define STATUS_FAN_Y STATUS_HEATERS_Y + 22 +#define STATUS_CHR_WIDTH 14 +#define STATUS_CHR_HEIGHT 28 + +// +// Before homing, blink '123' <-> '???'. +// Homed but unknown... '123' <-> ' '. +// Homed and known, display constantly. +// +FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink, const uint16_t x, const uint16_t y) { + + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + + uint8_t vallen = utf8_strlen(value); + if (!ui.did_first_redraw) { + dwin_string.set('X' + axis); + DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (vallen * 14 - 14) / 2, y + 2, S(dwin_string.string())); + } + + dwin_string.set(); + if (blink) + dwin_string.add(value); + else if (!TEST(axes_homed, axis)) + while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?'); + else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axes_trusted, axis)) + dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" ")); + else + dwin_string.add(value); + + // For E_TOTAL there may be some characters to cover up + if (BOTH(DWIN_MARLINUI_PORTRAIT, LCD_SHOW_E_TOTAL) && axis == X_AXIS) + dwin_string.add(F(" ")); + + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string())); + + #else // !DWIN_MARLINUI_PORTRAIT + + if (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) { + dwin_string.set('X' + axis); + DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string())); + } + + dwin_string.set(); + if (blink) + dwin_string.add(value); + else { + if (!TEST(axes_homed, axis)) + while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?'); + else { + #if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) + if (!TEST(axes_trusted, axis)) + dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" ")); + else + #endif + dwin_string.add(value); + } + } + + // For E_TOTAL there may be some characters to cover up + if (ENABLED(LCD_SHOW_E_TOTAL) && (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) && axis == X_AXIS) + dwin_string.add(F(" ")); + + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 32, y + 4, S(dwin_string.string())); + + #endif // !DWIN_MARLINUI_PORTRAIT +} + +#if ENABLED(LCD_SHOW_E_TOTAL) + + FORCE_INLINE void _draw_e_value(const_float_t value, const uint16_t x, const uint16_t y) { + const uint8_t scale = value >= 100000.0f ? 10 : 1; // show cm after 99,999mm + + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + + if (!ui.did_first_redraw) { + // Extra spaces to erase previous value + dwin_string.set(F("E ")); + DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (4 * 14 / 2) - 7, y + 2, S(dwin_string.string())); + } + + dwin_string.set(ui16tostr5rj(value / scale)); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string())); + + // Extra spaces to erase previous value + DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (5 * 14), y + 32, S(scale == 1 ? "mm " : "cm ")); + + #else // !DWIN_MARLINUI_PORTRAIT + + if (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) { + dwin_string.set(F("E ")); + DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string())); + } + + dwin_string.set(ui16tostr5rj(value / scale)); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 32, y + 4, S(dwin_string.string())); + + DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (32 + 70), y + 4, S(scale == 1 ? "mm " : "cm ")); + + #endif // !DWIN_MARLINUI_PORTRAIT + } + +#endif // LCD_SHOW_E_TOTAL + +// +// Fan Icon and Percentage +// +FORCE_INLINE void _draw_fan_status(const uint16_t x, const uint16_t y) { + const uint16_t fanx = (4 * STATUS_CHR_WIDTH - STATUS_FAN_WIDTH) / 2; + const uint8_t fan_pct = thermalManager.scaledFanSpeedPercent(0); + const bool fan_on = !!fan_pct; + if (fan_on) { + DWIN_ICON_Animation(0, fan_on, ICON, ICON_Fan0, ICON_Fan3, x + fanx, y, 25); + dwin_string.set(i8tostr3rj(fan_pct)); + dwin_string.add('%'); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string())); + } + else { + DWIN_ICON_AnimationControl(0x0000); // disable all icon animations (this is the only one) + DWIN_ICON_Show(ICON, ICON_Fan0, x + fanx, y); + dwin_string.set(F(" ")); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string())); + } +} + +/** + * Draw a single heater icon with current and target temperature, at the given XY + */ +FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x, const uint16_t y) { + + #if HAS_HOTEND + #if HOTENDS > 2 + #define HOTEND_STATS 3 + #elif HOTENDS > 1 + #define HOTEND_STATS 2 + #else + #define HOTEND_STATS 1 + #endif + static celsius_t old_temp[HOTEND_STATS] = { 0 }, + old_target[HOTEND_STATS] = { 0 }; + static bool old_on[HOTEND_STATS] = { false }; + #endif + + #if HAS_HEATED_BED + static celsius_t old_bed_temp = 0, old_bed_target = 0; + static bool old_bed_on = false; + #if HAS_LEVELING + static bool old_leveling_on = false; + #endif + #endif + + #if HAS_HOTEND && HAS_HEATED_BED + float tc, tt; + bool c_draw, t_draw, i_draw, ta; + const bool isBed = heater < 0; + if (isBed) { + tc = thermalManager.degBed(); + tt = thermalManager.degTargetBed(); + ta = thermalManager.isHeatingBed(); + c_draw = tc != old_bed_temp; + t_draw = tt != old_bed_target; + i_draw = ta != old_bed_on; + old_bed_temp = tc; + old_bed_target = tt; + old_bed_on = ta; + } + else { + tc = thermalManager.degHotend(heater); + tt = thermalManager.degTargetHotend(heater); + ta = thermalManager.isHeatingHotend(heater); + c_draw = tc != old_temp[heater]; + t_draw = tt != old_target[heater]; + i_draw = ta != old_on[heater]; + old_temp[heater] = tc; + old_target[heater] = tt; + old_on[heater] = ta; + } + #elif HAS_HOTEND + constexpr bool isBed = false; + const float tc = thermalManager.degHotend(heater), tt = thermalManager.degTargetHotend(heater); + const uint8_t ta = thermalManager.isHeatingHotend(heater); + bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater]; + old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta; + #elif HAS_HEATED_BED + constexpr bool isBed = true; + const float tc = thermalManager.degBed(), tt = thermalManager.degTargetBed(); + const uint8_t ta = thermalManager.isHeatingBed(); + bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on; + old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta; + #else + bool c_draw = false, t_draw = false, i_draw = false; + constexpr float tc = 0, tt = 0; + constexpr uint8_t ta = 0; + #endif + + #if HAS_HEATED_BED && HAS_LEVELING + if (isBed) { + i_draw |= (planner.leveling_active != old_leveling_on); + old_leveling_on = planner.leveling_active; + } + #endif + + // Draw target temperature, if needed + if (!ui.did_first_redraw || t_draw) { + dwin_string.set(i16tostr3rj(tt + 0.5)); + dwin_string.add(LCD_STR_DEGREE); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y, S(dwin_string.string())); + } + + // Draw heater icon with on / off / leveled states + if (!ui.did_first_redraw || i_draw) { + const uint8_t ico = isBed ? (TERN0(HAS_LEVELING, planner.leveling_active) ? ICON_BedLevelOff : ICON_BedOff) : ICON_HotendOff; + DWIN_ICON_Show(ICON, ico + ta, x, y + STATUS_CHR_HEIGHT + 2); + } + + // Draw current temperature, if needed + if (!ui.did_first_redraw || c_draw) { + dwin_string.set(i16tostr3rj(tc + 0.5)); + dwin_string.add(LCD_STR_DEGREE); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 70, S(dwin_string.string())); + } +} + +/** + * Draw the current "feed rate" percentage preceded by the >> character + */ +FORCE_INLINE void _draw_feedrate_status(const char *value, uint16_t x, uint16_t y) { + if (!ui.did_first_redraw) { + dwin_string.set(LCD_STR_FEEDRATE); + DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string())); + } + + dwin_string.set(value); + dwin_string.add('%'); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 14, y, S(dwin_string.string())); +} + +/** + * Draw the MarlinUI Status Screen for Ender 3 V2 + */ +void MarlinUI::draw_status_screen() { + const bool blink = get_blink(); + + // Draw elements that never change + if (!ui.did_first_redraw) { + // Logo/Status Icon + #define STATUS_LOGO_WIDTH 128 + #define STATUS_LOGO_HEIGHT 40 + DWIN_ICON_Show(ICON, ICON_LOGO_Marlin, + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + (LCD_PIXEL_WIDTH - (STATUS_LOGO_WIDTH)) / 2, ((STATUS_HEATERS_Y - 4) - (STATUS_LOGO_HEIGHT)) / 2 + #else + 5, 42 + #endif + ); + + // Draw a frame around the x/y/z values + DWIN_Draw_Rectangle(0, Select_Color, + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + 0, 193, LCD_PIXEL_WIDTH, 260 + #else + 0, 115, LCD_PIXEL_WIDTH - 1, 152 + #endif + ); + } + + uint16_t hx = STATUS_HEATERS_X; + #if HAS_HOTEND + _draw_heater_status(H_E0, hx, STATUS_HEATERS_Y); + hx += STATUS_HEATERS_XSPACE; + #endif + #if HAS_MULTI_HOTEND + _draw_heater_status(H_E1, hx, STATUS_HEATERS_Y); + hx += STATUS_HEATERS_XSPACE; + #endif + #if HAS_HEATED_BED + _draw_heater_status(H_BED, hx, STATUS_HEATERS_Y); + #endif + + #if HAS_FAN + _draw_fan_status(LCD_PIXEL_WIDTH - STATUS_CHR_WIDTH * 5, STATUS_FAN_Y); + #endif + + // Axis values + const xyz_pos_t lpos = current_position.asLogical(); + const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive()); UNUSED(show_e_total); + + constexpr int16_t cpy = TERN(DWIN_MARLINUI_PORTRAIT, 195, 117); + if (show_e_total) { + TERN_(LCD_SHOW_E_TOTAL, _draw_e_value(e_move_accumulator, TERN(DWIN_MARLINUI_PORTRAIT, 6, 75), cpy)); + } + else { + _draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink, TERN(DWIN_MARLINUI_PORTRAIT, 6, 75), cpy); + TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink, TERN(DWIN_MARLINUI_PORTRAIT, 95, 184), cpy)); + } + TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, TERN(DWIN_MARLINUI_PORTRAIT, 165, 300), cpy)); + + // Feedrate + static uint16_t old_fp = 0; + if (!ui.did_first_redraw || old_fp != feedrate_percentage) { + old_fp = feedrate_percentage; + _draw_feedrate_status(i16tostr3rj(feedrate_percentage), + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + 5, 290 + #else + 14, 195 + #endif + ); + } + + // + // Elapsed time + // + char buffer[14]; + duration_t time; + + #if ENABLED(DWIN_MARLINUI_PORTRAIT) + + // Portrait mode only shows one value at a time, and will rotate if ROTATE_PROGRESS_DISPLAY + dwin_string.set(); + char prefix = ' '; + #if ENABLED(SHOW_REMAINING_TIME) + if (TERN1(ROTATE_PROGRESS_DISPLAY, blink) && print_job_timer.isRunning()) { + time = get_remaining_time(); + prefix = 'R'; + } + else + #endif + time = print_job_timer.duration(); + + time.toDigital(buffer); + dwin_string.add(prefix); + dwin_string.add(buffer); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, (LCD_PIXEL_WIDTH - ((dwin_string.length + 1) * 14)), 290, S(dwin_string.string())); + + #else + + // landscape mode shows both elapsed and remaining (if SHOW_REMAINING_TIME) + time = print_job_timer.duration(); + time.toDigital(buffer); + dwin_string.set(' '); + dwin_string.add(buffer); + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 230, 170, S(dwin_string.string())); + + #if ENABLED(SHOW_REMAINING_TIME) + if (print_job_timer.isRunning()) { + time = get_remaining_time(); + DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 336, 170, S(" R ")); + if (print_job_timer.isPaused() && blink) + dwin_string.set(F(" ")); + else { + time.toDigital(buffer); + dwin_string.set(buffer); + } + DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 378, 170, S(dwin_string.string())); + } + else if (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) { + dwin_string.set(F(" ")); + DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 336, 170, S(dwin_string.string())); + } + #endif + #endif + + // + // Progress Bar + // + #if HAS_PRINT_PROGRESS + constexpr int16_t pb_margin = 5, + pb_left = pb_margin + TERN(DWIN_MARLINUI_PORTRAIT, 0, 90), + pb_height = TERN(DWIN_MARLINUI_PORTRAIT, 60, 20), + pb_right = LCD_PIXEL_WIDTH - pb_margin, + pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 220), + pb_top = pb_bottom - pb_height, + pb_width = pb_right - pb_left; + + const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)(); + + if (!ui.did_first_redraw) + DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom); // Outline + + static uint16_t old_solid = 50; + const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f; + const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid; + + if (p_draw) { + //if (pb_solid) + DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part + + //if (pb_solid < old_solid) + DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest + + #if ENABLED(SHOW_SD_PERCENT) + dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE)))); + dwin_string.add('%'); + DWIN_Draw_String( + false, font16x32, Percent_Color, Color_Bg_Black, + pb_left + (pb_width - dwin_string.length * 16) / 2, + pb_top + (pb_height - 32) / 2, + S(dwin_string.string()) + ); + #endif + + old_solid = pb_solid; + } + #endif // HAS_PRINT_PROGRESS + + // + // Status Message + // + draw_status_message(blink); + + ui.did_first_redraw = true; + ui.old_is_printing = print_job_timer.isRunning(); +} + +#endif // IS_DWIN_MARLINUI diff --git a/src/lcd/e3v2/proui/base64.hpp b/src/lcd/e3v2/proui/base64.hpp new file mode 100644 index 0000000..5c9a9fe --- /dev/null +++ b/src/lcd/e3v2/proui/base64.hpp @@ -0,0 +1,208 @@ +/** + * Base64 encoder/decoder for arduino repo + * Uses common web conventions - '+' for 62, '/' for 63, '=' for padding. + * Note that invalid base64 characters are interpreted as padding. + * Author: Densaugeo + * Maintainer: Densaugeo + * Version: 1.2.1.1 + * Changed unsigned int to uint16_t for use in the professional Ender 3V2/S1 firmware + * Url: https://www.arduino.cc/reference/en/libraries/base64/ + */ + +#ifndef BASE64_H_INCLUDED +#define BASE64_H_INCLUDED + +/* binary_to_base64: + * Description: + * Converts a single byte from a binary value to the corresponding base64 character + * Parameters: + * v - Byte to convert + * Returns: + * ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character + * and 255 is returned + */ +unsigned char binary_to_base64(unsigned char v); + +/* base64_to_binary: + * Description: + * Converts a single byte from a base64 character to the corresponding binary value + * Parameters: + * c - Base64 character (as ascii code) + * Returns: + * 6-bit binary value + */ +unsigned char base64_to_binary(unsigned char c); + +/* encode_base64_length: + * Description: + * Calculates length of base64 string needed for a given number of binary bytes + * Parameters: + * input_length - Amount of binary data in bytes + * Returns: + * Number of base64 characters needed to encode input_length bytes of binary data + */ +uint16_t encode_base64_length(uint16_t input_length); + +/* decode_base64_length: + * Description: + * Calculates number of bytes of binary data in a base64 string + * Variant that does not use input_length no longer used within library, retained for API compatibility + * Parameters: + * input - Base64-encoded null-terminated string + * input_length (optional) - Number of bytes to read from input pointer + * Returns: + * Number of bytes of binary data in input + */ +uint16_t decode_base64_length(unsigned char input[]); +uint16_t decode_base64_length(unsigned char input[], uint16_t input_length); + +/* encode_base64: + * Description: + * Converts an array of bytes to a base64 null-terminated string + * Parameters: + * input - Pointer to input data + * input_length - Number of bytes to read from input pointer + * output - Pointer to output string. Null terminator will be added automatically + * Returns: + * Length of encoded string in bytes (not including null terminator) + */ +uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]); + +/* decode_base64: + * Description: + * Converts a base64 null-terminated string to an array of bytes + * Parameters: + * input - Pointer to input string + * input_length (optional) - Number of bytes to read from input pointer + * output - Pointer to output array + * Returns: + * Number of bytes in the decoded binary + */ +uint16_t decode_base64(unsigned char input[], unsigned char output[]); +uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]); + +unsigned char binary_to_base64(unsigned char v) { + // Capital letters - 'A' is ascii 65 and base64 0 + if (v < 26) return v + 'A'; + + // Lowercase letters - 'a' is ascii 97 and base64 26 + if (v < 52) return v + 71; + + // Digits - '0' is ascii 48 and base64 52 + if (v < 62) return v - 4; + + // '+' is ascii 43 and base64 62 + if (v == 62) return '+'; + + // '/' is ascii 47 and base64 63 + if (v == 63) return '/'; + + return 64; +} + +unsigned char base64_to_binary(unsigned char c) { + // Capital letters - 'A' is ascii 65 and base64 0 + if ('A' <= c && c <= 'Z') return c - 'A'; + + // Lowercase letters - 'a' is ascii 97 and base64 26 + if ('a' <= c && c <= 'z') return c - 71; + + // Digits - '0' is ascii 48 and base64 52 + if ('0' <= c && c <= '9') return c + 4; + + // '+' is ascii 43 and base64 62 + if (c == '+') return 62; + + // '/' is ascii 47 and base64 63 + if (c == '/') return 63; + + return 255; +} + +uint16_t encode_base64_length(uint16_t input_length) { + return (input_length + 2)/3*4; +} + +uint16_t decode_base64_length(unsigned char input[]) { + return decode_base64_length(input, -1); +} + +uint16_t decode_base64_length(unsigned char input[], uint16_t input_length) { + unsigned char *start = input; + + while (base64_to_binary(input[0]) < 64 && (unsigned char)(input - start) < input_length) { + ++input; + } + + input_length = input - start; + return input_length/4*3 + (input_length % 4 ? input_length % 4 - 1 : 0); +} + +uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) { + uint16_t full_sets = input_length/3; + + // While there are still full sets of 24 bits... + for (uint16_t i = 0; i < full_sets; ++i) { + output[0] = binary_to_base64( input[0] >> 2); + output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4); + output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6); + output[3] = binary_to_base64( input[2] & 0x3F); + + input += 3; + output += 4; + } + + switch(input_length % 3) { + case 0: + output[0] = '\0'; + break; + case 1: + output[0] = binary_to_base64( input[0] >> 2); + output[1] = binary_to_base64((input[0] & 0x03) << 4); + output[2] = '='; + output[3] = '='; + output[4] = '\0'; + break; + case 2: + output[0] = binary_to_base64( input[0] >> 2); + output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4); + output[2] = binary_to_base64((input[1] & 0x0F) << 2); + output[3] = '='; + output[4] = '\0'; + break; + } + + return encode_base64_length(input_length); +} + +uint16_t decode_base64(unsigned char input[], unsigned char output[]) { + return decode_base64(input, -1, output); +} + +uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) { + uint16_t output_length = decode_base64_length(input, input_length); + + // While there are still full sets of 24 bits... + for (uint16_t i = 2; i < output_length; i += 3) { + output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4; + output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2; + output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]); + + input += 4; + output += 3; + } + + switch(output_length % 3) { + case 1: + output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4; + break; + case 2: + output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4; + output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2; + break; + } + + return output_length; +} + +#endif // ifndef diff --git a/src/lcd/e3v2/proui/bedlevel_tools.cpp b/src/lcd/e3v2/proui/bedlevel_tools.cpp new file mode 100644 index 0000000..e967c26 --- /dev/null +++ b/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -0,0 +1,286 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * Bed Level Tools for Pro UI + * Extended by: Miguel A. Risco-Castillo (MRISCOC) + * Version: 2.0.0 + * Date: 2022/05/23 + * + * Based on the original work of: Henri-J-Norden + * https://github.com/Jyers/Marlin/pull/126 + */ + +#include "../../../inc/MarlinConfigPre.h" +#include "bedlevel_tools.h" + +#if BOTH(DWIN_LCD_PROUI, HAS_LEVELING) + +#include "../../marlinui.h" +#include "../../../core/types.h" +#include "dwin.h" +#include "dwinui.h" +#include "dwin_popup.h" +#include "../../../feature/bedlevel/bedlevel.h" +#include "../../../module/probe.h" +#include "../../../gcode/gcode.h" +#include "../../../module/planner.h" +#include "../../../gcode/queue.h" +#include "../../../libs/least_squares_fit.h" +#include "../../../libs/vector_3.h" + +BedLevelToolsClass BedLevelTools; + +#if USE_UBL_VIEWER + bool BedLevelToolsClass::viewer_asymmetric_range = false; + bool BedLevelToolsClass::viewer_print_value = false; +#endif +bool BedLevelToolsClass::goto_mesh_value = false; +uint8_t BedLevelToolsClass::mesh_x = 0; +uint8_t BedLevelToolsClass::mesh_y = 0; +uint8_t BedLevelToolsClass::tilt_grid = 1; + +bool drawing_mesh = false; +char cmd[MAX_CMD_SIZE+16], str_1[16], str_2[16], str_3[16]; + +#if ENABLED(AUTO_BED_LEVELING_UBL) + + void BedLevelToolsClass::manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { + sprintf_P(cmd, PSTR("M421 I%i J%i Z%s %s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1), undefined ? "N" : ""); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } + + bool BedLevelToolsClass::create_plane_from_mesh() { + struct linear_fit_data lsf_results; + incremental_LSF_reset(&lsf_results); + GRID_LOOP(x, y) { + if (!isnan(bedlevel.z_values[x][y])) { + xy_pos_t rpos = { bedlevel.get_mesh_x(x), bedlevel.get_mesh_y(y) }; + incremental_LSF(&lsf_results, rpos, bedlevel.z_values[x][y]); + } + } + + if (finish_incremental_LSF(&lsf_results)) { + SERIAL_ECHOPGM("Could not complete LSF!"); + return true; + } + + bedlevel.set_all_mesh_points_to_value(0); + + matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1)); + GRID_LOOP(i, j) { + float mx = bedlevel.get_mesh_x(i), + my = bedlevel.get_mesh_y(j), + mz = bedlevel.z_values[i][j]; + + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOPAIR_F("before rotation = [", mx, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(my, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(mz, 7); + DEBUG_ECHOPGM("] ---> "); + DEBUG_DELAY(20); + } + + rotation.apply_rotation_xyz(mx, my, mz); + + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOPAIR_F("after rotation = [", mx, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(my, 7); + DEBUG_CHAR(','); + DEBUG_ECHO_F(mz, 7); + DEBUG_ECHOLNPGM("]"); + DEBUG_DELAY(20); + } + + bedlevel.z_values[i][j] = mz - lsf_results.D; + } + return false; + } + +#else + + void BedLevelToolsClass::manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y) { + sprintf_P(cmd, PSTR("G29 I%i J%i Z%s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1)); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } + +#endif + +void BedLevelToolsClass::manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove/*=false*/) { + gcode.process_subcommands_now(F("G28O")); + if (zmove) { + planner.synchronize(); + current_position.z = goto_mesh_value ? bedlevel.z_values[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES; + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + planner.synchronize(); + } + else { + DWIN_Show_Popup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); + HMI_SaveProcessID(NothingToDo); + sprintf_P(cmd, PSTR("G0 F300 Z%s"), dtostrf(Z_CLEARANCE_BETWEEN_PROBES, 1, 3, str_1)); + gcode.process_subcommands_now(cmd); + sprintf_P(cmd, PSTR("G42 F4000 I%i J%i"), mesh_x, mesh_y); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + current_position.z = goto_mesh_value ? bedlevel.z_values[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES; + planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder); + planner.synchronize(); + HMI_ReturnScreen(); + } +} + +void BedLevelToolsClass::MoveToXYZ() { + BedLevelTools.goto_mesh_value = true; + BedLevelTools.manual_move(BedLevelTools.mesh_x, BedLevelTools.mesh_y, false); +} +void BedLevelToolsClass::MoveToXY() { + BedLevelTools.goto_mesh_value = false; + BedLevelTools.manual_move(BedLevelTools.mesh_x, BedLevelTools.mesh_y, false); +} +void BedLevelToolsClass::MoveToZ() { + BedLevelTools.goto_mesh_value = true; + BedLevelTools.manual_move(BedLevelTools.mesh_x, BedLevelTools.mesh_y, true); +} +void BedLevelToolsClass::ProbeXY() { + sprintf_P(cmd, PSTR("G30X%sY%s"), + dtostrf(bedlevel.get_mesh_x(BedLevelTools.mesh_x), 1, 2, str_1), + dtostrf(bedlevel.get_mesh_y(BedLevelTools.mesh_y), 1, 2, str_2) + ); + gcode.process_subcommands_now(cmd); +} + +float BedLevelToolsClass::get_max_value() { + float max = __FLT_MAX__ * -1; + GRID_LOOP(x, y) { + if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] > max) + max = bedlevel.z_values[x][y]; + } + return max; +} + +float BedLevelToolsClass::get_min_value() { + float min = __FLT_MAX__; + GRID_LOOP(x, y) { + if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] < min) + min = bedlevel.z_values[x][y]; + } + return min; +} + +bool BedLevelToolsClass::meshvalidate() { + float min = __FLT_MAX__, max = __FLT_MAX__ * -1; + + GRID_LOOP(x, y) { + if (isnan(bedlevel.z_values[x][y])) return false; + if (bedlevel.z_values[x][y] < min) min = bedlevel.z_values[x][y]; + if (bedlevel.z_values[x][y] > max) max = bedlevel.z_values[x][y]; + } + return WITHIN(max, MESH_Z_OFFSET_MIN, MESH_Z_OFFSET_MAX); +} + +#if USE_UBL_VIEWER + + void BedLevelToolsClass::Draw_Bed_Mesh(int16_t selected /*= -1*/, uint8_t gridline_width /*= 1*/, uint16_t padding_x /*= 8*/, uint16_t padding_y_top /*= 40 + 53 - 7*/) { + drawing_mesh = true; + const uint16_t total_width_px = DWIN_WIDTH - padding_x - padding_x; + const uint16_t cell_width_px = total_width_px / (GRID_MAX_POINTS_X); + const uint16_t cell_height_px = total_width_px / (GRID_MAX_POINTS_Y); + const float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max); + + // Clear background from previous selection and select new square + DWIN_Draw_Rectangle(1, Color_Bg_Black, _MAX(0, padding_x - gridline_width), _MAX(0, padding_y_top - gridline_width), padding_x + total_width_px, padding_y_top + total_width_px); + if (selected >= 0) { + const auto selected_y = selected / (GRID_MAX_POINTS_X); + const auto selected_x = selected - (GRID_MAX_POINTS_X) * selected_y; + const auto start_y_px = padding_y_top + selected_y * cell_height_px; + const auto start_x_px = padding_x + selected_x * cell_width_px; + DWIN_Draw_Rectangle(1, Color_White, _MAX(0, start_x_px - gridline_width), _MAX(0, start_y_px - gridline_width), start_x_px + cell_width_px, start_y_px + cell_height_px); + } + + // Draw value square grid + char buf[8]; + GRID_LOOP(x, y) { + const auto start_x_px = padding_x + x * cell_width_px; + const auto end_x_px = start_x_px + cell_width_px - 1 - gridline_width; + const auto start_y_px = padding_y_top + ((GRID_MAX_POINTS_Y) - y - 1) * cell_height_px; + const auto end_y_px = start_y_px + cell_height_px - 1 - gridline_width; + DWIN_Draw_Rectangle(1, // RGB565 colors: http://www.barth-dev.de/online/rgb565-color-picker/ + isnan(bedlevel.z_values[x][y]) ? Color_Grey : ( // gray if undefined + (bedlevel.z_values[x][y] < 0 ? + (uint16_t)round(0x1F * -bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_min)) << 11 : // red if mesh point value is negative + (uint16_t)round(0x3F * bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_max)) << 5) | // green if mesh point value is positive + _MIN(0x1F, (((uint8_t)abs(bedlevel.z_values[x][y]) / 10) * 4))), // + blue stepping for every mm + start_x_px, start_y_px, end_x_px, end_y_px + ); + + safe_delay(10); + LCD_SERIAL.flushTX(); + + // Draw value text on + if (viewer_print_value) { + int8_t offset_x, offset_y = cell_height_px / 2 - 6; + if (isnan(bedlevel.z_values[x][y])) { // undefined + DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X")); + } + else { // has value + if (GRID_MAX_POINTS_X < 10) + sprintf_P(buf, PSTR("%s"), dtostrf(abs(bedlevel.z_values[x][y]), 1, 2, str_1)); + else + sprintf_P(buf, PSTR("%02i"), (uint16_t)(abs(bedlevel.z_values[x][y] - (int16_t)bedlevel.z_values[x][y]) * 100)); + offset_x = cell_width_px / 2 - 3 * (strlen(buf)) - 2; + if (!(GRID_MAX_POINTS_X < 10)) + DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px - 2 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, F(".")); + DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + 1 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, buf); + } + safe_delay(10); + LCD_SERIAL.flushTX(); + } + } + } + + void BedLevelToolsClass::Set_Mesh_Viewer_Status() { // TODO: draw gradient with values as a legend instead + float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max); + if (v_min > 3e+10F) v_min = 0.0000001; + if (v_max > 3e+10F) v_max = 0.0000001; + if (range > 3e+10F) range = 0.0000001; + char msg[46]; + if (viewer_asymmetric_range) { + dtostrf(-v_min, 1, 3, str_1); + dtostrf( v_max, 1, 3, str_2); + } + else { + dtostrf(-range, 1, 3, str_1); + dtostrf( range, 1, 3, str_2); + } + sprintf_P(msg, PSTR("Red %s..0..%s Green"), str_1, str_2); + ui.set_status(msg); + drawing_mesh = false; + } + +#endif // USE_UBL_VIEWER + +#endif // DWIN_LCD_PROUI && HAS_LEVELING diff --git a/src/lcd/e3v2/proui/bedlevel_tools.h b/src/lcd/e3v2/proui/bedlevel_tools.h new file mode 100644 index 0000000..9373d59 --- /dev/null +++ b/src/lcd/e3v2/proui/bedlevel_tools.h @@ -0,0 +1,77 @@ +/* + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * Bed Level Tools for Pro UI + * Extended by: Miguel A. Risco-Castillo (MRISCOC) + * Version: 2.0.0 + * Date: 2022/05/23 + * + * Based on the original work of: Henri-J-Norden + * https://github.com/Jyers/Marlin/pull/126 + */ + +#pragma once + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(AUTO_BED_LEVELING_UBL) + //#define USE_UBL_VIEWER 1 +#endif + +#define MESH_Z_OFFSET_MIN -3.0 +#define MESH_Z_OFFSET_MAX 3.0 + +class BedLevelToolsClass { +public: + #if USE_UBL_VIEWER + static bool viewer_asymmetric_range; + static bool viewer_print_value; + #endif + static bool goto_mesh_value; + static uint8_t mesh_x; + static uint8_t mesh_y; + static uint8_t tilt_grid; + + #if ENABLED(AUTO_BED_LEVELING_UBL) + static void manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined=false); + static bool create_plane_from_mesh(); + #else + static void manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y); + #endif + static void manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove=false); + static void MoveToXYZ(); + static void MoveToXY(); + static void MoveToZ(); + static void ProbeXY(); + static float get_max_value(); + static float get_min_value(); + static bool meshvalidate(); + #if USE_UBL_VIEWER + static void Draw_Bed_Mesh(int16_t selected = -1, uint8_t gridline_width = 1, uint16_t padding_x = 8, uint16_t padding_y_top = 40 + 53 - 7); + static void Set_Mesh_Viewer_Status(); + #endif +}; + +extern BedLevelToolsClass BedLevelTools; + +void Goto_MeshViewer(); diff --git a/src/lcd/e3v2/proui/dwin.cpp b/src/lcd/e3v2/proui/dwin.cpp new file mode 100644 index 0000000..f51da4c --- /dev/null +++ b/src/lcd/e3v2/proui/dwin.cpp @@ -0,0 +1,3875 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.17.2 + * Date: 2022/04/08 + */ + +#include "../../../inc/MarlinConfig.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#if DISABLED(LIMITED_MAX_FR_EDITING) + #warning "LIMITED_MAX_FR_EDITING is recommended with ProUI." +#endif +#if DISABLED(LIMITED_MAX_ACCEL_EDITING) + #warning "LIMITED_MAX_ACCEL_EDITING is recommended with ProUI." +#endif +#if ENABLED(CLASSIC_JERK) && DISABLED(LIMITED_JERK_EDITING) + #warning "LIMITED_JERK_EDITING is recommended with ProUI." +#endif +#if DISABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) + #warning "INDIVIDUAL_AXIS_HOMING_SUBMENU is recommended with ProUI." +#endif +#if DISABLED(LCD_SET_PROGRESS_MANUALLY) + #warning "LCD_SET_PROGRESS_MANUALLY is recommended with ProUI." +#endif +#if DISABLED(STATUS_MESSAGE_SCROLLING) + #warning "STATUS_MESSAGE_SCROLLING is recommended with ProUI." +#endif +#if DISABLED(BAUD_RATE_GCODE) + #warning "BAUD_RATE_GCODE is recommended with ProUI." +#endif +#if DISABLED(SOUND_MENU_ITEM) + #warning "SOUND_MENU_ITEM is recommended with ProUI." +#endif +#if DISABLED(PRINTCOUNTER) + #warning "PRINTCOUNTER is recommended with ProUI." +#endif +#if HAS_MESH && DISABLED(MESH_EDIT_MENU) + #warning "MESH_EDIT_MENU is recommended with ProUI." +#endif + +#include "dwin.h" +#include "menus.h" +#include "dwin_popup.h" + +#include "../../fontutils.h" +#include "../../marlinui.h" + +#include "../../../sd/cardreader.h" + +#include "../../../MarlinCore.h" +#include "../../../core/serial.h" +#include "../../../core/macros.h" + +#include "../../../module/temperature.h" +#include "../../../module/printcounter.h" +#include "../../../module/motion.h" +#include "../../../module/planner.h" + +#include "../../../gcode/gcode.h" +#include "../../../gcode/queue.h" + +#if HAS_FILAMENT_SENSOR + #include "../../../feature/runout.h" +#endif + +#if ENABLED(EEPROM_SETTINGS) + #include "../../../module/settings.h" +#endif + +#if ENABLED(HOST_ACTION_COMMANDS) + #include "../../../feature/host_actions.h" +#endif + +#if DISABLED(PROBE_MANUALLY) && ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT) + #define HAS_ONESTEP_LEVELING 1 +#endif + +#if HAS_MESH || (HAS_LEVELING && HAS_ZOFFSET_ITEM) + #include "../../../feature/bedlevel/bedlevel.h" + #include "bedlevel_tools.h" +#endif + +#if HAS_BED_PROBE + #include "../../../module/probe.h" +#endif + +#if ENABLED(BLTOUCH) + #include "../../../feature/bltouch.h" +#endif + +#if EITHER(BABYSTEPPING, HAS_BED_PROBE) + #define HAS_ZOFFSET_ITEM 1 + #if ENABLED(BABYSTEPPING) + #include "../../../feature/babystep.h" + #if !HAS_BED_PROBE + #define JUST_BABYSTEP 1 + #endif + #endif +#endif + +#if ENABLED(POWER_LOSS_RECOVERY) + #include "../../../feature/powerloss.h" +#endif + +#if HAS_ESDIAG + #include "endstop_diag.h" +#endif + +#if HAS_PIDPLOT + #include "plot.h" +#endif + +#if HAS_GCODE_PREVIEW + #include "gcode_preview.h" +#endif + +#if HAS_MESH + #include "meshviewer.h" +#endif + +#if ENABLED(PRINTCOUNTER) + #include "printstats.h" +#endif + +#if ENABLED(CASE_LIGHT_MENU) + #include "../../../feature/caselight.h" +#endif + +#if ENABLED(LED_CONTROL_MENU) + #include "../../../feature/leds/leds.h" +#endif + +#if HAS_LOCKSCREEN + #include "lockscreen.h" +#endif + +#ifndef MACHINE_SIZE + #define MACHINE_SIZE STRINGIFY(X_BED_SIZE) "x" STRINGIFY(Y_BED_SIZE) "x" STRINGIFY(Z_MAX_POS) +#endif + +#define PAUSE_HEAT + +#define MENU_CHAR_LIMIT 24 + +// Print speed limit +#define MIN_PRINT_SPEED 10 +#define MAX_PRINT_SPEED 999 + +// Print flow limit +#define MIN_PRINT_FLOW 10 +#define MAX_PRINT_FLOW 299 + +// Load and Unload limits +#define MAX_LOAD_UNLOAD 500 + +// Feedspeed limit (max feedspeed = MAX_FEEDRATE_EDIT_VALUES) +#define MIN_MAXFEEDSPEED 1 +#define MIN_MAXACCELERATION 1 +#define MIN_MAXJERK 0.1 +#define MIN_STEP 1 +#define MAX_STEP 999.9 + +// Editable temperature limits +#define MIN_ETEMP 0 +#define MAX_ETEMP (HEATER_0_MAXTEMP - (HOTEND_OVERSHOOT)) +#define MIN_BEDTEMP 0 +#define MAX_BEDTEMP BED_MAX_TARGET + +#define FEEDRATE_E (60) + +#define DWIN_VAR_UPDATE_INTERVAL 1024 +#define DWIN_SCROLL_UPDATE_INTERVAL SEC_TO_MS(2) +#define DWIN_REMAIN_TIME_UPDATE_INTERVAL SEC_TO_MS(20) + +#if HAS_MESH + #define BABY_Z_VAR TERN(HAS_BED_PROBE, probe.offset.z, HMI_data.ManualZOffset) +#else + float z_offset = 0; + #define BABY_Z_VAR z_offset +#endif + +// Structs +HMI_value_t HMI_value; +HMI_flag_t HMI_flag{0}; +HMI_data_t HMI_data; + +millis_t dwin_heat_time = 0; + +uint8_t checkkey = 255, last_checkkey = MainMenu; + +enum SelectItem : uint8_t { + PAGE_PRINT = 0, + PAGE_PREPARE, + PAGE_CONTROL, + PAGE_ADVANCE, + PAGE_COUNT, + + PRINT_SETUP = 0, + PRINT_PAUSE_RESUME, + PRINT_STOP, + PRINT_COUNT +}; + +typedef struct { + uint8_t now, last; + void set(uint8_t v) { now = last = v; } + void reset() { set(0); } + bool changed() { bool c = (now != last); if (c) last = now; return c; } + bool dec() { if (now) now--; return changed(); } + bool inc(uint8_t v) { if (now < (v - 1)) now++; else now = (v - 1); return changed(); } +} select_t; + +select_t select_page{0}, select_file{0}, select_print{0}; +uint8_t index_file = MROWS; + +bool hash_changed = true; // Flag to know if message status was changed + +constexpr float max_feedrate_edit_values[] = + #ifdef MAX_FEEDRATE_EDIT_VALUES + MAX_FEEDRATE_EDIT_VALUES + #else + { 1000, 1000, 10, 50 } + #endif +; + +constexpr float max_acceleration_edit_values[] = + #ifdef MAX_ACCEL_EDIT_VALUES + MAX_ACCEL_EDIT_VALUES + #else + { 1000, 1000, 200, 2000 } + #endif +; + +#if HAS_CLASSIC_JERK + constexpr float max_jerk_edit_values[] = + #ifdef MAX_JERK_EDIT_VALUES + MAX_JERK_EDIT_VALUES + #else + { DEFAULT_XJERK * 2, DEFAULT_YJERK * 2, DEFAULT_ZJERK * 2, DEFAULT_EJERK * 2 } + #endif + ; +#endif + +static uint8_t _percent_done = 0; +static uint32_t _remain_time = 0; + +// Additional Aux Host Support +static bool sdprint = false; + +#if HAS_HOTEND + float last_E = 0; +#endif + +// New menu system pointers +MenuClass *PrepareMenu = nullptr; +MenuClass *TrammingMenu = nullptr; +MenuClass *MoveMenu = nullptr; +MenuClass *ControlMenu = nullptr; +MenuClass *AdvancedSettings = nullptr; +#if HAS_HOME_OFFSET + MenuClass *HomeOffMenu = nullptr; +#endif +#if HAS_BED_PROBE + MenuClass *ProbeSetMenu = nullptr; +#endif +MenuClass *FilSetMenu = nullptr; +MenuClass *SelectColorMenu = nullptr; +MenuClass *GetColorMenu = nullptr; +MenuClass *TuneMenu = nullptr; +MenuClass *MotionMenu = nullptr; +MenuClass *FilamentMenu = nullptr; +#if ENABLED(MESH_BED_LEVELING) + MenuClass *ManualMesh = nullptr; +#endif +#if HAS_HOTEND + MenuClass *PreheatMenu = nullptr; +#endif +MenuClass *TemperatureMenu = nullptr; +MenuClass *MaxSpeedMenu = nullptr; +MenuClass *MaxAccelMenu = nullptr; +#if HAS_CLASSIC_JERK + MenuClass *MaxJerkMenu = nullptr; +#endif +MenuClass *StepsMenu = nullptr; +MenuClass *HotendPIDMenu = nullptr; +MenuClass *BedPIDMenu = nullptr; +#if ENABLED(CASELIGHT_USES_BRIGHTNESS) + MenuClass *CaseLightMenu = nullptr; +#endif +#if ENABLED(LED_CONTROL_MENU) + MenuClass *LedControlMenu = nullptr; +#endif +#if HAS_BED_PROBE + MenuClass *ZOffsetWizMenu = nullptr; +#endif +#if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) + MenuClass *HomingMenu = nullptr; +#endif +#if ENABLED(FWRETRACT) + MenuClass *FWRetractMenu = nullptr; +#endif +#if HAS_MESH + MenuClass *MeshMenu = nullptr; + #if ENABLED(MESH_EDIT_MENU) + MenuClass *EditMeshMenu = nullptr; + #endif +#endif + +// Updatable menuitems pointers +MenuItemClass *HotendTargetItem = nullptr; +MenuItemClass *BedTargetItem = nullptr; +MenuItemClass *FanSpeedItem = nullptr; +MenuItemClass *MMeshMoveZItem = nullptr; +MenuItemClass *EditZValueItem = nullptr; + +#define DWIN_LANGUAGE_EEPROM_ADDRESS 0x01 // Between 0x01 and 0x63 (EEPROM_OFFSET-1) + // BL24CXX::check() uses 0x00 + +inline bool HMI_IsChinese() { return HMI_flag.language == DWIN_CHINESE; } + +void HMI_SetLanguageCache() { + DWIN_JPG_CacheTo1(HMI_IsChinese() ? Language_Chinese : Language_English); +} + +void HMI_SetLanguage() { + #if BOTH(EEPROM_SETTINGS, IIC_BL24CXX_EEPROM) + BL24CXX::read(DWIN_LANGUAGE_EEPROM_ADDRESS, (uint8_t*)&HMI_flag.language, sizeof(HMI_flag.language)); + #endif + HMI_SetLanguageCache(); +} + +void HMI_ToggleLanguage() { + HMI_flag.language = HMI_IsChinese() ? DWIN_ENGLISH : DWIN_CHINESE; + HMI_SetLanguageCache(); + #if BOTH(EEPROM_SETTINGS, IIC_BL24CXX_EEPROM) + BL24CXX::write(DWIN_LANGUAGE_EEPROM_ADDRESS, (uint8_t*)&HMI_flag.language, sizeof(HMI_flag.language)); + #endif +} + +//----------------------------------------------------------------------------- +// Main Buttons +//----------------------------------------------------------------------------- + +typedef struct { uint16_t x, y[2], w, h; } text_info_t; + +void ICON_Button(const bool selected, const int iconid, const frame_rect_t &ico, const text_info_t (&txt), FSTR_P caption) { + DWIN_ICON_Show(true, false, false, ICON, iconid + selected, ico.x, ico.y); + if (selected) DWINUI::Draw_Box(0, HMI_data.Highlight_Color, ico); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, txt.x, txt.y[selected], txt.x + txt.w - 1, txt.y[selected] + txt.h - 1, ico.x + (ico.w - txt.w) / 2, (ico.y + ico.h - 25) - txt.h/2); + } + else { + const uint16_t x = ico.x + (ico.w - strlen_P(FTOP(caption)) * DWINUI::fontWidth()) / 2, + y = (ico.y + ico.h - 20) - DWINUI::fontHeight() / 2; + DWINUI::Draw_String(x, y, caption); + } +} + +// +// Main Menu: "Print" +// +void ICON_Print() { + constexpr frame_rect_t ico = { 17, 110, 110, 100 }; + constexpr text_info_t txt = { 1, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_page.now == PAGE_PRINT, ICON_Print_0, ico, txt, GET_TEXT_F(MSG_BUTTON_PRINT)); +} + +// +// Main Menu: "Prepare" +// +void ICON_Prepare() { + constexpr frame_rect_t ico = { 145, 110, 110, 100 }; + constexpr text_info_t txt = { 31, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_page.now == PAGE_PREPARE, ICON_Prepare_0, ico, txt, GET_TEXT_F(MSG_PREPARE)); +} + +// +// Main Menu: "Control" +// +void ICON_Control() { + constexpr frame_rect_t ico = { 17, 226, 110, 100 }; + constexpr text_info_t txt = { 61, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_page.now == PAGE_CONTROL, ICON_Control_0, ico, txt, GET_TEXT_F(MSG_CONTROL)); +} + +// +// Main Menu: "Advanced Settings" +// +void ICON_AdvSettings() { + constexpr frame_rect_t ico = { 145, 226, 110, 100 }; + constexpr text_info_t txt = { 91, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_page.now == PAGE_ADVANCE, ICON_Info_0, ico, txt, GET_TEXT_F(MSG_BUTTON_ADVANCED)); +} + +// +// Printing: "Tune" +// +void ICON_Tune() { + constexpr frame_rect_t ico = { 8, 232, 80, 100 }; + constexpr text_info_t txt = { 121, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_print.now == PRINT_SETUP, ICON_Setup_0, ico, txt, GET_TEXT_F(MSG_TUNE)); +} + +// +// Printing: "Pause" +// +void ICON_Pause() { + constexpr frame_rect_t ico = { 96, 232, 80, 100 }; + constexpr text_info_t txt = { 181, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_print.now == PRINT_PAUSE_RESUME, ICON_Pause_0, ico, txt, GET_TEXT_F(MSG_BUTTON_PAUSE)); +} + +// +// Printing: "Resume" +// +void ICON_Resume() { + constexpr frame_rect_t ico = { 96, 232, 80, 100 }; + constexpr text_info_t txt = { 1, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; + ICON_Button(select_print.now == PRINT_PAUSE_RESUME, ICON_Continue_0, ico, txt, GET_TEXT_F(MSG_BUTTON_RESUME)); +} + +// +// Printing: "Stop" +// +void ICON_Stop() { + constexpr frame_rect_t ico = { 184, 232, 80, 100 }; + constexpr text_info_t txt = { 151, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 12 }; + ICON_Button(select_print.now == PRINT_STOP, ICON_Stop_0, ico, txt, GET_TEXT_F(MSG_BUTTON_STOP)); +} + +//----------------------------------------------------------------------------- +// Drawing routines +//----------------------------------------------------------------------------- + +void Move_Highlight(const int8_t from, const int8_t newline) { + Erase_Menu_Cursor(newline - from); + Draw_Menu_Cursor(newline); +} + +void Add_Menu_Line() { + Move_Highlight(1, MROWS); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(MROWS + 1), 240); +} + +void Scroll_Menu(const uint8_t dir) { + DWIN_Frame_AreaMove(1, dir, MLINE, HMI_data.Background_Color, 0, 31, DWIN_WIDTH, 349); + switch (dir) { + case DWIN_SCROLL_DOWN: Move_Highlight(-1, 0); break; + case DWIN_SCROLL_UP: Add_Menu_Line(); break; + } +} + +inline uint16_t nr_sd_menu_items() { + return card.get_num_Files() + !card.flag.workDirIsRoot; +} + +void Erase_Menu_Text(const uint8_t line) { + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, LBLX, MBASE(line) - 14, 271, MBASE(line) + 28); +} + +// Draw "Back" line at the top +void Draw_Back_First(const bool is_sel=true) { + Draw_Menu_Line(0, ICON_Back); + if (HMI_IsChinese()) + DWIN_Frame_AreaCopy(1, 129, 72, 156, 84, LBLX, MBASE(0)); + else + DWINUI::Draw_String(LBLX, MBASE(0), GET_TEXT_F(MSG_BACK)); + if (is_sel) Draw_Menu_Cursor(0); +} + +//PopUps +void Popup_window_PauseOrStop() { + if (HMI_IsChinese()) { + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + if (select_print.now == PRINT_PAUSE_RESUME) DWIN_Frame_AreaCopy(1, 237, 338, 269, 356, 98, 150); + else if (select_print.now == PRINT_STOP) DWIN_Frame_AreaCopy(1, 221, 320, 253, 336, 98, 150); + DWIN_Frame_AreaCopy(1, 220, 304, 264, 319, 130, 150); + DWINUI::Draw_IconWB(ICON_Confirm_C, 26, 280); + DWINUI::Draw_IconWB(ICON_Cancel_C, 146, 280); + Draw_Select_Highlight(true); + DWIN_UpdateLCD(); + } + else + DWIN_Popup_ConfirmCancel(ICON_BLTouch, select_print.now == PRINT_PAUSE_RESUME ? GET_TEXT_F(MSG_PAUSE_PRINT) : GET_TEXT_F(MSG_STOP_PRINT)); +} + +#if HAS_HOTEND + + void Popup_Window_ETempTooLow() { + if (HMI_IsChinese()) { + HMI_SaveProcessID(WaitResponse); + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + DWINUI::Draw_Icon(ICON_TempTooLow, 102, 105); + DWIN_Frame_AreaCopy(1, 103, 371, 136, 386, 69, 240); + DWIN_Frame_AreaCopy(1, 170, 371, 270, 386, 102, 240); + DWINUI::Draw_IconWB(ICON_Confirm_C, 86, 280); + DWIN_UpdateLCD(); + } + else + DWIN_Popup_Confirm(ICON_TempTooLow, GET_TEXT_F(MSG_HOTEND_TOO_COLD), GET_TEXT_F(MSG_PLEASE_PREHEAT)); + } + +#endif + +#if HAS_HOTEND || HAS_HEATED_BED + void DWIN_Popup_Temperature(const bool toohigh) { + HMI_SaveProcessID(WaitResponse); + if (HMI_IsChinese()) { + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + if (toohigh) { + DWINUI::Draw_Icon(ICON_TempTooHigh, 102, 165); + DWIN_Frame_AreaCopy(1, 103, 371, 237, 386, 52, 285); + DWIN_Frame_AreaCopy(1, 151, 389, 185, 402, 187, 285); + DWIN_Frame_AreaCopy(1, 189, 389, 271, 402, 95, 310); + } + else { + DWINUI::Draw_Icon(ICON_TempTooLow, 102, 165); + DWIN_Frame_AreaCopy(1, 103, 371, 270, 386, 52, 285); + DWIN_Frame_AreaCopy(1, 189, 389, 271, 402, 95, 310); + } + } + else DWIN_Show_Popup(toohigh ? ICON_TempTooHigh : ICON_TempTooLow, F("Nozzle or Bed temperature"), toohigh ? F("is too high") : F("is too low"), BTN_Continue); + } +#endif + +// Draw status line +void DWIN_DrawStatusLine() { + DWIN_Draw_Rectangle(1, HMI_data.StatusBg_Color, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20); + DWINUI::Draw_CenteredString(HMI_data.StatusTxt_Color, STATUS_Y + 2, ui.status_message); +} + +// Clear & reset status line +void DWIN_ResetStatusLine() { + ui.status_message[0] = 0; + DWIN_CheckStatusMessage(); +} + +// Djb2 hash algorithm +void DWIN_CheckStatusMessage() { + static uint32_t old_hash = 0; + char * str = &ui.status_message[0]; + uint32_t hash = 5381; + char c; + while ((c = *str++)) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + hash_changed = hash != old_hash; + old_hash = hash; +}; + +void DWIN_DrawStatusMessage() { + #if ENABLED(STATUS_MESSAGE_SCROLLING) + + // Get the UTF8 character count of the string + uint8_t slen = utf8_strlen(ui.status_message); + + // If the string fits the status line do not scroll it + if (slen <= LCD_WIDTH) { + if (hash_changed) { + DWIN_DrawStatusLine(); + hash_changed = false; + } + } + else { + // String is larger than the available line space + + // Get a pointer to the next valid UTF8 character + // and the string remaining length + uint8_t rlen; + const char *stat = MarlinUI::status_and_len(rlen); + DWIN_Draw_Rectangle(1, HMI_data.StatusBg_Color, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20); + DWINUI::MoveTo(0, STATUS_Y + 2); + DWINUI::Draw_String(HMI_data.StatusTxt_Color, stat, LCD_WIDTH); + + // If the string doesn't completely fill the line... + if (rlen < LCD_WIDTH) { + DWINUI::Draw_Char(HMI_data.StatusTxt_Color, '.'); // Always at 1+ spaces left, draw a dot + uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters + if (--chars) { // Draw a second dot if there's space + DWINUI::Draw_Char(HMI_data.StatusTxt_Color, '.'); + if (--chars) + DWINUI::Draw_String(HMI_data.StatusTxt_Color, ui.status_message, chars); // Print a second copy of the message + } + } + MarlinUI::advance_status_scroll(); + } + + #else + + if (hash_changed) { + ui.status_message[LCD_WIDTH] = 0; + DWIN_DrawStatusLine(); + hash_changed = false; + } + + #endif +} + +void Draw_Print_Labels() { + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 0, 72, 63, 86, 41, 173); // Printing Time + DWIN_Frame_AreaCopy(1, 65, 72, 128, 86, 176, 173); // Remain + } + else { + DWINUI::Draw_String( 46, 173, GET_TEXT_F(MSG_INFO_PRINT_TIME)); + DWINUI::Draw_String(181, 173, GET_TEXT_F(MSG_REMAINING_TIME)); + } +} + +void Draw_Print_ProgressBar() { + DWIN_ICON_Show(true, false, false, ICON, ICON_Bar, 15, 93); + DWIN_Draw_Rectangle(1, HMI_data.Barfill_Color, 16 + _percent_done * 240 / 100, 93, 256, 113); + DWINUI::Draw_Int(HMI_data.PercentTxt_Color, HMI_data.Background_Color, 3, 117, 133, _percent_done); + DWINUI::Draw_String(HMI_data.PercentTxt_Color, 142, 133, F("%")); +} + +void Draw_Print_ProgressElapsed() { + char buf[10]; + duration_t elapsed = print_job_timer.duration(); // print timer + sprintf_P(buf, PSTR("%02i:%02i "), (uint16_t)(elapsed.value / 3600), ((uint16_t)elapsed.value % 3600) / 60); + DWINUI::Draw_String(HMI_data.Text_Color, HMI_data.Background_Color, 47, 192, buf); +} + +void Draw_Print_ProgressRemain() { + char buf[10]; + sprintf_P(buf, PSTR("%02i:%02i "), (uint16_t)(_remain_time / 3600), ((uint16_t)_remain_time % 3600) / 60); + DWINUI::Draw_String(HMI_data.Text_Color, HMI_data.Background_Color, 181, 192, buf); +} + +void ICON_ResumeOrPause() { + if (checkkey == PrintProcess) printingIsPaused() ? ICON_Resume() : ICON_Pause(); +} + +// Update filename on print +void DWIN_Print_Header(const char *text=nullptr) { + static char headertxt[31] = ""; // Print header text + if (text) { + const int8_t size = _MIN(30U, strlen_P(text)); + LOOP_L_N(i, size) headertxt[i] = text[i]; + headertxt[size] = '\0'; + } + if (checkkey == PrintProcess || checkkey == PrintDone) { + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, 60, DWIN_WIDTH, 60+16); + DWINUI::Draw_CenteredString(60, headertxt); + } +} + +void Draw_PrintProcess() { + if (HMI_IsChinese()) + Title.FrameCopy(30, 1, 42, 14); // "Printing" + else + Title.ShowCaption(GET_TEXT_F(MSG_PRINTING)); + DWINUI::ClearMainArea(); + DWIN_Print_Header(sdprint ? card.longest_filename() : nullptr); + Draw_Print_Labels(); + DWINUI::Draw_Icon(ICON_PrintTime, 15, 173); + DWINUI::Draw_Icon(ICON_RemainTime, 150, 171); + Draw_Print_ProgressBar(); + Draw_Print_ProgressElapsed(); + Draw_Print_ProgressRemain(); + ICON_Tune(); + ICON_ResumeOrPause(); + ICON_Stop(); +} + +void Goto_PrintProcess() { + if (checkkey == PrintProcess) + ICON_ResumeOrPause(); + else { + checkkey = PrintProcess; + Draw_PrintProcess(); + TERN_(DASH_REDRAW, DWIN_RedrawDash()); + } + DWIN_UpdateLCD(); +} + +void Draw_PrintDone() { + // show percent bar and value + _percent_done = 100; + _remain_time = 0; + + Title.ShowCaption(GET_TEXT_F(MSG_PRINT_DONE)); + DWINUI::ClearMainArea(); + DWIN_Print_Header(nullptr); + if (sdprint && TERN0(HAS_GCODE_PREVIEW, Preview_Valid())) { + DWIN_ICON_Show(0, 0, 1, 21, 100, 0x00); + DWINUI::Draw_Button(BTN_Continue, 86, 300); + } + else { + Draw_Print_ProgressBar(); + Draw_Print_Labels(); + DWINUI::Draw_Icon(ICON_PrintTime, 15, 173); + DWINUI::Draw_Icon(ICON_RemainTime, 150, 171); + Draw_Print_ProgressElapsed(); + Draw_Print_ProgressRemain(); + DWINUI::Draw_Button(BTN_Continue, 86, 273); + } +} + +void Goto_PrintDone() { + wait_for_user = true; + if (checkkey != PrintDone) { + checkkey = PrintDone; + Draw_PrintDone(); + DWIN_UpdateLCD(); + } +} + +void Draw_Main_Menu() { + DWINUI::ClearMainArea(); + if (HMI_IsChinese()) + Title.FrameCopy(2, 2, 26, 13); // "Home" etc + else + Title.ShowCaption(MACHINE_NAME); + DWINUI::Draw_Icon(ICON_LOGO, 71, 52); // CREALITY logo + DWIN_ResetStatusLine(); + ICON_Print(); + ICON_Prepare(); + ICON_Control(); + ICON_AdvSettings(); +} + +void Goto_Main_Menu() { + if (checkkey == MainMenu) return; + checkkey = MainMenu; + Draw_Main_Menu(); + DWIN_UpdateLCD(); +} + +// Draw X, Y, Z and blink if in an un-homed or un-trusted state +void _update_axis_value(const AxisEnum axis, const uint16_t x, const uint16_t y, const bool blink, const bool force) { + const bool draw_qmark = axis_should_home(axis), + draw_empty = NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !draw_qmark && !axis_is_trusted(axis); + + // Check for a position change + static xyz_pos_t oldpos = { -1, -1, -1 }; + const float p = current_position[axis]; + const bool changed = oldpos[axis] != p; + if (changed) oldpos[axis] = p; + + if (force || changed || draw_qmark || draw_empty) { + if (blink && draw_qmark) + DWINUI::Draw_String(HMI_data.Coordinate_Color, HMI_data.Background_Color, x, y, F(" - ? -")); + else if (blink && draw_empty) + DWINUI::Draw_String(HMI_data.Coordinate_Color, HMI_data.Background_Color, x, y, F(" ")); + else + DWINUI::Draw_Signed_Float(HMI_data.Coordinate_Color, HMI_data.Background_Color, 3, 2, x, y, p); + } +} + +void _draw_xyz_position(const bool force) { + //SERIAL_ECHOPGM("Draw XYZ:"); + static bool _blink = false; + const bool blink = !!(millis() & 0x400UL); + if (force || blink != _blink) { + _blink = blink; + //SERIAL_ECHOPGM(" (blink)"); + _update_axis_value(X_AXIS, 27, 459, blink, true); + _update_axis_value(Y_AXIS, 112, 459, blink, true); + _update_axis_value(Z_AXIS, 197, 459, blink, true); + } + //SERIAL_EOL(); +} + +void update_variable() { + #if HAS_HOTEND + static celsius_t _hotendtemp = 0, _hotendtarget = 0; + const celsius_t hc = thermalManager.wholeDegHotend(0), + ht = thermalManager.degTargetHotend(0); + const bool _new_hotend_temp = _hotendtemp != hc, + _new_hotend_target = _hotendtarget != ht; + if (_new_hotend_temp) _hotendtemp = hc; + if (_new_hotend_target) _hotendtarget = ht; + #endif + #if HAS_HEATED_BED + static celsius_t _bedtemp = 0, _bedtarget = 0; + const celsius_t bc = thermalManager.wholeDegBed(), + bt = thermalManager.degTargetBed(); + const bool _new_bed_temp = _bedtemp != bc, + _new_bed_target = _bedtarget != bt; + if (_new_bed_temp) _bedtemp = bc; + if (_new_bed_target) _bedtarget = bt; + #endif + #if HAS_FAN + static uint8_t _fanspeed = 0; + const bool _new_fanspeed = _fanspeed != thermalManager.fan_speed[0]; + if (_new_fanspeed) _fanspeed = thermalManager.fan_speed[0]; + #endif + + if (checkkey == Menu && (CurrentMenu == TuneMenu || CurrentMenu == TemperatureMenu)) { + // Tune page temperature update + #if HAS_HOTEND + if (_new_hotend_target) HotendTargetItem->redraw(); + #endif + #if HAS_HEATED_BED + if (_new_bed_target) BedTargetItem->redraw(); + #endif + #if HAS_FAN + if (_new_fanspeed) FanSpeedItem->redraw(); + #endif + } + + // Bottom temperature update + + #if HAS_HOTEND + if (_new_hotend_temp) + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 28, 384, _hotendtemp); + if (_new_hotend_target) + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 25 + 4 * STAT_CHR_W + 6, 384, _hotendtarget); + + static int16_t _flow = planner.flow_percentage[0]; + if (_flow != planner.flow_percentage[0]) { + _flow = planner.flow_percentage[0]; + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 116 + 2 * STAT_CHR_W, 417, _flow); + } + #endif + + #if HAS_HEATED_BED + if (_new_bed_temp) + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 28, 417, _bedtemp); + if (_new_bed_target) + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 25 + 4 * STAT_CHR_W + 6, 417, _bedtarget); + #endif + + static int16_t _feedrate = 100; + if (_feedrate != feedrate_percentage) { + _feedrate = feedrate_percentage; + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 116 + 2 * STAT_CHR_W, 384, _feedrate); + } + + #if HAS_FAN + if (_new_fanspeed) { + _fanspeed = thermalManager.fan_speed[0]; + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 195 + 2 * STAT_CHR_W, 384, _fanspeed); + } + #endif + + static float _offset = 0; + if (BABY_Z_VAR != _offset) { + _offset = BABY_Z_VAR; + DWINUI::Draw_Signed_Float(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 2, 2, 204, 417, _offset); + } + + #if HAS_MESH + static bool _leveling_active = false; + if (_leveling_active != planner.leveling_active) { + _leveling_active = planner.leveling_active; + DWIN_Draw_Box(1, HMI_data.Background_Color, 186, 416, 20, 20); + if (_leveling_active) + DWINUI::Draw_Icon(ICON_SetZOffset, 186, 416); + else + DWINUI::Draw_Icon(ICON_Zoffset, 187, 416); + } + #else + DWINUI::Draw_Icon(ICON_Zoffset, 187, 416); + #endif + + _draw_xyz_position(false); +} + +/** + * Read and cache the working directory. + * + * TODO: New code can follow the pattern of menu_media.cpp + * and rely on Marlin caching for performance. No need to + * cache files here. + */ + +#ifndef strcasecmp_P + #define strcasecmp_P(a, b) strcasecmp((a), (b)) +#endif + +void make_name_without_ext(char *dst, char *src, size_t maxlen=MENU_CHAR_LIMIT) { + size_t pos = strlen(src); // index of ending nul + + // For files, remove the extension + // which may be .gcode, .gco, or .g + if (!card.flag.filenameIsDir) + while (pos && src[pos] != '.') pos--; // find last '.' (stop at 0) + + if (!pos) pos = strlen(src); // pos = 0 ('.' not found) restore pos + + size_t len = pos; // nul or '.' + if (len > maxlen) { // Keep the name short + pos = len = maxlen; // move nul down + dst[--pos] = '.'; // insert dots + dst[--pos] = '.'; + dst[--pos] = '.'; + } + + dst[len] = '\0'; // end it + + // Copy down to 0 + while (pos--) dst[pos] = src[pos]; +} + +void HMI_SDCardInit() { card.cdroot(); } + +#if ENABLED(SCROLL_LONG_FILENAMES) + + char shift_name[LONG_FILENAME_LENGTH + 1]; + int8_t shift_amt; // = 0 + millis_t shift_ms; // = 0 + + // Init the shift name based on the highlighted item + void Init_Shift_Name() { + const bool is_subdir = !card.flag.workDirIsRoot; + const int8_t filenum = select_file.now - 1 - is_subdir; // Skip "Back" and ".." + const uint16_t fileCnt = card.get_num_Files(); + if (WITHIN(filenum, 0, fileCnt - 1)) { + card.getfilename_sorted(SD_ORDER(filenum, fileCnt)); + char * const name = card.longest_filename(); + make_name_without_ext(shift_name, name, 100); + } + } + + void Init_SDItem_Shift() { + shift_amt = 0; + shift_ms = select_file.now > 0 && strlen(shift_name) > MENU_CHAR_LIMIT ? millis() + 750UL : 0; + } + +#endif + +/** + * Display an SD item, adding a CDUP for subfolders. + */ +void Draw_SDItem(const uint16_t item, int16_t row=-1) { + if (row < 0) row = item + 1 + MROWS - index_file; + const bool is_subdir = !card.flag.workDirIsRoot; + if (is_subdir && item == 0) + return Draw_Menu_Line(row, ICON_Folder, ".."); + + card.getfilename_sorted(SD_ORDER(item - is_subdir, card.get_num_Files())); + char * const name = card.longest_filename(); + + #if ENABLED(SCROLL_LONG_FILENAMES) + // Init the current selected name + // This is used during scroll drawing + if (item == select_file.now - 1) { + make_name_without_ext(shift_name, name, 100); + Init_SDItem_Shift(); + } + #endif + + // Draw the file/folder with name aligned left + char str[strlen(name) + 1]; + make_name_without_ext(str, name); + const uint8_t icon = card.flag.filenameIsDir ? ICON_Folder : card.fileIsBinary() ? ICON_Binary : ICON_File; + Draw_Menu_Line(row, icon, str); +} + +#if ENABLED(SCROLL_LONG_FILENAMES) + + void Draw_SDItem_Shifted(uint8_t &shift) { + // Limit to the number of chars past the cutoff + const size_t len = strlen(shift_name); + NOMORE(shift, _MAX(len - MENU_CHAR_LIMIT, 0U)); + + // Shorten to the available space + const size_t lastchar = _MIN((signed)len, shift + MENU_CHAR_LIMIT); + + const char c = shift_name[lastchar]; + shift_name[lastchar] = '\0'; + + const uint8_t row = select_file.now + MROWS - index_file; // skip "Back" and scroll + Erase_Menu_Text(row); + Draw_Menu_Line(row, 0, &shift_name[shift]); + + shift_name[lastchar] = c; + } + +#endif + +// Redraw the first set of SD Files +void Redraw_SD_List() { + select_file.reset(); + index_file = MROWS; + + DWINUI::ClearMainArea(); // Leave title bar unchanged + + Draw_Back_First(); + + if (card.isMounted()) { + // As many files as will fit + LOOP_L_N(i, _MIN(nr_sd_menu_items(), MROWS)) + Draw_SDItem(i, i + 1); + + TERN_(SCROLL_LONG_FILENAMES, Init_SDItem_Shift()); + } + else { + DWIN_Draw_Rectangle(1, HMI_data.AlertBg_Color, 10, MBASE(3) - 10, DWIN_WIDTH - 10, MBASE(4)); + DWINUI::Draw_CenteredString(font12x24, HMI_data.AlertTxt_Color, MBASE(3), GET_TEXT_F(MSG_MEDIA_NOT_INSERTED)); + } +} + +bool DWIN_lcd_sd_status = false; + +void SDCard_Up() { + card.cdup(); + Redraw_SD_List(); + DWIN_lcd_sd_status = false; // On next DWIN_Update +} + +void SDCard_Folder(char * const dirname) { + card.cd(dirname); + Redraw_SD_List(); + DWIN_lcd_sd_status = false; // On next DWIN_Update +} + +// +// Watch for media mount / unmount +// +void HMI_SDCardUpdate() { + if (HMI_flag.home_flag) return; + if (DWIN_lcd_sd_status != card.isMounted()) { + DWIN_lcd_sd_status = card.isMounted(); + //SERIAL_ECHOLNPGM("HMI_SDCardUpdate: ", DWIN_lcd_sd_status); + if (DWIN_lcd_sd_status) { // Media inserted + if (checkkey == SelectFile) + Redraw_SD_List(); + } + else { // Media removed + // clean file icon + if (checkkey == SelectFile) { + Redraw_SD_List(); + } + else if (sdprint && card.isPrinting() && printingIsActive()) { + wait_for_heatup = wait_for_user = false; + HMI_flag.abort_flag = true; // Abort print + } + } + DWIN_UpdateLCD(); + } +} + +// +// The Dashboard is always on-screen, except during +// full-screen modal dialogs. +// +void DWIN_Draw_Dashboard() { + + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, STATUS_Y + 21, DWIN_WIDTH, DWIN_HEIGHT - 1); + + #if HAS_HOTEND + DWINUI::Draw_Icon(ICON_HotendTemp, 10, 383); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 28, 384, thermalManager.wholeDegHotend(0)); + DWINUI::Draw_String(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 25 + 3 * STAT_CHR_W + 5, 384, F("/")); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 25 + 4 * STAT_CHR_W + 6, 384, thermalManager.degTargetHotend(0)); + + DWINUI::Draw_Icon(ICON_StepE, 112, 417); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 116 + 2 * STAT_CHR_W, 417, planner.flow_percentage[0]); + DWINUI::Draw_String(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 116 + 5 * STAT_CHR_W + 2, 417, F("%")); + #endif + + #if HAS_HEATED_BED + DWINUI::Draw_Icon(ICON_BedTemp, 10, 416); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 28, 417, thermalManager.wholeDegBed()); + DWINUI::Draw_String(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 25 + 3 * STAT_CHR_W + 5, 417, F("/")); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 25 + 4 * STAT_CHR_W + 6, 417, thermalManager.degTargetBed()); + #endif + + DWINUI::Draw_Icon(ICON_Speed, 113, 383); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 116 + 2 * STAT_CHR_W, 384, feedrate_percentage); + DWINUI::Draw_String(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 116 + 5 * STAT_CHR_W + 2, 384, F("%")); + + #if HAS_FAN + DWINUI::Draw_Icon(ICON_FanSpeed, 187, 383); + DWINUI::Draw_Int(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 3, 195 + 2 * STAT_CHR_W, 384, thermalManager.fan_speed[0]); + #endif + + #if HAS_ZOFFSET_ITEM + DWINUI::Draw_Icon(planner.leveling_active ? ICON_SetZOffset : ICON_Zoffset, 187, 416); + #endif + + DWINUI::Draw_Signed_Float(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 2, 2, 204, 417, BABY_Z_VAR); + + DWIN_Draw_Rectangle(1, HMI_data.SplitLine_Color, 0, 449, DWIN_WIDTH, 451); + + DWINUI::Draw_Icon(ICON_MaxSpeedX, 10, 456); + DWINUI::Draw_Icon(ICON_MaxSpeedY, 95, 456); + DWINUI::Draw_Icon(ICON_MaxSpeedZ, 180, 456); + _draw_xyz_position(true); + +} + +void Draw_Info_Menu() { + DWINUI::ClearMainArea(); + Draw_Back_First(); + if (HMI_IsChinese()) + Title.FrameCopy(30, 17, 28, 13); // "Info" + else + Title.ShowCaption(GET_TEXT_F(MSG_INFO_SCREEN)); + + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 197, 149, 252, 161, 108, 102); // "Size" + DWIN_Frame_AreaCopy(1, 1, 164, 56, 176, 108, 175); // "Firmware Version" + DWIN_Frame_AreaCopy(1, 58, 164, 113, 176, 105, 248); // "Contact Details" + DWINUI::Draw_CenteredString(268, F(CORP_WEBSITE)); + } + else { + DWINUI::Draw_CenteredString(102, F("Size")); + DWINUI::Draw_CenteredString(175, F("Firmware version")); + DWINUI::Draw_CenteredString(248, F("Build Datetime")); + DWINUI::Draw_CenteredString(268, F(STRING_DISTRIBUTION_DATE)); + } + DWINUI::Draw_CenteredString(122, F(MACHINE_SIZE)); + DWINUI::Draw_CenteredString(195, F(SHORT_BUILD_VERSION)); + + LOOP_L_N(i, 3) { + DWINUI::Draw_Icon(ICON_PrintSize + i, ICOX, 99 + i * 73); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MBASE(2) + i * 73, 240); + } +} + +void Draw_Print_File_Menu() { + if (HMI_IsChinese()) + Title.FrameCopy(0, 31, 56, 14); // "Print file" + else + Title.ShowCaption(GET_TEXT_F(MSG_MEDIA_MENU)); + Redraw_SD_List(); + TERN_(DASH_REDRAW, DWIN_RedrawDash()); +} + +// Main Process +void HMI_MainMenu() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_page.inc(PAGE_COUNT)) { + switch (select_page.now) { + case PAGE_PRINT: ICON_Print(); break; + case PAGE_PREPARE: ICON_Print(); ICON_Prepare(); break; + case PAGE_CONTROL: ICON_Prepare(); ICON_Control(); break; + case PAGE_ADVANCE: ICON_Control(); ICON_AdvSettings(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_page.dec()) { + switch (select_page.now) { + case PAGE_PRINT: ICON_Print(); ICON_Prepare(); break; + case PAGE_PREPARE: ICON_Prepare(); ICON_Control(); break; + case PAGE_CONTROL: ICON_Control(); ICON_AdvSettings(); break; + case PAGE_ADVANCE: ICON_AdvSettings(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_page.now) { + case PAGE_PRINT: + checkkey = SelectFile; + card.mount(); + safe_delay(300); + Draw_Print_File_Menu(); + break; + case PAGE_PREPARE: Draw_Prepare_Menu(); break; + case PAGE_CONTROL: Draw_Control_Menu(); break; + case PAGE_ADVANCE: Draw_AdvancedSettings_Menu(); break; + } + } + DWIN_UpdateLCD(); +} + +// Select (and Print) File +void HMI_SelectFile() { + EncoderState encoder_diffState = get_encoder_state(); + + const uint16_t hasUpDir = !card.flag.workDirIsRoot; + + if (encoder_diffState == ENCODER_DIFF_NO) { + #if ENABLED(SCROLL_LONG_FILENAMES) + if (shift_ms && select_file.now >= 1 + hasUpDir) { + // Scroll selected filename every second + const millis_t ms = millis(); + if (ELAPSED(ms, shift_ms)) { + const bool was_reset = shift_amt < 0; + shift_ms = ms + 375UL + was_reset * 250UL; // ms per character + uint8_t shift_new = shift_amt + 1; // Try to shift by... + Draw_SDItem_Shifted(shift_new); // Draw the item + if (!was_reset && shift_new == 0) // Was it limited to 0? + shift_ms = 0; // No scrolling needed + else if (shift_new == shift_amt) // Scroll reached the end + shift_new = -1; // Reset + shift_amt = shift_new; // Set new scroll + } + } + #endif + return; + } + + // First pause is long. Easy. + // On reset, long pause must be after 0. + + const uint16_t fullCnt = nr_sd_menu_items(); + + if (encoder_diffState == ENCODER_DIFF_CW && fullCnt) { + if (select_file.inc(1 + fullCnt)) { + const uint8_t itemnum = select_file.now - 1; // -1 for "Back" + if (TERN0(SCROLL_LONG_FILENAMES, shift_ms)) { // If line was shifted + Erase_Menu_Text(itemnum + MROWS - index_file); // Erase and + Draw_SDItem(itemnum - 1); // redraw + } + if (select_file.now > MROWS && select_file.now > index_file) { // Cursor past the bottom + index_file = select_file.now; // New bottom line + Scroll_Menu(DWIN_SCROLL_UP); + Draw_SDItem(itemnum, MROWS); // Draw and init the shift name + } + else { + Move_Highlight(1, select_file.now + MROWS - index_file); // Just move highlight + TERN_(SCROLL_LONG_FILENAMES, Init_Shift_Name()); // ...and init the shift name + } + TERN_(SCROLL_LONG_FILENAMES, Init_SDItem_Shift()); + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW && fullCnt) { + if (select_file.dec()) { + const uint8_t itemnum = select_file.now - 1; // -1 for "Back" + if (TERN0(SCROLL_LONG_FILENAMES, shift_ms)) { // If line was shifted + Erase_Menu_Text(select_file.now + 1 + MROWS - index_file); // Erase and + Draw_SDItem(itemnum + 1); // redraw + } + if (select_file.now < index_file - MROWS) { // Cursor past the top + index_file--; // New bottom line + Scroll_Menu(DWIN_SCROLL_DOWN); + if (index_file == MROWS) { + Draw_Back_First(); + TERN_(SCROLL_LONG_FILENAMES, shift_ms = 0); + } + else { + Draw_SDItem(itemnum, 0); // Draw the item (and init shift name) + } + } + else { + Move_Highlight(-1, select_file.now + MROWS - index_file); // Just move highlight + TERN_(SCROLL_LONG_FILENAMES, Init_Shift_Name()); // ...and init the shift name + } + TERN_(SCROLL_LONG_FILENAMES, Init_SDItem_Shift()); // Reset left. Init timer. + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + if (select_file.now == 0) { // Back + select_page.set(PAGE_PRINT); + return Goto_Main_Menu(); + } + else if (hasUpDir && select_file.now == 1) { // CD-Up + SDCard_Up(); + goto HMI_SelectFileExit; + } + else { + const uint16_t filenum = select_file.now - 1 - hasUpDir; + card.getfilename_sorted(SD_ORDER(filenum, card.get_num_Files())); + + // Enter that folder! + if (card.flag.filenameIsDir) { + SDCard_Folder(card.filename); + goto HMI_SelectFileExit; + } + + // Reset highlight for next entry + select_print.reset(); + select_file.reset(); + + // Start choice and print SD file + HMI_flag.heat_flag = true; + HMI_flag.print_finish = false; + + if (card.fileIsBinary()) + return DWIN_Popup_Confirm(ICON_Error, F("Please check filenames"), F("Only G-code can be printed")); + else + return Goto_ConfirmToPrint(); + } + } + + HMI_SelectFileExit: + DWIN_UpdateLCD(); +} + +// Pause or Stop popup +void onClick_PauseOrStop() { + switch (select_print.now) { + case PRINT_PAUSE_RESUME: if (HMI_flag.select_flag) HMI_flag.pause_flag = true; break; // confirm pause + case PRINT_STOP: if (HMI_flag.select_flag) HMI_flag.abort_flag = true; break; // stop confirmed then abort print + default: break; + } + return Goto_PrintProcess(); +} + +// Printing +void HMI_Printing() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + // Avoid flicker by updating only the previous menu + if (encoder_diffState == ENCODER_DIFF_CW) { + if (select_print.inc(PRINT_COUNT)) { + switch (select_print.now) { + case PRINT_SETUP: ICON_Tune(); break; + case PRINT_PAUSE_RESUME: ICON_Tune(); ICON_ResumeOrPause(); break; + case PRINT_STOP: ICON_ResumeOrPause(); ICON_Stop(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_CCW) { + if (select_print.dec()) { + switch (select_print.now) { + case PRINT_SETUP: ICON_Tune(); ICON_ResumeOrPause(); break; + case PRINT_PAUSE_RESUME: ICON_ResumeOrPause(); ICON_Stop(); break; + case PRINT_STOP: ICON_Stop(); break; + } + } + } + else if (encoder_diffState == ENCODER_DIFF_ENTER) { + switch (select_print.now) { + case PRINT_SETUP: Draw_Tune_Menu(); break; + case PRINT_PAUSE_RESUME: + if (printingIsPaused()) { // if printer is already in pause + ui.resume_print(); + break; + } + else + return Goto_Popup(Popup_window_PauseOrStop, onClick_PauseOrStop); + case PRINT_STOP: + return Goto_Popup(Popup_window_PauseOrStop, onClick_PauseOrStop); + default: break; + } + } + DWIN_UpdateLCD(); +} + +#include "../../../libs/buzzer.h" + +void Draw_Main_Area() { + switch (checkkey) { + case MainMenu: Draw_Main_Menu(); break; + case SelectFile: Draw_Print_File_Menu(); break; + case PrintProcess: Draw_PrintProcess(); break; + case PrintDone: Draw_PrintDone(); break; + #if HAS_ESDIAG + case ESDiagProcess: Draw_EndStopDiag(); break; + #endif + case Popup: popupDraw(); break; + #if HAS_LOCKSCREEN + case Locked: lockScreen.draw(); break; + #endif + case Menu: + case SetInt: + case SetPInt: + case SetIntNoDraw: + case SetFloat: + case SetPFloat: ReDrawMenu(true); break; + default: break; + } +} + +void HMI_ReturnScreen() { + checkkey = last_checkkey; + wait_for_user = false; + Draw_Main_Area(); +} + +void HMI_WaitForUser() { + get_encoder_state(); + if (!wait_for_user) { + switch (checkkey) { + case PrintDone: + select_page.reset(); + Goto_Main_Menu(); + break; + TERN_(HAS_ONESTEP_LEVELING, case Leveling:) + default: HMI_ReturnScreen(); break; + } + } +} + +void HMI_Init() { + DWINUI::Draw_Box(1, Color_Black, {5, 220, DWIN_WIDTH-5, DWINUI::fontHeight()}); + DWINUI::Draw_CenteredString(Color_White, 220, F("Professional Firmware ")); + for (uint16_t t = 0; t <= 100; t += 2) { + DWINUI::Draw_Icon(ICON_Bar, 15, 260); + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 15 + t * 242 / 100, 260, 257, 280); + DWIN_UpdateLCD(); + delay(20); + } + HMI_SetLanguage(); +} + +void EachMomentUpdate() { + static millis_t next_var_update_ms = 0, next_rts_update_ms = 0, next_status_update_ms = 0; + const millis_t ms = millis(); + + if (ELAPSED(ms, next_var_update_ms)) { + next_var_update_ms = ms + DWIN_VAR_UPDATE_INTERVAL; + update_variable(); + #if HAS_ESDIAG + if (checkkey == ESDiagProcess) ESDiag.Update(); + #endif + #if HAS_PIDPLOT + if (checkkey == PidProcess) Plot.Update((HMI_value.pidresult == PID_EXTR_START) ? thermalManager.wholeDegHotend(0) : thermalManager.wholeDegBed()); + #endif + } + + #if HAS_STATUS_MESSAGE_TIMEOUT + bool did_expire = ui.status_reset_callback && (*ui.status_reset_callback)(); + did_expire |= ui.status_message_expire_ms && ELAPSED(ms, ui.status_message_expire_ms); + if (did_expire) ui.reset_status(); + #endif + + if (ELAPSED(ms, next_status_update_ms)) { + next_status_update_ms = ms + 500; + DWIN_DrawStatusMessage(); + } + + if (PENDING(ms, next_rts_update_ms)) return; + next_rts_update_ms = ms + DWIN_SCROLL_UPDATE_INTERVAL; + + if (checkkey == PrintProcess) { // print process + + // Print pause + if (HMI_flag.pause_flag && !HMI_flag.home_flag) { + HMI_flag.pause_flag = false; + if (!HMI_flag.pause_action) { + HMI_flag.pause_action = true; + return ui.pause_print(); + } + } + + // if print done + if (HMI_flag.print_finish && !HMI_flag.home_flag) { + HMI_flag.print_finish = false; + return DWIN_Print_Finished(); + } + + // if print was aborted + if (HMI_flag.abort_flag && !HMI_flag.home_flag) { // Print Stop + HMI_flag.abort_flag = false; + if (!HMI_flag.abort_action) { + HMI_flag.abort_action = true; + ui.abort_print(); + return Goto_PrintDone(); + } + } + + duration_t elapsed = print_job_timer.duration(); // print timer + + if (sdprint && card.isPrinting() && !HMI_flag.percent_flag) { + uint8_t percentDone = card.percentDone(); + if (_percent_done != percentDone) { // print percent + _percent_done = percentDone; + Draw_Print_ProgressBar(); + } + + // Estimate remaining time every 20 seconds + static millis_t next_remain_time_update = 0; + if (_percent_done > 1 && ELAPSED(ms, next_remain_time_update) && !HMI_flag.heat_flag && !HMI_flag.remain_flag) { + _remain_time = (elapsed.value - dwin_heat_time) / (_percent_done * 0.01f) - (elapsed.value - dwin_heat_time); + next_remain_time_update += DWIN_REMAIN_TIME_UPDATE_INTERVAL; + Draw_Print_ProgressRemain(); + } + } + + // Print time so far + static uint16_t last_Printtime = 0; + const uint16_t min = (elapsed.value % 3600) / 60; + if (last_Printtime != min) { // 1 minute update + last_Printtime = min; + Draw_Print_ProgressElapsed(); + } + + } + + #if ENABLED(POWER_LOSS_RECOVERY) + else if (DWIN_lcd_sd_status && recovery.dwin_flag) { // resume print before power off + return Goto_PowerLossRecovery(); + } + #endif // POWER_LOSS_RECOVERY + + DWIN_UpdateLCD(); +} + +#if ENABLED(POWER_LOSS_RECOVERY) + void Popup_PowerLossRecovery() { + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + if (HMI_IsChinese()) { + DWIN_Frame_AreaCopy(1, 160, 338, 235, 354, 98, 115); + DWIN_Frame_AreaCopy(1, 103, 321, 271, 335, 52, 167); + DWINUI::Draw_IconWB(ICON_Cancel_C, 26, 280); + DWINUI::Draw_IconWB(ICON_Continue_C, 146, 280); + } + else { + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 70, GET_TEXT_F(MSG_OUTAGE_RECOVERY)); + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 147, F("It looks like the last")); + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 167, F("file was interrupted.")); + DWINUI::Draw_Button(BTN_Cancel, 26, 280); + DWINUI::Draw_Button(BTN_Continue, 146, 280); + } + SdFile *dir = nullptr; + const char * const filename = card.diveToFile(true, dir, recovery.info.sd_filename); + card.selectFileByName(filename); + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 207, card.longest_filename()); + Draw_Select_Highlight(HMI_flag.select_flag); + DWIN_UpdateLCD(); + } + + void onClick_PowerLossRecovery() { + if (HMI_flag.select_flag) { + queue.inject(F("M1000C")); + select_page.reset(); + return Goto_Main_Menu(); + } + else { + select_print.set(PRINT_SETUP); + queue.inject(F("M1000")); + sdprint = true; + return Goto_PrintProcess(); + } + } + + void Goto_PowerLossRecovery() { + recovery.dwin_flag = false; + LCD_MESSAGE(MSG_CONTINUE_PRINT_JOB); + Goto_Popup(Popup_PowerLossRecovery, onClick_PowerLossRecovery); + } + +#endif // POWER_LOSS_RECOVERY + + +void DWIN_HandleScreen() { + switch (checkkey) { + case MainMenu: HMI_MainMenu(); break; + case Menu: HMI_Menu(); break; + case SetInt: HMI_SetInt(); break; + case SetPInt: HMI_SetPInt(); break; + case SetIntNoDraw: HMI_SetIntNoDraw(); break; + case SetFloat: HMI_SetFloat(); break; + case SetPFloat: HMI_SetPFloat(); break; + case SelectFile: HMI_SelectFile(); break; + case PrintProcess: HMI_Printing(); break; + case Popup: HMI_Popup(); break; + case Leveling: break; + #if HAS_LOCKSCREEN + case Locked: HMI_LockScreen(); break; + #endif + case PrintDone: + TERN_(HAS_ESDIAG, case ESDiagProcess:) + case WaitResponse: HMI_WaitForUser(); break; + case Homing: + case PidProcess: + case NothingToDo: break; + default: break; + } +} + +bool IDisPopUp() { // If ID is popup... + return (checkkey == NothingToDo) + || (checkkey == WaitResponse) + || (checkkey == Homing) + || (checkkey == Leveling) + || (checkkey == PidProcess) + || TERN0(HAS_ESDIAG, (checkkey == ESDiagProcess)) + || (checkkey == Popup); +} + +void HMI_SaveProcessID(const uint8_t id) { + if (checkkey != id) { + if (!IDisPopUp()) last_checkkey = checkkey; // if previous is not a popup + if ((id == Popup) + || TERN0(HAS_ESDIAG, (id == ESDiagProcess)) + || (id == PrintDone) + || (id == Leveling) + || (id == WaitResponse)) wait_for_user = true; + checkkey = id; + } +} + +void DWIN_HomingStart() { + HMI_flag.home_flag = true; + HMI_SaveProcessID(Homing); + Title.ShowCaption(GET_TEXT_F(MSG_HOMING)); + DWIN_Show_Popup(ICON_BLTouch, GET_TEXT_F(MSG_HOMING), GET_TEXT_F(MSG_PLEASE_WAIT)); +} + +void DWIN_HomingDone() { + HMI_flag.home_flag = false; + #if ENABLED(MESH_BED_LEVELING) && EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + planner.synchronize(); + babystep.add_mm(Z_AXIS, HMI_data.ManualZOffset); + #endif + if (HMI_flag.abort_action) DWIN_Print_Aborted(); else HMI_ReturnScreen(); +} + +void DWIN_LevelingStart() { + #if HAS_ONESTEP_LEVELING + HMI_SaveProcessID(Leveling); + Title.ShowCaption(GET_TEXT_F(MSG_BED_LEVELING)); + DWIN_Show_Popup(ICON_AutoLeveling, GET_TEXT_F(MSG_BED_LEVELING), GET_TEXT_F(MSG_PLEASE_WAIT)); + #if BOTH(AUTO_BED_LEVELING_UBL, PREHEAT_BEFORE_LEVELING) + #if HAS_HOTEND + if (thermalManager.degTargetHotend(0) < LEVELING_NOZZLE_TEMP) + thermalManager.setTargetHotend(LEVELING_NOZZLE_TEMP, 0); + #endif + #if HAS_HEATED_BED + if (thermalManager.degTargetBed() < HMI_data.BedLevT) + thermalManager.setTargetBed(HMI_data.BedLevT); + #endif + TERN_(HAS_HOTEND, thermalManager.wait_for_hotend(0)); + TERN_(HAS_HEATED_BED, thermalManager.wait_for_bed_heating()); + #endif + #elif ENABLED(MESH_BED_LEVELING) + Draw_ManualMesh_Menu(); + #endif +} + +void DWIN_LevelingDone() { + TERN_(HAS_MESH, Goto_MeshViewer()); +} + +#if HAS_MESH + void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { + char msg[33] = ""; + char str_1[6] = ""; + sprintf_P(msg, PSTR(S_FMT " %i/%i Z=%s"), GET_TEXT(MSG_PROBING_POINT), xpos, ypos, dtostrf(zval, 1, 2, str_1)); + ui.set_status(msg); + } +#endif + +// PID process + +#if HAS_PIDPLOT + void DWIN_Draw_PIDPopup() { + frame_rect_t gfrm = {40, 180, DWIN_WIDTH - 80, 120}; + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 100, GET_TEXT_F(MSG_PID_AUTOTUNE)); + DWINUI::Draw_String(HMI_data.PopupTxt_Color, gfrm.x, gfrm.y - DWINUI::fontHeight() - 4, F("PID target: Celsius")); + switch (HMI_value.pidresult) { + case PID_EXTR_START: + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 120, F("for Nozzle is running.")); + Plot.Draw(gfrm, thermalManager.hotend_maxtemp[0], HMI_data.HotendPidT); + DWINUI::Draw_Int(HMI_data.PopupTxt_Color, 3, gfrm.x + 90, gfrm.y - DWINUI::fontHeight() - 4, HMI_data.HotendPidT); + break; + case PID_BED_START: + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 120, F("for BED is running.")); + Plot.Draw(gfrm, BED_MAXTEMP, HMI_data.BedPidT); + DWINUI::Draw_Int(HMI_data.PopupTxt_Color, 3, gfrm.x + 90, gfrm.y - DWINUI::fontHeight() - 4, HMI_data.BedPidT); + break; + default: + break; + } + } +#endif + +void DWIN_PidTuning(pidresult_t result) { + HMI_value.pidresult = result; + switch (result) { + case PID_BED_START: + HMI_SaveProcessID(PidProcess); + #if HAS_PIDPLOT + DWIN_Draw_PIDPopup(); + #else + DWIN_Draw_Popup(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE), F("for BED is running.")); + #endif + break; + case PID_EXTR_START: + HMI_SaveProcessID(PidProcess); + #if HAS_PIDPLOT + DWIN_Draw_PIDPopup(); + #else + DWIN_Draw_Popup(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE), F("for Nozzle is running.")); + #endif + break; + case PID_BAD_EXTRUDER_NUM: + checkkey = last_checkkey; + DWIN_Popup_Confirm(ICON_TempTooLow, GET_TEXT_F(MSG_PID_AUTOTUNE_FAILED), GET_TEXT_F(MSG_BAD_EXTRUDER_NUM)); + break; + case PID_TUNING_TIMEOUT: + checkkey = last_checkkey; + DWIN_Popup_Confirm(ICON_TempTooHigh, GET_TEXT_F(MSG_ERROR), GET_TEXT_F(MSG_PID_TIMEOUT)); + break; + case PID_TEMP_TOO_HIGH: + checkkey = last_checkkey; + DWIN_Popup_Confirm(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE_FAILED), GET_TEXT_F(MSG_TEMP_TOO_HIGH)); + break; + case PID_DONE: + checkkey = last_checkkey; + DWIN_Popup_Confirm(ICON_TempTooLow, GET_TEXT_F(MSG_PID_AUTOTUNE), GET_TEXT_F(MSG_BUTTON_DONE)); + break; + default: + checkkey = last_checkkey; + break; + } +} + +// Started a Print Job +void DWIN_Print_Started(const bool sd) { + sdprint = IS_SD_PRINTING() || sd; + _percent_done = 0; + _remain_time = 0; + HMI_flag.percent_flag = false; + HMI_flag.remain_flag = false; + HMI_flag.pause_flag = false; + HMI_flag.pause_action = false; + HMI_flag.abort_flag = false; + HMI_flag.abort_action = false; + HMI_flag.print_finish = false; + Goto_PrintProcess(); +} + +// Pause a print job +void DWIN_Print_Pause() { + ICON_ResumeOrPause(); +} + +// Resume print job +void DWIN_Print_Resume() { + HMI_flag.pause_action = false; + ICON_ResumeOrPause(); + if (printJobOngoing()) { + LCD_MESSAGE(MSG_RESUME_PRINT); + Goto_PrintProcess(); + } +} + +// Ended print job +void DWIN_Print_Finished() { + if (HMI_flag.abort_flag || checkkey == PrintDone) return; + TERN_(POWER_LOSS_RECOVERY, if (card.isPrinting()) recovery.cancel()); + HMI_flag.pause_flag = false; + wait_for_heatup = false; + planner.finish_and_disable(); + thermalManager.cooldown(); + Goto_PrintDone(); +} + +// Print was aborted +void DWIN_Print_Aborted() { + TERN_(DEBUG_DWIN, SERIAL_ECHOLNPGM("DWIN_Print_Aborted")); + HMI_flag.abort_action = false; + wait_for_heatup = false; + planner.finish_and_disable(); + thermalManager.cooldown(); + Goto_PrintDone(); +} + +// Progress and remaining time update +void DWIN_M73() { + if (parser.seenval('P')) { + _percent_done = parser.value_byte(); + HMI_flag.percent_flag = true; + } + if (parser.seenval('R')) { + _remain_time = parser.value_ulong() * 60; + HMI_flag.remain_flag = true; + } + if (checkkey == PrintProcess) { + Draw_Print_ProgressBar(); + Draw_Print_ProgressRemain(); + Draw_Print_ProgressElapsed(); + } +} + +#if HAS_FILAMENT_SENSOR + // Filament Runout process + void DWIN_FilamentRunout(const uint8_t extruder) { LCD_MESSAGE(MSG_RUNOUT_SENSOR); } +#endif + +void DWIN_SetColorDefaults() { + HMI_data.Background_Color = Def_Background_Color; + HMI_data.Cursor_color = Def_Cursor_color; + HMI_data.TitleBg_color = Def_TitleBg_color; + HMI_data.TitleTxt_color = Def_TitleTxt_color; + HMI_data.Text_Color = Def_Text_Color; + HMI_data.Selected_Color = Def_Selected_Color; + HMI_data.SplitLine_Color = Def_SplitLine_Color; + HMI_data.Highlight_Color = Def_Highlight_Color; + HMI_data.StatusBg_Color = Def_StatusBg_Color; + HMI_data.StatusTxt_Color = Def_StatusTxt_Color; + HMI_data.PopupBg_color = Def_PopupBg_color; + HMI_data.PopupTxt_Color = Def_PopupTxt_Color; + HMI_data.AlertBg_Color = Def_AlertBg_Color; + HMI_data.AlertTxt_Color = Def_AlertTxt_Color; + HMI_data.PercentTxt_Color = Def_PercentTxt_Color; + HMI_data.Barfill_Color = Def_Barfill_Color; + HMI_data.Indicator_Color = Def_Indicator_Color; + HMI_data.Coordinate_Color = Def_Coordinate_Color; +} + +void DWIN_SetDataDefaults() { + DWIN_SetColorDefaults(); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + TERN_(HAS_HOTEND, HMI_data.HotendPidT = PREHEAT_1_TEMP_HOTEND); + TERN_(HAS_HEATED_BED, HMI_data.BedPidT = PREHEAT_1_TEMP_BED); + TERN_(HAS_HOTEND, HMI_data.PidCycles = 5); + #if ENABLED(PREVENT_COLD_EXTRUSION) + HMI_data.ExtMinT = EXTRUDE_MINTEMP; + ApplyExtMinT(); + #endif + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + HMI_data.BedLevT = LEVELING_BED_TEMP; + #endif + TERN_(BAUD_RATE_GCODE, SetBaud250K()); + #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) + TERN_(LED_COLOR_PRESETS, leds.set_default()); + ApplyLEDColor(); + #endif +} + +void DWIN_CopySettingsTo(char * const buff) { + memcpy(buff, &HMI_data, eeprom_data_size); +} + +void DWIN_CopySettingsFrom(const char * const buff) { + memcpy(&HMI_data, buff, sizeof(HMI_data_t)); + if (HMI_data.Text_Color == HMI_data.Background_Color) DWIN_SetColorDefaults(); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + TERN_(PREVENT_COLD_EXTRUSION, ApplyExtMinT()); + feedrate_percentage = 100; + TERN_(BAUD_RATE_GCODE, HMI_SetBaudRate()); + #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) + leds.set_color( + HMI_data.Led_Color.r, + HMI_data.Led_Color.g, + HMI_data.Led_Color.b + OPTARG(HAS_WHITE_LED, HMI_data.Led_Color.w) + ); + leds.update(); + #endif + +} + +// Initialize or re-initialize the LCD +void MarlinUI::init_lcd() { + TERN_(DEBUG_DWIN, SERIAL_ECHOLNPGM("DWIN_Startup")); + DWINUI::init(); + DWIN_JPG_CacheTo1(Language_English); + Encoder_Configuration(); +} + +void DWIN_InitScreen() { + HMI_Init(); // draws boot screen + onCursorDraw = Draw_Menu_Cursor; + onCursorErase = Erase_Menu_Cursor; + DWINUI::onTitleDraw = Draw_Title; + onMenuDraw = Draw_Menu; + checkkey = 255; + CurrentMenu = nullptr; + PreviousMenu = nullptr; + index_file = MROWS; + hash_changed = true; + last_E = 0; + DWIN_DrawStatusLine(); + DWIN_Draw_Dashboard(); + Goto_Main_Menu(); +} + +void MarlinUI::update() { + EachMomentUpdate(); // Status update + HMI_SDCardUpdate(); // SD card update + DWIN_HandleScreen(); // Rotary encoder update +} + +void MarlinUI::refresh() { /* Nothing to see here */ } + +#if HAS_LCD_BRIGHTNESS + void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); } +#endif + +void MarlinUI::kill_screen(FSTR_P const lcd_error, FSTR_P const lcd_component) { + DWIN_Draw_Popup(ICON_BLTouch, GET_TEXT_F(MSG_PRINTER_KILLED), lcd_error); + DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 270, GET_TEXT_F(MSG_TURN_OFF)); + DWIN_UpdateLCD(); +} + +void DWIN_RebootScreen() { + DWIN_Frame_Clear(Color_Bg_Black); + DWIN_JPG_ShowAndCache(0); + DWINUI::Draw_CenteredString(Color_White, 220, GET_TEXT_F(MSG_PLEASE_WAIT_REBOOT)); + DWIN_UpdateLCD(); + safe_delay(500); +} + +void DWIN_RedrawDash() { + hash_changed = true; + DWIN_DrawStatusMessage(); + DWIN_Draw_Dashboard(); +} + +void DWIN_RedrawScreen() { + Draw_Main_Area(); + DWIN_RedrawDash(); +} + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + void DWIN_Popup_Pause(FSTR_P const fmsg, uint8_t button /*= 0*/) { + HMI_SaveProcessID(button ? WaitResponse : NothingToDo); + DWIN_Show_Popup(ICON_BLTouch, GET_TEXT_F(MSG_ADVANCED_PAUSE), fmsg, button); + } + + void MarlinUI::pause_show_message(const PauseMessage message, const PauseMode mode/*=PAUSE_MODE_SAME*/, const uint8_t extruder/*=active_extruder*/) { + //if (mode == PAUSE_MODE_SAME) return; + pause_mode = mode; + switch (message) { + case PAUSE_MESSAGE_PARKING: DWIN_Popup_Pause(GET_TEXT_F(MSG_PAUSE_PRINT_PARKING)); break; // M125 + case PAUSE_MESSAGE_CHANGING: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_INIT)); break; // pause_print (M125, M600) + case PAUSE_MESSAGE_WAITING: DWIN_Popup_Pause(GET_TEXT_F(MSG_ADVANCED_PAUSE_WAITING), BTN_Continue); break; + case PAUSE_MESSAGE_INSERT: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_INSERT), BTN_Continue); break; + case PAUSE_MESSAGE_LOAD: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_LOAD)); break; + case PAUSE_MESSAGE_UNLOAD: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_UNLOAD)); break; // Unload of pause and Unload of M702 + case PAUSE_MESSAGE_PURGE: + #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE) + DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_CONT_PURGE)); + #else + DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE)); + #endif + break; + case PAUSE_MESSAGE_OPTION: Goto_FilamentPurge(); break; + case PAUSE_MESSAGE_RESUME: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_RESUME)); break; + case PAUSE_MESSAGE_HEAT: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_HEAT), BTN_Continue); break; + case PAUSE_MESSAGE_HEATING: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_HEATING)); break; + case PAUSE_MESSAGE_STATUS: HMI_ReturnScreen(); break; // Exit from Pause, Load and Unload + default: break; + } + } + + void Draw_Popup_FilamentPurge() { + DWIN_Draw_Popup(ICON_BLTouch, GET_TEXT_F(MSG_ADVANCED_PAUSE), GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE_CONTINUE)); + DWINUI::Draw_Button(BTN_Purge, 26, 280); + DWINUI::Draw_Button(BTN_Continue, 146, 280); + Draw_Select_Highlight(true); + } + + void onClick_FilamentPurge() { + if (HMI_flag.select_flag) + pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; // "Purge More" button + else { + HMI_SaveProcessID(NothingToDo); + pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; // "Continue" button + } + } + + void Goto_FilamentPurge() { + pause_menu_response = PAUSE_RESPONSE_WAIT_FOR; + Goto_Popup(Draw_Popup_FilamentPurge, onClick_FilamentPurge); + } + +#endif // ADVANCED_PAUSE_FEATURE + +#if HAS_MESH + void DWIN_MeshViewer() { + if (!leveling_is_valid()) + DWIN_Popup_Continue(ICON_BLTouch, GET_TEXT_F(MSG_MESH_VIEWER), GET_TEXT_F(MSG_NO_VALID_MESH)); + else { + HMI_SaveProcessID(WaitResponse); + MeshViewer.Draw(); + } + } +#endif // HAS_MESH + + +#if HAS_LOCKSCREEN + + void DWIN_LockScreen() { + if (checkkey != Locked) { + lockScreen.rprocess = checkkey; + checkkey = Locked; + lockScreen.init(); + } + } + + void DWIN_UnLockScreen() { + if (checkkey == Locked) { + checkkey = lockScreen.rprocess; + Draw_Main_Area(); + } + } + + void HMI_LockScreen() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + lockScreen.onEncoder(encoder_diffState); + if (lockScreen.isUnlocked()) DWIN_UnLockScreen(); + } + +#endif // HAS_LOCKSCREEN + +#if HAS_GCODE_PREVIEW + + void onClick_ConfirmToPrint() { + if (HMI_flag.select_flag) { // Confirm + card.openAndPrintFile(card.filename); + return DWIN_Print_Started(true); + } + else { // Cancel + DWIN_ResetStatusLine(); + checkkey = SelectFile; + return Draw_Print_File_Menu(); + } + } + + void Goto_ConfirmToPrint() { + Goto_Popup(Preview_DrawFromSD, onClick_ConfirmToPrint); + } + +#else + void Goto_ConfirmToPrint() { + card.openAndPrintFile(card.filename); + DWIN_Print_Started(true); + } +#endif + +#if HAS_ESDIAG + void Draw_EndStopDiag() { + HMI_SaveProcessID(ESDiagProcess); + ESDiag.Draw(); + } +#endif + +//============================================================================= +// NEW MENU SUBSYSTEM +//============================================================================= + +// Tool functions + +#if ENABLED(EEPROM_SETTINGS) + void WriteEeprom() { + ui.set_status(GET_TEXT_F(MSG_STORE_EEPROM)); + DWIN_DrawStatusLine(); + DWIN_UpdateLCD(); + DONE_BUZZ(settings.save()); + } + + void ReadEeprom() { + const bool success = settings.load(); + DWIN_RedrawScreen(); + DONE_BUZZ(success); + } + + void ResetEeprom() { + settings.reset(); + DWIN_RedrawScreen(); + DONE_BUZZ(true); + } + + #if HAS_MESH + void SaveMesh() { TERN(AUTO_BED_LEVELING_UBL, UBLSaveMesh(), WriteEeprom()); } + #endif +#endif + +// Reset Printer +void RebootPrinter() { + wait_for_heatup = wait_for_user = false; // Stop waiting for heating/user + thermalManager.disable_all_heaters(); + planner.finish_and_disable(); + DWIN_RebootScreen(); + hal.reboot(); +} + +void Goto_Info_Menu() { + Draw_Info_Menu(); + DWIN_UpdateLCD(); + HMI_SaveProcessID(WaitResponse); +} + +void Goto_Move_Menu() { + #if HAS_HOTEND + gcode.process_subcommands_now(F("G92E0")); // reset extruder position + #endif + Draw_Move_Menu(); +} + +void DisableMotors() { queue.inject(F("M84")); } + +void AutoLev() { // Always reacquire the Z "home" position + queue.inject(F(TERN(AUTO_BED_LEVELING_UBL, "G28Z\nG29P1", "G28XYO\nG28Z\nG29"))); +} + +void AutoHome() { queue.inject_P(G28_STR); } +void HomeX() { queue.inject(F("G28X")); } +void HomeY() { queue.inject(F("G28Y")); } +void HomeZ() { queue.inject(F("G28Z")); } + +#if HAS_HOME_OFFSET + // Apply workspace offset, making the current position 0,0,0 + void SetHome() { + queue.inject(F("G92X0Y0Z0")); + DONE_BUZZ(true); + } +#endif + +#if HAS_ZOFFSET_ITEM + + void ApplyZOffset() { TERN_(EEPROM_SETTINGS, settings.save()); } + void LiveZOffset() { + #if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + const_float_t step_zoffset = round((MenuData.Value / 100.0f) * planner.settings.axis_steps_per_mm[Z_AXIS]) - babystep.accum; + if (BABYSTEP_ALLOWED()) babystep.add_steps(Z_AXIS, step_zoffset); + #endif + } + + #if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + void SetZOffset() { + babystep.accum = round(planner.settings.axis_steps_per_mm[Z_AXIS] * BABY_Z_VAR); + SetPFloatOnClick(Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX, 2, ApplyZOffset, LiveZOffset); + } + #endif + + void SetMoveZto0() { + #if ENABLED(Z_SAFE_HOMING) + char cmd[54], str_1[5], str_2[5]; + sprintf_P(cmd, PSTR("G28XYO\nG28Z\nG0X%sY%sF5000\nG0Z0F300\nM400"), + dtostrf(Z_SAFE_HOMING_X_POINT, 1, 1, str_1), + dtostrf(Z_SAFE_HOMING_Y_POINT, 1, 1, str_2) + ); + gcode.process_subcommands_now(cmd); + #else + TERN_(HAS_LEVELING, set_bed_leveling_enabled(false)); + gcode.process_subcommands_now(F("G28O\nG0Z0F300\nM400")); + #endif + ui.reset_status(); + DONE_BUZZ(true); + } + + #if !HAS_BED_PROBE + void HomeZandDisable() { + SetMoveZto0(); + DisableMotors(); + } + #endif + +#endif // HAS_ZOFFSET_ITEM + +#if HAS_PREHEAT + void DoPreheat0() { ui.preheat_all(0); } + #if PREHEAT_COUNT >= 2 + void DoPreheat1() { ui.preheat_all(1); } + #if PREHEAT_COUNT >= 3 + void DoPreheat2() { ui.preheat_all(2); } + #endif + #endif +#endif + +void DoCoolDown() { thermalManager.cooldown(); } + +void SetLanguage() { + HMI_ToggleLanguage(); + CurrentMenu = nullptr; // Invalidate menu to full redraw + Draw_Prepare_Menu(); +} + +void LiveMove() { + *MenuData.P_Float = MenuData.Value / MINUNITMULT; + if (!planner.is_full()) { + planner.synchronize(); + planner.buffer_line(current_position, homing_feedrate(HMI_value.axis)); + } +} +void ApplyMoveE() { + last_E = MenuData.Value / MINUNITMULT; + if (!planner.is_full()) { + planner.synchronize(); + planner.buffer_line(current_position, MMM_TO_MMS(FEEDRATE_E)); + } +} +void SetMoveX() { HMI_value.axis = X_AXIS; SetPFloatOnClick(X_MIN_POS, X_MAX_POS, UNITFDIGITS, planner.synchronize, LiveMove); } +void SetMoveY() { HMI_value.axis = Y_AXIS; SetPFloatOnClick(Y_MIN_POS, Y_MAX_POS, UNITFDIGITS, planner.synchronize, LiveMove); } +void SetMoveZ() { HMI_value.axis = Z_AXIS; SetPFloatOnClick(Z_MIN_POS, Z_MAX_POS, UNITFDIGITS, planner.synchronize, LiveMove); } + +#if HAS_HOTEND + void SetMoveE() { + #if ENABLED(PREVENT_COLD_EXTRUSION) + if (thermalManager.tooColdToExtrude(0)) + return DWIN_Popup_Confirm(ICON_TempTooLow, GET_TEXT_F(MSG_HOTEND_TOO_COLD), GET_TEXT_F(MSG_PLEASE_PREHEAT)); + #endif + SetPFloatOnClick(last_E - (EXTRUDE_MAXLENGTH), last_E + (EXTRUDE_MAXLENGTH), UNITFDIGITS, ApplyMoveE); + } +#endif + +void SetPID(celsius_t t, heater_id_t h) { + char cmd[53] = ""; + char str_1[5] = "", str_2[5] = ""; + sprintf_P(cmd, PSTR("G28OXY\nG0Z5F300\nG0X%sY%sF5000\nM84\nM400"), + dtostrf(X_CENTER, 1, 1, str_1), + dtostrf(Y_CENTER, 1, 1, str_2) + ); + gcode.process_subcommands_now(cmd); + thermalManager.PID_autotune(t, h, HMI_data.PidCycles, true); +} +#if HAS_HOTEND + void HotendPID() { SetPID(HMI_data.HotendPidT, H_E0); } +#endif +#if HAS_HEATED_BED + void BedPID() { SetPID(HMI_data.BedPidT, H_BED); } +#endif + +#if ENABLED(POWER_LOSS_RECOVERY) + void SetPwrLossr() { + recovery.enable(!recovery.enabled); + Draw_Chkb_Line(CurrentMenu->line(), recovery.enabled); + DWIN_UpdateLCD(); + } +#endif + +#if ENABLED(BAUD_RATE_GCODE) + void HMI_SetBaudRate() { HMI_data.Baud115K ? SetBaud115K() : SetBaud250K(); } + void SetBaudRate() { + HMI_data.Baud115K ^= true; + HMI_SetBaudRate(); + Draw_Chkb_Line(CurrentMenu->line(), HMI_data.Baud115K); + DWIN_UpdateLCD(); + } + void SetBaud115K() { queue.inject(F("M575 P0 B115200")); HMI_data.Baud115K = true; } + void SetBaud250K() { queue.inject(F("M575 P0 B250000")); HMI_data.Baud115K = false; } +#endif + +#if HAS_LCD_BRIGHTNESS + void ApplyBrightness() { ui.set_brightness(MenuData.Value); } + void LiveBrightness() { DWIN_LCD_Brightness(MenuData.Value); } + void SetBrightness() { SetIntOnClick(LCD_BRIGHTNESS_MIN, LCD_BRIGHTNESS_MAX, ui.brightness, ApplyBrightness, LiveBrightness); } + void TurnOffBacklight() { HMI_SaveProcessID(WaitResponse); ui.set_brightness(0); DWIN_RedrawScreen(); } +#endif + +#if ENABLED(CASE_LIGHT_MENU) + void SetCaseLight() { + caselight.on = !caselight.on; + caselight.update_enabled(); + Draw_Chkb_Line(CurrentMenu->line(), caselight.on); + DWIN_UpdateLCD(); + } + #if ENABLED(CASELIGHT_USES_BRIGHTNESS) + void LiveCaseLightBrightness() { caselight.brightness = MenuData.Value; caselight.update_brightness(); } + void SetCaseLightBrightness() { SetIntOnClick(0, 255, caselight.brightness, nullptr, LiveCaseLightBrightness); } + #endif +#endif + +#if ENABLED(LED_CONTROL_MENU) + #if !BOTH(CASE_LIGHT_MENU, CASE_LIGHT_USE_NEOPIXEL) + void SetLedStatus() { + leds.toggle(); + Draw_Chkb_Line(CurrentMenu->line(), leds.lights_on); + DWIN_UpdateLCD(); + } + #endif + #if HAS_COLOR_LEDS + void ApplyLEDColor() { + HMI_data.Led_Color = LEDColor( {leds.color.r, leds.color.g, leds.color.b OPTARG(HAS_WHITE_LED, HMI_data.Led_Color.w) } ); + } + void LiveLEDColor(uint8_t *color) { *color = MenuData.Value; leds.update(); } + void LiveLEDColorR() { LiveLEDColor(&leds.color.r); } + void LiveLEDColorG() { LiveLEDColor(&leds.color.g); } + void LiveLEDColorB() { LiveLEDColor(&leds.color.b); } + void SetLEDColorR() { SetIntOnClick(0, 255, leds.color.r, ApplyLEDColor, LiveLEDColorR); } + void SetLEDColorG() { SetIntOnClick(0, 255, leds.color.g, ApplyLEDColor, LiveLEDColorG); } + void SetLEDColorB() { SetIntOnClick(0, 255, leds.color.b, ApplyLEDColor, LiveLEDColorB); } + #if HAS_WHITE_LED + void LiveLEDColorW() { LiveLEDColor(&leds.color.w); } + void SetLEDColorW() { SetIntOnClick(0, 255, leds.color.w, ApplyLEDColor, LiveLEDColorW); } + #endif + #endif +#endif + +#if ENABLED(SOUND_MENU_ITEM) + void SetEnableSound() { + ui.sound_on = !ui.sound_on; + Draw_Chkb_Line(CurrentMenu->line(), ui.sound_on); + DWIN_UpdateLCD(); + } +#endif + +#if HAS_HOME_OFFSET + void ApplyHomeOffset() { set_home_offset(HMI_value.axis, MenuData.Value / MINUNITMULT); } + void SetHomeOffsetX() { HMI_value.axis = X_AXIS; SetPFloatOnClick(-50, 50, UNITFDIGITS, ApplyHomeOffset); } + void SetHomeOffsetY() { HMI_value.axis = Y_AXIS; SetPFloatOnClick(-50, 50, UNITFDIGITS, ApplyHomeOffset); } + void SetHomeOffsetZ() { HMI_value.axis = Z_AXIS; SetPFloatOnClick( -2, 2, UNITFDIGITS, ApplyHomeOffset); } +#endif + +#if HAS_BED_PROBE + void SetProbeOffsetX() { SetPFloatOnClick(-60, 60, UNITFDIGITS); } + void SetProbeOffsetY() { SetPFloatOnClick(-60, 60, UNITFDIGITS); } + void SetProbeOffsetZ() { SetPFloatOnClick(-10, 10, 2); } + void ProbeTest() { + LCD_MESSAGE(MSG_M48_TEST); + queue.inject(F("G28O\nM48 P10")); + } + void ProbeStow() { probe.stow(); } + void ProbeDeploy() { probe.deploy(); } + + #ifdef BLTOUCH_HS_MODE + void SetHSMode() { + bltouch.high_speed_mode = !bltouch.high_speed_mode; + Draw_Chkb_Line(CurrentMenu->line(), bltouch.high_speed_mode); + DWIN_UpdateLCD(); + } + #endif + +#endif + +#if HAS_FILAMENT_SENSOR + void SetRunoutEnable() { + runout.reset(); + runout.enabled = !runout.enabled; + Draw_Chkb_Line(CurrentMenu->line(), runout.enabled); + DWIN_UpdateLCD(); + } + #if HAS_FILAMENT_RUNOUT_DISTANCE + void ApplyRunoutDistance() { runout.set_runout_distance(MenuData.Value / MINUNITMULT); } + void SetRunoutDistance() { SetFloatOnClick(0, 999, UNITFDIGITS, runout.runout_distance(), ApplyRunoutDistance); } + #endif +#endif + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + void SetFilLoad() { SetPFloatOnClick(0, MAX_LOAD_UNLOAD, UNITFDIGITS); } + void SetFilUnload() { SetPFloatOnClick(0, MAX_LOAD_UNLOAD, UNITFDIGITS); } +#endif + +#if ENABLED(PREVENT_COLD_EXTRUSION) + void ApplyExtMinT() { thermalManager.extrude_min_temp = HMI_data.ExtMinT; thermalManager.allow_cold_extrude = (HMI_data.ExtMinT == 0); } + void SetExtMinT() { SetPIntOnClick(MIN_ETEMP, MAX_ETEMP, ApplyExtMinT); } +#endif + +void RestoreDefaultsColors() { + DWIN_SetColorDefaults(); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + DWIN_RedrawScreen(); +} + +void SelColor() { + MenuData.P_Int = (int16_t*)static_cast(CurrentMenu->SelectedItem())->value; + HMI_value.Color[0] = GetRColor(*MenuData.P_Int); // Red + HMI_value.Color[1] = GetGColor(*MenuData.P_Int); // Green + HMI_value.Color[2] = GetBColor(*MenuData.P_Int); // Blue + Draw_GetColor_Menu(); +} + +void LiveRGBColor() { + HMI_value.Color[CurrentMenu->line() - 2] = MenuData.Value; + uint16_t color = RGB(HMI_value.Color[0], HMI_value.Color[1], HMI_value.Color[2]); + DWIN_Draw_Rectangle(1, color, 20, 315, DWIN_WIDTH - 20, 335); +} +void SetRGBColor() { + const uint8_t color = CurrentMenu->SelectedItem()->icon; + SetIntOnClick(0, (color == 1) ? 63 : 31, HMI_value.Color[color], nullptr, LiveRGBColor); +} + +void DWIN_ApplyColor() { + *MenuData.P_Int = RGB(HMI_value.Color[0], HMI_value.Color[1], HMI_value.Color[2]); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + Draw_SelectColors_Menu(); + hash_changed = true; + LCD_MESSAGE(MSG_COLORS_APPLIED); + DWIN_Draw_Dashboard(); +} + +void SetSpeed() { SetPIntOnClick(MIN_PRINT_SPEED, MAX_PRINT_SPEED); } + +#if HAS_HOTEND + void ApplyHotendTemp() { thermalManager.setTargetHotend(MenuData.Value, 0); } + void SetHotendTemp() { SetIntOnClick(MIN_ETEMP, MAX_ETEMP, thermalManager.degTargetHotend(0), ApplyHotendTemp); } +#endif + +#if HAS_HEATED_BED + void ApplyBedTemp() { thermalManager.setTargetBed(MenuData.Value); } + void SetBedTemp() { SetIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP, thermalManager.degTargetBed(), ApplyBedTemp); } +#endif + +#if HAS_FAN + void ApplyFanSpeed() { thermalManager.set_fan_speed(0, MenuData.Value); } + void SetFanSpeed() { SetIntOnClick(0, 255, thermalManager.fan_speed[0], ApplyFanSpeed); } +#endif + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + + void ChangeFilament() { + HMI_SaveProcessID(NothingToDo); + queue.inject(F("M600 B2")); + } + + void ParkHead() { + LCD_MESSAGE(MSG_FILAMENT_PARK_ENABLED); + queue.inject(F("G28O\nG27")); + } + + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + void UnloadFilament() { + LCD_MESSAGE(MSG_FILAMENTUNLOAD); + queue.inject(F("M702 Z20")); + } + + void LoadFilament() { + LCD_MESSAGE(MSG_FILAMENTLOAD); + queue.inject(F("M701 Z20")); + } + #endif + +#endif // ADVANCED_PAUSE_FEATURE + +void ApplyFlow() { planner.refresh_e_factor(0); } +void SetFlow() { SetPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW, ApplyFlow); } + +// Bed Tramming + +void TramXY(const uint8_t point, const float &margin, float &x, float &y) { + switch (point) { + case 0: + LCD_MESSAGE(MSG_LEVBED_FL); + x = y = margin; + break; + case 1: + LCD_MESSAGE(MSG_LEVBED_FR); + x = X_BED_SIZE - margin; y = margin; + break; + case 2: + LCD_MESSAGE(MSG_LEVBED_BR); + x = X_BED_SIZE - margin; y = Y_BED_SIZE - margin; + break; + case 3: + LCD_MESSAGE(MSG_LEVBED_BL); + x = margin; y = Y_BED_SIZE - margin; + break; + case 4: + LCD_MESSAGE(MSG_LEVBED_C); + x = X_CENTER; y = Y_CENTER; + break; + } +} + +#if HAS_BED_PROBE + + float Tram(const uint8_t point) { + char cmd[100] = ""; + static bool inLev = false; + float xpos = 0, ypos = 0, zval = 0, margin = 0; + char str_1[6] = "", str_2[6] = "", str_3[6] = ""; + if (inLev) return NAN; + margin = HMI_data.FullManualTramming ? 30 : PROBING_MARGIN; + + TramXY(point, margin, xpos, ypos); + + if (HMI_data.FullManualTramming) { + sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%sY%sF5000\nG0Z0F300"), + dtostrf(xpos, 1, 1, str_1), + dtostrf(ypos, 1, 1, str_2) + ); + queue.inject(cmd); + } + else { + // AUTO_BED_LEVELING_BILINEAR does not define MESH_INSET + #ifndef MESH_MIN_X + #define MESH_MIN_X (_MAX(X_MIN_BED + PROBING_MARGIN, X_MIN_POS)) + #endif + #ifndef MESH_MIN_Y + #define MESH_MIN_Y (_MAX(Y_MIN_BED + PROBING_MARGIN, Y_MIN_POS)) + #endif + #ifndef MESH_MAX_X + #define MESH_MAX_X (_MIN(X_MAX_BED - (PROBING_MARGIN), X_MAX_POS)) + #endif + #ifndef MESH_MAX_Y + #define MESH_MAX_Y (_MIN(Y_MAX_BED - (PROBING_MARGIN), Y_MAX_POS)) + #endif + + LIMIT(xpos, MESH_MIN_X, MESH_MAX_X); + LIMIT(ypos, MESH_MIN_Y, MESH_MAX_Y); + probe.stow(); + gcode.process_subcommands_now(F("M420S0\nG28O")); + inLev = true; + zval = probe.probe_at_point(xpos, ypos, PROBE_PT_STOW); + if (isnan(zval)) + LCD_MESSAGE(MSG_ZPROBE_OUT); + else { + sprintf_P(cmd, PSTR("X:%s, Y:%s, Z:%s"), + dtostrf(xpos, 1, 1, str_1), + dtostrf(ypos, 1, 1, str_2), + dtostrf(zval, 1, 2, str_3) + ); + ui.set_status(cmd); + } + inLev = false; + } + return zval; + } + +#else + + void Tram(const uint8_t point) { + float xpos = 0, ypos = 0, margin = 30; + TramXY(point, margin, xpos, ypos); + + char cmd[100] = "", str_1[6] = "", str_2[6] = ""; + sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%sY%sF5000\nG0Z0F300"), dtostrf(xpos, 1, 1, str_1), dtostrf(ypos, 1, 1, str_2)); + queue.inject(cmd); + } + +#endif + +void TramFL() { Tram(0); } +void TramFR() { Tram(1); } +void TramBR() { Tram(2); } +void TramBL() { Tram(3); } +void TramC () { Tram(4); } + +#if HAS_BED_PROBE + + void Trammingwizard() { + bed_mesh_t zval = {0}; + if (HMI_data.FullManualTramming) { + LCD_MESSAGE_F("Disable manual tramming"); + return; + } + zval[0][0] = Tram(0); + checkkey = NothingToDo; + MeshViewer.DrawMesh(zval, 2, 2); + zval[1][0] = Tram(1); + MeshViewer.DrawMesh(zval, 2, 2); + zval[1][1] = Tram(2); + MeshViewer.DrawMesh(zval, 2, 2); + zval[0][1] = Tram(3); + MeshViewer.DrawMesh(zval, 2, 2); + + DWINUI::Draw_CenteredString(140, F("Calculating average")); + DWINUI::Draw_CenteredString(160, F("and relative heights")); + safe_delay(1000); + float avg = 0.0f; + LOOP_L_N(x, 2) LOOP_L_N(y, 2) avg += zval[x][y]; + avg /= 4.0f; + LOOP_L_N(x, 2) LOOP_L_N(y, 2) zval[x][y] -= avg; + MeshViewer.DrawMesh(zval, 2, 2); + ui.reset_status(); + + if (ABS(MeshViewer.max - MeshViewer.min) < 0.05) { + DWINUI::Draw_CenteredString(140,F("Corners leveled")); + DWINUI::Draw_CenteredString(160,F("Tolerance achieved!")); + } + else { + uint8_t p = 0; + float max = 0; + FSTR_P plabel; + bool s = true; + LOOP_L_N(x, 2) LOOP_L_N(y, 2) { + const float d = ABS(zval[x][y]); + if (max < d) { + s = (zval[x][y] >= 0); + max = d; + p = x + 2 * y; + } + } + switch (p) { + case 0b00 : plabel = GET_TEXT_F(MSG_LEVBED_FL); break; + case 0b01 : plabel = GET_TEXT_F(MSG_LEVBED_FR); break; + case 0b10 : plabel = GET_TEXT_F(MSG_LEVBED_BL); break; + case 0b11 : plabel = GET_TEXT_F(MSG_LEVBED_BR); break; + default : plabel = F(""); break; + } + DWINUI::Draw_CenteredString(120, F("Corners not leveled")); + DWINUI::Draw_CenteredString(140, F("Knob adjustment required")); + DWINUI::Draw_CenteredString(Color_Green, 160, s ? F("Lower") : F("Raise")); + DWINUI::Draw_CenteredString(Color_Green, 180, plabel); + } + DWINUI::Draw_Button(BTN_Continue, 86, 305); + checkkey = Menu; + HMI_SaveProcessID(WaitResponse); + } + + void SetManualTramming() { + HMI_data.FullManualTramming = !HMI_data.FullManualTramming; + Draw_Chkb_Line(CurrentMenu->line(), HMI_data.FullManualTramming); + DWIN_UpdateLCD(); + } + +#endif // HAS_BED_PROBE + +#if ENABLED(MESH_BED_LEVELING) + + void ManualMeshStart() { + LCD_MESSAGE(MSG_UBL_BUILD_MESH_MENU); + gcode.process_subcommands_now(F("G28XYO\nG28Z\nM211S0\nG29S1")); + #ifdef MANUAL_PROBE_START_Z + const uint8_t line = CurrentMenu->line(MMeshMoveZItem->pos); + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, 2, VALX - 2 * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), MANUAL_PROBE_START_Z); + #endif + } + + void LiveMeshMoveZ() { + *MenuData.P_Float = MenuData.Value / POW(10, 2); + if (!planner.is_full()) { + planner.synchronize(); + planner.buffer_line(current_position, homing_feedrate(Z_AXIS)); + } + } + void SetMMeshMoveZ() { SetPFloatOnClick(-1, 1, 2, planner.synchronize, LiveMeshMoveZ); } + + void ManualMeshContinue() { + gcode.process_subcommands_now(F("G29S2")); + MMeshMoveZItem->redraw(); + } + + void ManualMeshSave() { + LCD_MESSAGE(MSG_UBL_STORAGE_MESH_MENU); + queue.inject(F("M211S1\nM500")); + } + +#endif // MESH_BED_LEVELING + +#if HAS_PREHEAT + #if HAS_HOTEND + void SetPreheatEndTemp() { SetPIntOnClick(MIN_ETEMP, MAX_ETEMP); } + #endif + #if HAS_HEATED_BED + void SetPreheatBedTemp() { SetPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); } + #endif + #if HAS_FAN + void SetPreheatFanSpeed() { SetPIntOnClick(0, 255); } + #endif +#endif + +void ApplyMaxSpeed() { planner.set_max_feedrate(HMI_value.axis, MenuData.Value / MINUNITMULT); } +void SetMaxSpeedX() { HMI_value.axis = X_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[X_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[X_AXIS], ApplyMaxSpeed); } +void SetMaxSpeedY() { HMI_value.axis = Y_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[Y_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[Y_AXIS], ApplyMaxSpeed); } +void SetMaxSpeedZ() { HMI_value.axis = Z_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[Z_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[Z_AXIS], ApplyMaxSpeed); } +#if HAS_HOTEND + void SetMaxSpeedE() { HMI_value.axis = E_AXIS; SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[E_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[E_AXIS], ApplyMaxSpeed); } +#endif + +void ApplyMaxAccel() { planner.set_max_acceleration(HMI_value.axis, MenuData.Value); } +void SetMaxAccelX() { HMI_value.axis = X_AXIS, SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[X_AXIS], planner.settings.max_acceleration_mm_per_s2[X_AXIS], ApplyMaxAccel); } +void SetMaxAccelY() { HMI_value.axis = Y_AXIS, SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[Y_AXIS], planner.settings.max_acceleration_mm_per_s2[Y_AXIS], ApplyMaxAccel); } +void SetMaxAccelZ() { HMI_value.axis = Z_AXIS, SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[Z_AXIS], planner.settings.max_acceleration_mm_per_s2[Z_AXIS], ApplyMaxAccel); } +#if HAS_HOTEND + void SetMaxAccelE() { HMI_value.axis = E_AXIS; SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[E_AXIS], planner.settings.max_acceleration_mm_per_s2[E_AXIS], ApplyMaxAccel); } +#endif + +#if HAS_CLASSIC_JERK + void ApplyMaxJerk() { planner.set_max_jerk(HMI_value.axis, MenuData.Value / MINUNITMULT); } + void SetMaxJerkX() { HMI_value.axis = X_AXIS, SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[X_AXIS], UNITFDIGITS, planner.max_jerk[X_AXIS], ApplyMaxJerk); } + void SetMaxJerkY() { HMI_value.axis = Y_AXIS, SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[Y_AXIS], UNITFDIGITS, planner.max_jerk[Y_AXIS], ApplyMaxJerk); } + void SetMaxJerkZ() { HMI_value.axis = Z_AXIS, SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[Z_AXIS], UNITFDIGITS, planner.max_jerk[Z_AXIS], ApplyMaxJerk); } + #if HAS_HOTEND + void SetMaxJerkE() { HMI_value.axis = E_AXIS; SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[E_AXIS], UNITFDIGITS, planner.max_jerk[E_AXIS], ApplyMaxJerk); } + #endif +#endif + +void SetStepsX() { HMI_value.axis = X_AXIS, SetPFloatOnClick( MIN_STEP, MAX_STEP, UNITFDIGITS); } +void SetStepsY() { HMI_value.axis = Y_AXIS, SetPFloatOnClick( MIN_STEP, MAX_STEP, UNITFDIGITS); } +void SetStepsZ() { HMI_value.axis = Z_AXIS, SetPFloatOnClick( MIN_STEP, MAX_STEP, UNITFDIGITS); } +#if HAS_HOTEND + void SetStepsE() { HMI_value.axis = E_AXIS; SetPFloatOnClick( MIN_STEP, MAX_STEP, UNITFDIGITS); } + void SetHotendPidT() { SetPIntOnClick(MIN_ETEMP, MAX_ETEMP); } +#endif +#if HAS_HEATED_BED + void SetBedPidT() { SetPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); } +#endif + +#if HAS_HOTEND || HAS_HEATED_BED + void SetPidCycles() { SetPIntOnClick(3, 50); } + void SetKp() { SetPFloatOnClick(0, 1000, 2); } + void ApplyPIDi() { + *MenuData.P_Float = scalePID_i(MenuData.Value / POW(10, 2)); + thermalManager.updatePID(); + } + void ApplyPIDd() { + *MenuData.P_Float = scalePID_d(MenuData.Value / POW(10, 2)); + thermalManager.updatePID(); + } + void SetKi() { + MenuData.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; + const float value = unscalePID_i(*MenuData.P_Float); + SetFloatOnClick(0, 1000, 2, value, ApplyPIDi); + } + void SetKd() { + MenuData.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; + const float value = unscalePID_d(*MenuData.P_Float); + SetFloatOnClick(0, 1000, 2, value, ApplyPIDd); + } +#endif + +#if ENABLED(FWRETRACT) + void Return_FWRetract_Menu() { (PreviousMenu == FilSetMenu) ? Draw_FilSet_Menu() : Draw_Tune_Menu(); } + void SetRetractLength() { SetPFloatOnClick( 0, 10, UNITFDIGITS); } + void SetRetractSpeed() { SetPFloatOnClick( 1, 90, UNITFDIGITS); } + void SetZRaise() { SetPFloatOnClick( 0, 2, 2); } + void SetRecoverSpeed() { SetPFloatOnClick( 1, 90, UNITFDIGITS); } + void SetAddRecover() { SetPFloatOnClick(-5, 5, UNITFDIGITS); } +#endif + +// Special Menuitem Drawing functions ================================================= + +void onDrawBack(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 129, 72, 156, 84); + onDrawMenuItem(menuitem, line); +} + +void onDrawTempSubMenu(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 57, 104, 84, 116); + onDrawSubMenu(menuitem, line); +} + +void onDrawMotionSubMenu(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 87, 104, 114, 116); + onDrawSubMenu(menuitem, line); +} + +#if ENABLED(EEPROM_SETTINGS) + void onDrawWriteEeprom(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 117, 104, 172, 116); + onDrawMenuItem(menuitem, line); + } + + void onDrawReadEeprom(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 174, 103, 229, 116); + onDrawMenuItem(menuitem, line); + } + + void onDrawResetEeprom(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 1, 118, 56, 131); + onDrawMenuItem(menuitem, line); + } +#endif + +void onDrawInfoSubMenu(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 231, 104, 258, 116); + onDrawSubMenu(menuitem, line); +} + +void onDrawMoveX(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 58, 118, 106, 132); + onDrawPFloatMenu(menuitem, line); +} + +void onDrawMoveY(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 109, 118, 157, 132); + onDrawPFloatMenu(menuitem, line); +} + +void onDrawMoveZ(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 160, 118, 209, 132); + onDrawPFloatMenu(menuitem, line); +} + +#if HAS_HOTEND + void onDrawMoveE(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 212, 118, 253, 131); + onDrawPFloatMenu(menuitem, line); + } +#endif + +void onDrawMoveSubMenu(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 159, 70, 200, 84); + onDrawSubMenu(menuitem, line); +} + +void onDrawDisableMotors(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 204, 70, 259, 82); + onDrawMenuItem(menuitem, line); +} + +void onDrawAutoHome(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 0, 89, 41, 101); + onDrawMenuItem(menuitem, line); +} + +#if HAS_ZOFFSET_ITEM + #if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + void onDrawZOffset(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 174, 164, 223, 177); + onDrawPFloat2Menu(menuitem, line); + } + #else + void onDrawHomeOffset(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 43, 89, 98, 101); + onDrawMenuItem(menuitem, line); + } + #endif +#endif + +#if HAS_HOTEND + void onDrawPreheat1(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 100, 89, 151, 101); + onDrawMenuItem(menuitem, line); + } + #if PREHEAT_COUNT > 1 + void onDrawPreheat2(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 180, 89, 233, 100); + onDrawMenuItem(menuitem, line); + } + #endif +#endif + +#if HAS_PREHEAT + void onDrawCooldown(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 1, 104, 56, 117); + onDrawMenuItem(menuitem, line); + } +#endif + +void onDrawLanguage(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 239, 134, 266, 146); + onDrawMenuItem(menuitem, line); + DWINUI::Draw_String(VALX, MBASE(line), HMI_IsChinese() ? F("CN") : F("EN")); +} + +void onDrawSelColorItem(MenuItemClass* menuitem, int8_t line) { + const uint16_t color = *(uint16_t*)static_cast(menuitem)->value; + DWIN_Draw_Rectangle(0, HMI_data.Highlight_Color, ICOX + 1, MBASE(line) - 1 + 1, ICOX + 18, MBASE(line) - 1 + 18); + DWIN_Draw_Rectangle(1, color, ICOX + 2, MBASE(line) - 1 + 2, ICOX + 17, MBASE(line) - 1 + 17); + onDrawMenuItem(menuitem, line); +} + +void onDrawGetColorItem(MenuItemClass* menuitem, int8_t line) { + const uint8_t i = menuitem->icon; + uint16_t color; + switch (i) { + case 0: color = RGB(31, 0, 0); break; // Red + case 1: color = RGB(0, 63, 0); break; // Green + case 2: color = RGB(0, 0, 31); break; // Blue + default: color = 0; break; + } + DWIN_Draw_Rectangle(0, HMI_data.Highlight_Color, ICOX + 1, MBASE(line) - 1 + 1, ICOX + 18, MBASE(line) - 1 + 18); + DWIN_Draw_Rectangle(1, color, ICOX + 2, MBASE(line) - 1 + 2, ICOX + 17, MBASE(line) - 1 + 17); + DWINUI::Draw_String(LBLX, MBASE(line) - 1, menuitem->caption); + Draw_Menu_IntValue(HMI_data.Background_Color, line, 4, HMI_value.Color[i]); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); +} + + +void onDrawPIDi(MenuItemClass* menuitem, int8_t line) { onDrawFloatMenu(menuitem, line, 2, unscalePID_i(*(float*)static_cast(menuitem)->value)); } +void onDrawPIDd(MenuItemClass* menuitem, int8_t line) { onDrawFloatMenu(menuitem, line, 2, unscalePID_d(*(float*)static_cast(menuitem)->value)); } + +void onDrawSpeedItem(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 116, 164, 171, 176); + onDrawPIntMenu(menuitem, line); +} + +#if HAS_HOTEND + void onDrawHotendTemp(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 1, 134, 56, 146); + onDrawPIntMenu(menuitem, line); + } +#endif + +#if HAS_HEATED_BED + void onDrawBedTemp(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 58, 134, 113, 146); + onDrawPIntMenu(menuitem, line); + } +#endif + +#if HAS_FAN + void onDrawFanSpeed(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 115, 134, 170, 146); + onDrawPInt8Menu(menuitem, line); + } +#endif + +void onDrawSteps(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 153, 148, 194, 161); + onDrawSubMenu(menuitem, line); +} + +#if ENABLED(MESH_BED_LEVELING) + void onDrawMMeshMoveZ(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 160, 118, 209, 132); + onDrawPFloat2Menu(menuitem, line); + } +#endif + +#if HAS_PREHEAT + #if HAS_HOTEND + void onDrawSetPreheatHotend(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 1, 134, 56, 146); + onDrawPIntMenu(menuitem, line); + } + #endif + #if HAS_HEATED_BED + void onDrawSetPreheatBed(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 58, 134, 113, 146); + onDrawPIntMenu(menuitem, line); + } + #endif + #if HAS_FAN + void onDrawSetPreheatFan(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 115, 134, 170, 146); + onDrawPIntMenu(menuitem, line); + } + #endif + void onDrawPLAPreheatSubMenu(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 100, 89, 178, 101); + onDrawSubMenu(menuitem,line); + } + #if PREHEAT_COUNT >= 2 + void onDrawABSPreheatSubMenu(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) menuitem->SetFrame(1, 180, 89, 260, 100); + onDrawSubMenu(menuitem,line); + } + #endif +#endif // HAS_PREHEAT + +void onDrawSpeed(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) + menuitem->SetFrame(1, 173, 133, 228, 147); + onDrawSubMenu(menuitem, line); +} + +void onDrawMaxSpeedX(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 228, 147); + DWIN_Frame_AreaCopy(1, 229, 133, 236, 147, LBLX + 58, MBASE(line)); // X + } + onDrawPFloatMenu(menuitem, line); +} + +void onDrawMaxSpeedY(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 228, 147); + DWIN_Frame_AreaCopy(1, 1, 150, 7, 160, LBLX + 58, MBASE(line)); // Y + } + onDrawPFloatMenu(menuitem, line); +} + +void onDrawMaxSpeedZ(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 228, 147); + DWIN_Frame_AreaCopy(1, 9, 150, 16, 160, LBLX + 58, MBASE(line) + 3); // Z + } + onDrawPFloatMenu(menuitem, line); +} + +#if HAS_HOTEND + void onDrawMaxSpeedE(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 228, 147); + DWIN_Frame_AreaCopy(1, 18, 150, 25, 160, LBLX + 58, MBASE(line)); // E + } + onDrawPFloatMenu(menuitem, line); + } +#endif + +void onDrawAcc(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 28, 149, 69, 161, LBLX + 27, MBASE(line) + 1); // ...Acceleration + } + onDrawSubMenu(menuitem, line); +} + +void onDrawMaxAccelX(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 28, 149, 69, 161, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 229, 133, 236, 147, LBLX + 71, MBASE(line)); // X + } + onDrawPInt32Menu(menuitem, line); +} + +void onDrawMaxAccelY(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 28, 149, 69, 161, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 1, 150, 7, 160, LBLX + 71, MBASE(line)); // Y + } + onDrawPInt32Menu(menuitem, line); +} + +void onDrawMaxAccelZ(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 28, 149, 69, 161, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 9, 150, 16, 160, LBLX + 71, MBASE(line)); // Z + } + onDrawPInt32Menu(menuitem, line); +} + +#if HAS_HOTEND + void onDrawMaxAccelE(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 28, 149, 69, 161, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 18, 150, 25, 160, LBLX + 71, MBASE(line)); // E + } + onDrawPInt32Menu(menuitem, line); + } +#endif + +#if HAS_CLASSIC_JERK + + void onDrawJerk(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 1, 180, 28, 192, LBLX + 27, MBASE(line) + 1); // ... + DWIN_Frame_AreaCopy(1, 202, 133, 228, 147, LBLX + 54, MBASE(line)); // ...Jerk + } + onDrawSubMenu(menuitem, line); + } + + void onDrawMaxJerkX(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 1, 180, 28, 192, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 202, 133, 228, 147, LBLX + 53, MBASE(line)); + DWIN_Frame_AreaCopy(1, 229, 133, 236, 147, LBLX + 83, MBASE(line)); + } + onDrawPFloatMenu(menuitem, line); + } + + void onDrawMaxJerkY(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 1, 180, 28, 192, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 202, 133, 228, 147, LBLX + 53, MBASE(line)); + DWIN_Frame_AreaCopy(1, 1, 150, 7, 160, LBLX + 83, MBASE(line)); + } + onDrawPFloatMenu(menuitem, line); + } + + void onDrawMaxJerkZ(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 1, 180, 28, 192, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 202, 133, 228, 147, LBLX + 53, MBASE(line)); + DWIN_Frame_AreaCopy(1, 9, 150, 16, 160, LBLX + 83, MBASE(line)); + } + onDrawPFloatMenu(menuitem, line); + } + + #if HAS_HOTEND + void onDrawMaxJerkE(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 173, 133, 200, 147); + DWIN_Frame_AreaCopy(1, 1, 180, 28, 192, LBLX + 27, MBASE(line)); + DWIN_Frame_AreaCopy(1, 202, 133, 228, 147, LBLX + 53, MBASE(line)); + DWIN_Frame_AreaCopy(1, 18, 150, 25, 160, LBLX + 83, MBASE(line)); + } + onDrawPFloatMenu(menuitem, line); + } + #endif + +#endif // HAS_CLASSIC_JERK + +void onDrawStepsX(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 153, 148, 194, 161); + DWIN_Frame_AreaCopy(1, 229, 133, 236, 147, LBLX + 44, MBASE(line)); // X + } + onDrawPFloatMenu(menuitem, line); +} + +void onDrawStepsY(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 153, 148, 194, 161); + DWIN_Frame_AreaCopy(1, 1, 150, 7, 160, LBLX + 44, MBASE(line)); // Y + } + onDrawPFloatMenu(menuitem, line); +} + +void onDrawStepsZ(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 153, 148, 194, 161); + DWIN_Frame_AreaCopy(1, 9, 150, 16, 160, LBLX + 44, MBASE(line)); // Z + } + onDrawPFloatMenu(menuitem, line); +} + +#if HAS_HOTEND + void onDrawStepsE(MenuItemClass* menuitem, int8_t line) { + if (HMI_IsChinese()) { + menuitem->SetFrame(1, 153, 148, 194, 161); + DWIN_Frame_AreaCopy(1, 18, 150, 25, 160, LBLX + 44, MBASE(line)); // E + } + onDrawPFloatMenu(menuitem, line); + } +#endif + +#if HAS_ONESTEP_LEVELING + void onDrawManualTramming(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, HMI_data.FullManualTramming); } +#endif + +// Menu Creation and Drawing functions ====================================================== + +void SetMenuTitle(frame_rect_t cn, const __FlashStringHelper* fstr) { + if (HMI_IsChinese() && (cn.w != 0)) + CurrentMenu->MenuTitle.SetFrame(cn.x, cn.y, cn.w, cn.h); + else + CurrentMenu->MenuTitle.SetCaption(fstr); +} + +void Draw_Prepare_Menu() { + checkkey = Menu; + if (!PrepareMenu) PrepareMenu = new MenuClass(); + if (CurrentMenu != PrepareMenu) { + CurrentMenu = PrepareMenu; + SetMenuTitle({133, 1, 28, 13}, GET_TEXT_F(MSG_PREPARE)); + MenuItemsPrepare(13); + BACK_ITEM(Goto_Main_Menu); + #if ENABLED(ADVANCED_PAUSE_FEATURE) + MENU_ITEM_F(ICON_FilMan, MSG_FILAMENT_MAN, onDrawSubMenu, Draw_FilamentMan_Menu); + #endif + MENU_ITEM_F(ICON_Axis, MSG_MOVE_AXIS, onDrawMoveSubMenu, Goto_Move_Menu); + MENU_ITEM_F(ICON_Tram, MSG_BED_TRAMMING, onDrawSubMenu, Draw_Tramming_Menu); + MENU_ITEM_F(ICON_CloseMotor, MSG_DISABLE_STEPPERS, onDrawDisableMotors, DisableMotors); + #if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) + MENU_ITEM_F(ICON_Homing, MSG_HOMING, onDrawSubMenu, Draw_Homing_Menu); + #else + MENU_ITEM_F(ICON_Homing, MSG_AUTO_HOME, onDrawAutoHome, AutoHome); + #endif + #if ENABLED(MESH_BED_LEVELING) + MENU_ITEM_F(ICON_ManualMesh, MSG_MANUAL_MESH, onDrawSubMenu, Draw_ManualMesh_Menu); + #endif + #if HAS_ONESTEP_LEVELING + MENU_ITEM_F(ICON_Level, MSG_AUTO_MESH, onDrawMenuItem, AutoLev); + #endif + #if HAS_ZOFFSET_ITEM + #if ENABLED(BABYSTEP_ZPROBE_OFFSET) + MENU_ITEM_F(ICON_SetZOffset, MSG_PROBE_WIZARD, onDrawSubMenu, Draw_ZOffsetWiz_Menu); + #elif JUST_BABYSTEP + EDIT_ITEM_F(ICON_Zoffset, MSG_ZPROBE_ZOFFSET, onDrawPFloat2Menu, SetZOffset, &BABY_Z_VAR); + #else + MENU_ITEM_F(ICON_SetHome, MSG_SET_HOME_OFFSETS, onDrawHomeOffset, SetHome); + #endif + #endif + #if HAS_PREHEAT + MENU_ITEM_F(ICON_PLAPreheat, MSG_PREHEAT_1, onDrawPreheat1, DoPreheat0); + #if PREHEAT_COUNT > 1 + MENU_ITEM(ICON_ABSPreheat, F("Preheat " PREHEAT_2_LABEL), onDrawPreheat2, DoPreheat1); + #if PREHEAT_COUNT > 2 + MENU_ITEM(ICON_CustomPreheat, F("Preheat " PREHEAT_3_LABEL), onDrawMenuItem, DoPreheat2); + #endif + #endif + #endif + MENU_ITEM_F(ICON_Cool, MSG_COOLDOWN, onDrawCooldown, DoCoolDown); + MENU_ITEM_F(ICON_Language, MSG_UI_LANGUAGE, onDrawLanguage, SetLanguage); + } + ui.reset_status(true); + CurrentMenu->draw(); +} + +void Draw_Tramming_Menu() { + checkkey = Menu; + if (SetMenu(TrammingMenu, GET_TEXT_F(MSG_BED_TRAMMING), 8)) { + BACK_ITEM(Draw_Prepare_Menu); + #if HAS_BED_PROBE + MENU_ITEM_F(ICON_ProbeSet, MSG_TRAMMING_WIZARD, onDrawMenuItem, Trammingwizard); + EDIT_ITEM_F(ICON_ProbeSet, MSG_BED_TRAMMING_MANUAL, onDrawChkbMenu, SetManualTramming, &HMI_data.FullManualTramming); + #else + MENU_ITEM(ICON_MoveZ0, F("Home Z and disable"), onDrawMenuItem, HomeZandDisable); + #endif + MENU_ITEM_F(ICON_Axis, MSG_LEVBED_FL, onDrawMenuItem, TramFL); + MENU_ITEM_F(ICON_Axis, MSG_LEVBED_FR, onDrawMenuItem, TramFR); + MENU_ITEM_F(ICON_Axis, MSG_LEVBED_BR, onDrawMenuItem, TramBR); + MENU_ITEM_F(ICON_Axis, MSG_LEVBED_BL, onDrawMenuItem, TramBL); + MENU_ITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_C ), onDrawMenuItem, TramC ); + } + UpdateMenu(TrammingMenu); +} + +void Draw_Control_Menu() { + checkkey = Menu; + if (!ControlMenu) ControlMenu = new MenuClass(); + if (CurrentMenu != ControlMenu) { + CurrentMenu = ControlMenu; + SetMenuTitle({103, 1, 28, 14}, GET_TEXT_F(MSG_CONTROL)); + MenuItemsPrepare(10); + BACK_ITEM(Goto_Main_Menu); + MENU_ITEM_F(ICON_Temperature, MSG_TEMPERATURE, onDrawTempSubMenu, Draw_Temperature_Menu); + MENU_ITEM_F(ICON_Motion, MSG_MOTION, onDrawMotionSubMenu, Draw_Motion_Menu); + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM_F(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawWriteEeprom, WriteEeprom); + MENU_ITEM_F(ICON_ReadEEPROM, MSG_LOAD_EEPROM, onDrawReadEeprom, ReadEeprom); + MENU_ITEM_F(ICON_ResumeEEPROM, MSG_RESTORE_DEFAULTS, onDrawResetEeprom, ResetEeprom); + #endif + MENU_ITEM_F(ICON_Reboot, MSG_RESET_PRINTER, onDrawMenuItem, RebootPrinter); + #if ENABLED(CASE_LIGHT_MENU) + #if ENABLED(CASELIGHT_USES_BRIGHTNESS) + MENU_ITEM_F(ICON_CaseLight, MSG_CASE_LIGHT, onDrawSubMenu, Draw_CaseLight_Menu); + #else + MENU_ITEM_F(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, SetCaseLight, &caselight.on); + #endif + #endif + #if ENABLED(LED_CONTROL_MENU) + MENU_ITEM_F(ICON_LedControl, MSG_LED_CONTROL, onDrawSubMenu, Draw_LedControl_Menu); + #endif + MENU_ITEM_F(ICON_Info, MSG_INFO_SCREEN, onDrawInfoSubMenu, Goto_Info_Menu); + } + ui.reset_status(true); + CurrentMenu->draw(); +} + +void Draw_AdvancedSettings_Menu() { + checkkey = Menu; + if (SetMenu(AdvancedSettings, GET_TEXT_F(MSG_ADVANCED_SETTINGS), 20)) { + BACK_ITEM(Goto_Main_Menu); + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM_F(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawMenuItem, WriteEeprom); + #endif + #if HAS_BED_PROBE + MENU_ITEM_F(ICON_ProbeSet, MSG_ZPROBE_SETTINGS, onDrawSubMenu, Draw_ProbeSet_Menu); + #endif + #if HAS_MESH + MENU_ITEM_F(ICON_ProbeSet, MSG_MESH_LEVELING, onDrawSubMenu, Draw_MeshSet_Menu); + #endif + #if HAS_HOME_OFFSET + MENU_ITEM_F(ICON_HomeOffset, MSG_SET_HOME_OFFSETS, onDrawSubMenu, Draw_HomeOffset_Menu); + #endif + #if HAS_HOTEND + MENU_ITEM(ICON_PIDNozzle, F(STR_HOTEND_PID " Settings"), onDrawSubMenu, Draw_HotendPID_Menu); + #endif + #if HAS_HEATED_BED + MENU_ITEM(ICON_PIDbed, F(STR_BED_PID " Settings"), onDrawSubMenu, Draw_BedPID_Menu); + #endif + MENU_ITEM_F(ICON_FilSet, MSG_FILAMENT_SET, onDrawSubMenu, Draw_FilSet_Menu); + #if ENABLED(POWER_LOSS_RECOVERY) + EDIT_ITEM_F(ICON_Pwrlossr, MSG_OUTAGE_RECOVERY, onDrawChkbMenu, SetPwrLossr, &recovery.enabled); + #endif + #if ENABLED(BAUD_RATE_GCODE) + EDIT_ITEM(ICON_SetBaudRate, F("115K baud"), onDrawChkbMenu, SetBaudRate, &HMI_data.Baud115K); + #endif + #if HAS_LCD_BRIGHTNESS + EDIT_ITEM_F(ICON_Brightness, MSG_BRIGHTNESS, onDrawPInt8Menu, SetBrightness, &ui.brightness); + MENU_ITEM_F(ICON_Brightness, MSG_BRIGHTNESS_OFF, onDrawMenuItem, TurnOffBacklight); + #endif + MENU_ITEM_F(ICON_Scolor, MSG_COLORS_SELECT, onDrawSubMenu, Draw_SelectColors_Menu); + #if ENABLED(SOUND_MENU_ITEM) + EDIT_ITEM_F(ICON_Sound, MSG_SOUND_ENABLE, onDrawChkbMenu, SetEnableSound, &ui.sound_on); + #endif + #if HAS_ESDIAG + MENU_ITEM(ICON_ESDiag, F("End-stops diag."), onDrawSubMenu, Draw_EndStopDiag); + #endif + #if ENABLED(PRINTCOUNTER) + MENU_ITEM_F(ICON_PrintStats, MSG_INFO_STATS_MENU, onDrawSubMenu, Goto_PrintStats); + MENU_ITEM_F(ICON_PrintStatsReset, MSG_INFO_PRINT_COUNT_RESET, onDrawSubMenu, PrintStats.Reset); + #endif + #if HAS_LOCKSCREEN + MENU_ITEM_F(ICON_Lock, MSG_LOCKSCREEN, onDrawMenuItem, DWIN_LockScreen); + #endif + } + ui.reset_status(true); + UpdateMenu(AdvancedSettings); +} + +void Draw_Move_Menu() { + checkkey = Menu; + if (!MoveMenu) MoveMenu = new MenuClass(); + if (CurrentMenu != MoveMenu) { + CurrentMenu = MoveMenu; + SetMenuTitle({192, 1, 42, 14}, GET_TEXT_F(MSG_MOVE_AXIS)); + MenuItemsPrepare(5); + BACK_ITEM(Draw_Prepare_Menu); + EDIT_ITEM_F(ICON_MoveX, MSG_MOVE_X, onDrawMoveX, SetMoveX, ¤t_position.x); + EDIT_ITEM_F(ICON_MoveY, MSG_MOVE_Y, onDrawMoveY, SetMoveY, ¤t_position.y); + EDIT_ITEM_F(ICON_MoveZ, MSG_MOVE_Z, onDrawMoveZ, SetMoveZ, ¤t_position.z); + #if HAS_HOTEND + EDIT_ITEM_F(ICON_Extruder, MSG_MOVE_E, onDrawMoveE, SetMoveE, ¤t_position.e); + #endif + } + CurrentMenu->draw(); + if (!all_axes_trusted()) LCD_MESSAGE_F("WARNING: Current position unknown. Home axes."); +} + +#if HAS_HOME_OFFSET + void Draw_HomeOffset_Menu() { + checkkey = Menu; + if (SetMenu(HomeOffMenu, GET_TEXT_F(MSG_SET_HOME_OFFSETS), 4)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + EDIT_ITEM_F(ICON_HomeOffsetX, MSG_HOME_OFFSET_X, onDrawPFloatMenu, SetHomeOffsetX, &home_offset.x); + EDIT_ITEM_F(ICON_HomeOffsetY, MSG_HOME_OFFSET_Y, onDrawPFloatMenu, SetHomeOffsetY, &home_offset.y); + EDIT_ITEM_F(ICON_HomeOffsetZ, MSG_HOME_OFFSET_Z, onDrawPFloatMenu, SetHomeOffsetZ, &home_offset.z); + } + UpdateMenu(HomeOffMenu); + } +#endif + +#if HAS_BED_PROBE + void Draw_ProbeSet_Menu() { + checkkey = Menu; + if (SetMenu(ProbeSetMenu, GET_TEXT_F(MSG_ZPROBE_SETTINGS), 8)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + EDIT_ITEM_F(ICON_ProbeOffsetX, MSG_ZPROBE_XOFFSET, onDrawPFloatMenu, SetProbeOffsetX, &probe.offset.x); + EDIT_ITEM_F(ICON_ProbeOffsetY, MSG_ZPROBE_YOFFSET, onDrawPFloatMenu, SetProbeOffsetY, &probe.offset.y); + EDIT_ITEM_F(ICON_ProbeOffsetZ, MSG_ZPROBE_ZOFFSET, onDrawPFloat2Menu, SetProbeOffsetZ, &probe.offset.z); + #if ENABLED(BLTOUCH) + MENU_ITEM_F(ICON_ProbeStow, MSG_MANUAL_STOW, onDrawMenuItem, ProbeStow); + MENU_ITEM_F(ICON_ProbeDeploy, MSG_MANUAL_DEPLOY, onDrawMenuItem, ProbeDeploy); + MENU_ITEM_F(ICON_BltouchReset, MSG_BLTOUCH_RESET, onDrawMenuItem, bltouch._reset); + #ifdef BLTOUCH_HS_MODE + EDIT_ITEM_F(ICON_HSMode, MSG_ENABLE_HS_MODE, onDrawChkbMenu, SetHSMode, &bltouch.high_speed_mode); + #endif + #endif + MENU_ITEM_F(ICON_ProbeTest, MSG_M48_TEST, onDrawMenuItem, ProbeTest); + } + UpdateMenu(ProbeSetMenu); + } + +#endif + +void Draw_FilSet_Menu() { + checkkey = Menu; + if (SetMenu(FilSetMenu, GET_TEXT_F(MSG_FILAMENT_SET), 9)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + #if HAS_FILAMENT_SENSOR + EDIT_ITEM_F(ICON_Runout, MSG_RUNOUT_ENABLE, onDrawChkbMenu, SetRunoutEnable, &runout.enabled); + #endif + #if HAS_FILAMENT_RUNOUT_DISTANCE + EDIT_ITEM_F(ICON_Runout, MSG_RUNOUT_DISTANCE_MM, onDrawPFloatMenu, SetRunoutDistance, &runout.runout_distance()); + #endif + #if ENABLED(PREVENT_COLD_EXTRUSION) + EDIT_ITEM_F(ICON_ExtrudeMinT, MSG_EXTRUDER_MIN_TEMP, onDrawPIntMenu, SetExtMinT, &HMI_data.ExtMinT); + #endif + #if ENABLED(ADVANCED_PAUSE_FEATURE) + EDIT_ITEM_F(ICON_FilLoad, MSG_FILAMENT_LOAD, onDrawPFloatMenu, SetFilLoad, &fc_settings[0].load_length); + EDIT_ITEM_F(ICON_FilUnload, MSG_FILAMENT_UNLOAD, onDrawPFloatMenu, SetFilUnload, &fc_settings[0].unload_length); + #endif + #if ENABLED(FWRETRACT) + MENU_ITEM_F(ICON_FWRetract, MSG_FWRETRACT, onDrawSubMenu, Draw_FWRetract_Menu); + #endif + } + UpdateMenu(FilSetMenu); +} + +void Draw_SelectColors_Menu() { + checkkey = Menu; + if (SetMenu(SelectColorMenu, GET_TEXT_F(MSG_COLORS_SELECT), 20)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + MENU_ITEM_F(ICON_StockConfiguration, MSG_RESTORE_DEFAULTS, onDrawMenuItem, RestoreDefaultsColors); + EDIT_ITEM(0, F("Screen Background"), onDrawSelColorItem, SelColor, &HMI_data.Background_Color); + EDIT_ITEM(0, F("Cursor"), onDrawSelColorItem, SelColor, &HMI_data.Cursor_color); + EDIT_ITEM(0, F("Title Background"), onDrawSelColorItem, SelColor, &HMI_data.TitleBg_color); + EDIT_ITEM(0, F("Title Text"), onDrawSelColorItem, SelColor, &HMI_data.TitleTxt_color); + EDIT_ITEM(0, F("Text"), onDrawSelColorItem, SelColor, &HMI_data.Text_Color); + EDIT_ITEM(0, F("Selected"), onDrawSelColorItem, SelColor, &HMI_data.Selected_Color); + EDIT_ITEM(0, F("Split Line"), onDrawSelColorItem, SelColor, &HMI_data.SplitLine_Color); + EDIT_ITEM(0, F("Highlight"), onDrawSelColorItem, SelColor, &HMI_data.Highlight_Color); + EDIT_ITEM(0, F("Status Background"), onDrawSelColorItem, SelColor, &HMI_data.StatusBg_Color); + EDIT_ITEM(0, F("Status Text"), onDrawSelColorItem, SelColor, &HMI_data.StatusTxt_Color); + EDIT_ITEM(0, F("Popup Background"), onDrawSelColorItem, SelColor, &HMI_data.PopupBg_color); + EDIT_ITEM(0, F("Popup Text"), onDrawSelColorItem, SelColor, &HMI_data.PopupTxt_Color); + EDIT_ITEM(0, F("Alert Background"), onDrawSelColorItem, SelColor, &HMI_data.AlertBg_Color); + EDIT_ITEM(0, F("Alert Text"), onDrawSelColorItem, SelColor, &HMI_data.AlertTxt_Color); + EDIT_ITEM(0, F("Percent Text"), onDrawSelColorItem, SelColor, &HMI_data.PercentTxt_Color); + EDIT_ITEM(0, F("Bar Fill"), onDrawSelColorItem, SelColor, &HMI_data.Barfill_Color); + EDIT_ITEM(0, F("Indicator value"), onDrawSelColorItem, SelColor, &HMI_data.Indicator_Color); + EDIT_ITEM(0, F("Coordinate value"), onDrawSelColorItem, SelColor, &HMI_data.Coordinate_Color); + } + UpdateMenu(SelectColorMenu); +} + +void Draw_GetColor_Menu() { + checkkey = Menu; + if (SetMenu(GetColorMenu, GET_TEXT_F(MSG_COLORS_GET), 5)) { + BACK_ITEM(DWIN_ApplyColor); + MENU_ITEM_F(ICON_Cancel, MSG_BUTTON_CANCEL, onDrawMenuItem, Draw_SelectColors_Menu); + MENU_ITEM_F(0, MSG_COLORS_RED, onDrawGetColorItem, SetRGBColor); + MENU_ITEM_F(1, MSG_COLORS_GREEN, onDrawGetColorItem, SetRGBColor); + MENU_ITEM_F(2, MSG_COLORS_BLUE, onDrawGetColorItem, SetRGBColor); + } + UpdateMenu(GetColorMenu); + DWIN_Draw_Rectangle(1, *MenuData.P_Int, 20, 315, DWIN_WIDTH - 20, 335); +} + +#if BOTH(CASE_LIGHT_MENU, CASELIGHT_USES_BRIGHTNESS) + void Draw_CaseLight_Menu() { + checkkey = Menu; + if (SetMenu(CaseLightMenu, GET_TEXT_F(MSG_CASE_LIGHT), 3)) { + BACK_ITEM(Draw_Control_Menu); + EDIT_ITEM_F(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, SetCaseLight, &caselight.on); + EDIT_ITEM_F(ICON_Brightness, MSG_CASE_LIGHT_BRIGHTNESS, onDrawPInt8Menu, SetCaseLightBrightness, &caselight.brightness); + } + UpdateMenu(CaseLightMenu); + } +#endif + +#if ENABLED(LED_CONTROL_MENU) + void Draw_LedControl_Menu() { + checkkey = Menu; + if (SetMenu(LedControlMenu, GET_TEXT_F(MSG_LED_CONTROL), 6)) { + BACK_ITEM(Draw_Control_Menu); + #if !BOTH(CASE_LIGHT_MENU, CASE_LIGHT_USE_NEOPIXEL) + EDIT_ITEM_F(ICON_LedControl, MSG_LEDS, onDrawChkbMenu, SetLedStatus, &leds.lights_on); + #endif + #if HAS_COLOR_LEDS + #if ENABLED(LED_COLOR_PRESETS) + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_WHITE, onDrawMenuItem, leds.set_white); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_RED, onDrawMenuItem, leds.set_red); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_ORANGE, onDrawMenuItem, leds.set_orange); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_YELLOW, onDrawMenuItem, leds.set_yellow); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_GREEN, onDrawMenuItem, leds.set_green); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_BLUE, onDrawMenuItem, leds.set_blue); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_INDIGO, onDrawMenuItem, leds.set_indigo); + MENU_ITEM_F(ICON_LedControl, MSG_SET_LEDS_VIOLET, onDrawMenuItem, leds.set_violet); + #else + EDIT_ITEM_F(ICON_LedControl, MSG_COLORS_RED, onDrawPInt8Menu, SetLEDColorR, &leds.color.r); + EDIT_ITEM_F(ICON_LedControl, MSG_COLORS_GREEN, onDrawPInt8Menu, SetLEDColorG, &leds.color.g); + EDIT_ITEM_F(ICON_LedControl, MSG_COLORS_BLUE, onDrawPInt8Menu, SetLEDColorB, &leds.color.b); + #if ENABLED(HAS_WHITE_LED) + EDIT_ITEM_F(ICON_LedControl, MSG_COLORS_WHITE, onDrawPInt8Menu, SetLEDColorW, &leds.color.w); + #endif + #endif + #endif + } + UpdateMenu(LedControlMenu); + } +#endif + +void Draw_Tune_Menu() { + checkkey = Menu; + if (!TuneMenu) TuneMenu = new MenuClass(); + if (CurrentMenu != TuneMenu) { + CurrentMenu = TuneMenu; + SetMenuTitle({73, 2, 28, 12}, GET_TEXT_F(MSG_TUNE)); // TODO: Chinese, English "Tune" JPG + MenuItemsPrepare(16); + BACK_ITEM(Goto_PrintProcess); + EDIT_ITEM_F(ICON_Speed, MSG_SPEED, onDrawSpeedItem, SetSpeed, &feedrate_percentage); + #if HAS_HOTEND + HotendTargetItem = EDIT_ITEM_F(ICON_HotendTemp, MSG_UBL_SET_TEMP_HOTEND, onDrawHotendTemp, SetHotendTemp, &thermalManager.temp_hotend[0].target); + #endif + #if HAS_HEATED_BED + BedTargetItem = EDIT_ITEM_F(ICON_BedTemp, MSG_UBL_SET_TEMP_BED, onDrawBedTemp, SetBedTemp, &thermalManager.temp_bed.target); + #endif + #if HAS_FAN + FanSpeedItem = EDIT_ITEM_F(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, SetFanSpeed, &thermalManager.fan_speed[0]); + #endif + #if HAS_ZOFFSET_ITEM && EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + EDIT_ITEM_F(ICON_Zoffset, MSG_ZPROBE_ZOFFSET, onDrawZOffset, SetZOffset, &BABY_Z_VAR); + #endif + EDIT_ITEM_F(ICON_Flow, MSG_FLOW, onDrawPIntMenu, SetFlow, &planner.flow_percentage[0]); + #if ENABLED(ADVANCED_PAUSE_FEATURE) + MENU_ITEM_F(ICON_FilMan, MSG_FILAMENTCHANGE, onDrawMenuItem, ChangeFilament); + #endif + #if ENABLED(FWRETRACT) + MENU_ITEM_F(ICON_FWRetract, MSG_FWRETRACT, onDrawSubMenu, Draw_FWRetract_Menu); + #endif + #if HAS_LOCKSCREEN + MENU_ITEM_F(ICON_Lock, MSG_LOCKSCREEN, onDrawMenuItem, DWIN_LockScreen); + #endif + #if HAS_LCD_BRIGHTNESS + EDIT_ITEM_F(ICON_Brightness, MSG_BRIGHTNESS, onDrawPInt8Menu, SetBrightness, &ui.brightness); + MENU_ITEM_F(ICON_Brightness, MSG_BRIGHTNESS_OFF, onDrawMenuItem, TurnOffBacklight); + #endif + #if ENABLED(CASE_LIGHT_MENU) + EDIT_ITEM_F(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, SetCaseLight, &caselight.on); + #elif ENABLED(LED_CONTROL_MENU) && DISABLED(CASE_LIGHT_USE_NEOPIXEL) + EDIT_ITEM_F(ICON_LedControl, MSG_LEDS, onDrawChkbMenu, SetLedStatus, &leds.lights_on); + #endif + } + CurrentMenu->draw(); +} + +void Draw_Motion_Menu() { + checkkey = Menu; + if (!MotionMenu) MotionMenu = new MenuClass(); + if (CurrentMenu != MotionMenu) { + CurrentMenu = MotionMenu; + SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_MOTION)); // TODO: Chinese, English "Motion" JPG + MenuItemsPrepare(6); + BACK_ITEM(Draw_Control_Menu); + MENU_ITEM_F(ICON_MaxSpeed, MSG_SPEED, onDrawSpeed, Draw_MaxSpeed_Menu); + MENU_ITEM_F(ICON_MaxAccelerated, MSG_ACCELERATION, onDrawAcc, Draw_MaxAccel_Menu); + #if HAS_CLASSIC_JERK + MENU_ITEM_F(ICON_MaxJerk, MSG_JERK, onDrawJerk, Draw_MaxJerk_Menu); + #endif + MENU_ITEM_F(ICON_Step, MSG_STEPS_PER_MM, onDrawSteps, Draw_Steps_Menu); + EDIT_ITEM_F(ICON_Flow, MSG_FLOW, onDrawPIntMenu, SetFlow, &planner.flow_percentage[0]); + } + CurrentMenu->draw(); +} + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + void Draw_FilamentMan_Menu() { + checkkey = Menu; + if (SetMenu(FilamentMenu, GET_TEXT_F(MSG_FILAMENT_MAN), 5)) { + BACK_ITEM(Draw_Prepare_Menu); + MENU_ITEM_F(ICON_Park, MSG_FILAMENT_PARK_ENABLED, onDrawMenuItem, ParkHead); + MENU_ITEM_F(ICON_FilMan, MSG_FILAMENTCHANGE, onDrawMenuItem, ChangeFilament); + #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + MENU_ITEM_F(ICON_FilUnload, MSG_FILAMENTUNLOAD, onDrawMenuItem, UnloadFilament); + MENU_ITEM_F(ICON_FilLoad, MSG_FILAMENTLOAD, onDrawMenuItem, LoadFilament); + #endif + } + UpdateMenu(FilamentMenu); + } +#endif + +#if ENABLED(MESH_BED_LEVELING) + void Draw_ManualMesh_Menu() { + checkkey = Menu; + if (SetMenu(ManualMesh, GET_TEXT_F(MSG_UBL_MANUAL_MESH), 6)) { + BACK_ITEM(Draw_Prepare_Menu); + MENU_ITEM_F(ICON_ManualMesh, MSG_LEVEL_BED, onDrawMenuItem, ManualMeshStart); + MMeshMoveZItem = EDIT_ITEM_F(ICON_Zoffset, MSG_MOVE_Z, onDrawMMeshMoveZ, SetMMeshMoveZ, ¤t_position.z); + MENU_ITEM_F(ICON_Axis, MSG_UBL_CONTINUE_MESH, onDrawMenuItem, ManualMeshContinue); + MENU_ITEM_F(ICON_MeshViewer, MSG_MESH_VIEW, onDrawSubMenu, DWIN_MeshViewer); + MENU_ITEM_F(ICON_MeshSave, MSG_UBL_SAVE_MESH, onDrawMenuItem, ManualMeshSave); + } + UpdateMenu(ManualMesh); + } +#endif + +#if HAS_PREHEAT + + void Draw_Preheat_Menu(frame_rect_t cn, const __FlashStringHelper* fstr) { + checkkey = Menu; + if (CurrentMenu != PreheatMenu) { + CurrentMenu = PreheatMenu; + SetMenuTitle(cn, fstr); + MenuItemsPrepare(5); + BACK_ITEM(Draw_Temperature_Menu); + #if HAS_HOTEND + EDIT_ITEM_F(ICON_SetEndTemp, MSG_UBL_SET_TEMP_HOTEND, onDrawSetPreheatHotend, SetPreheatEndTemp, &ui.material_preset[HMI_value.Select].hotend_temp); + #endif + #if HAS_HEATED_BED + EDIT_ITEM_F(ICON_SetBedTemp, MSG_UBL_SET_TEMP_BED, onDrawSetPreheatBed, SetPreheatBedTemp, &ui.material_preset[HMI_value.Select].bed_temp); + #endif + #if HAS_FAN + EDIT_ITEM_F(ICON_FanSpeed, MSG_FAN_SPEED, onDrawSetPreheatFan, SetPreheatFanSpeed, &ui.material_preset[HMI_value.Select].fan_speed); + #endif + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM_F(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawWriteEeprom, WriteEeprom); + #endif + } + CurrentMenu->draw(); + } + + void Draw_Preheat1_Menu() { + HMI_value.Select = 0; + if (!PreheatMenu) PreheatMenu = new MenuClass(); + Draw_Preheat_Menu({59, 16, 81, 14}, F(PREHEAT_1_LABEL " Preheat Settings")); // TODO: English "PLA Settings" JPG + } + + #if PREHEAT_COUNT >= 2 + void Draw_Preheat2_Menu() { + HMI_value.Select = 1; + if (!PreheatMenu) PreheatMenu = new MenuClass(); + Draw_Preheat_Menu({142, 16, 82, 14}, F(PREHEAT_2_LABEL " Preheat Settings")); // TODO: English "ABS Settings" JPG + } + #endif + + #if PREHEAT_COUNT >= 3 + void Draw_Preheat3_Menu() { + HMI_value.Select = 2; + if (!PreheatMenu) PreheatMenu = new MenuClass(); + Draw_Preheat_Menu({225, 16, 82, 14}, F(PREHEAT_3_LABEL " Preheat Settings")); // TODO: English "... Settings" JPG + } + #endif + +#endif // HAS_PREHEAT + +void Draw_Temperature_Menu() { + checkkey = Menu; + if (!TemperatureMenu) TemperatureMenu = new MenuClass(); + if (CurrentMenu != TemperatureMenu) { + CurrentMenu = TemperatureMenu; + SetMenuTitle({236, 2, 28, 12}, GET_TEXT_F(MSG_TEMPERATURE)); + MenuItemsPrepare(7); + BACK_ITEM(Draw_Control_Menu); + #if HAS_HOTEND + HotendTargetItem = EDIT_ITEM_F(ICON_SetEndTemp, MSG_UBL_SET_TEMP_HOTEND, onDrawHotendTemp, SetHotendTemp, &thermalManager.temp_hotend[0].target); + #endif + #if HAS_HEATED_BED + BedTargetItem = EDIT_ITEM_F(ICON_SetBedTemp, MSG_UBL_SET_TEMP_BED, onDrawBedTemp, SetBedTemp, &thermalManager.temp_bed.target); + #endif + #if HAS_FAN + FanSpeedItem = EDIT_ITEM_F(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, SetFanSpeed, &thermalManager.fan_speed[0]); + #endif + #if HAS_PREHEAT + MENU_ITEM_F(ICON_SetPLAPreheat, MSG_PREHEAT_1_SETTINGS, onDrawPLAPreheatSubMenu, Draw_Preheat1_Menu); + #if PREHEAT_COUNT >= 2 + MENU_ITEM_F(ICON_SetABSPreheat, MSG_PREHEAT_2_SETTINGS, onDrawABSPreheatSubMenu, Draw_Preheat2_Menu); + #if PREHEAT_COUNT >= 3 + MENU_ITEM_F(ICON_SetCustomPreheat, MSG_PREHEAT_3_SETTINGS, onDrawSubMenu, Draw_Preheat3_Menu); + #endif + #endif + #endif + } + CurrentMenu->draw(); +} + +void Draw_MaxSpeed_Menu() { + checkkey = Menu; + if (!MaxSpeedMenu) MaxSpeedMenu = new MenuClass(); + if (CurrentMenu != MaxSpeedMenu) { + CurrentMenu = MaxSpeedMenu; + SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_MAX_SPEED)); + MenuItemsPrepare(5); + BACK_ITEM(Draw_Motion_Menu); + EDIT_ITEM_F(ICON_MaxSpeedX, MSG_VMAX_A, onDrawMaxSpeedX, SetMaxSpeedX, &planner.settings.max_feedrate_mm_s[X_AXIS]); + EDIT_ITEM_F(ICON_MaxSpeedY, MSG_VMAX_B, onDrawMaxSpeedY, SetMaxSpeedY, &planner.settings.max_feedrate_mm_s[Y_AXIS]); + EDIT_ITEM_F(ICON_MaxSpeedZ, MSG_VMAX_C, onDrawMaxSpeedZ, SetMaxSpeedZ, &planner.settings.max_feedrate_mm_s[Z_AXIS]); + #if HAS_HOTEND + EDIT_ITEM_F(ICON_MaxSpeedE, MSG_VMAX_E, onDrawMaxSpeedE, SetMaxSpeedE, &planner.settings.max_feedrate_mm_s[E_AXIS]); + #endif + } + CurrentMenu->draw(); +} + +void Draw_MaxAccel_Menu() { + checkkey = Menu; + if (!MaxAccelMenu) MaxAccelMenu = new MenuClass(); + if (CurrentMenu != MaxAccelMenu) { + CurrentMenu = MaxAccelMenu; + SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_ACCELERATION)); + MenuItemsPrepare(5); + BACK_ITEM(Draw_Motion_Menu); + EDIT_ITEM_F(ICON_MaxAccX, MSG_AMAX_A, onDrawMaxAccelX, SetMaxAccelX, &planner.settings.max_acceleration_mm_per_s2[X_AXIS]); + EDIT_ITEM_F(ICON_MaxAccY, MSG_AMAX_B, onDrawMaxAccelY, SetMaxAccelY, &planner.settings.max_acceleration_mm_per_s2[Y_AXIS]); + EDIT_ITEM_F(ICON_MaxAccZ, MSG_AMAX_C, onDrawMaxAccelZ, SetMaxAccelZ, &planner.settings.max_acceleration_mm_per_s2[Z_AXIS]); + #if HAS_HOTEND + EDIT_ITEM_F(ICON_MaxAccE, MSG_AMAX_E, onDrawMaxAccelE, SetMaxAccelE, &planner.settings.max_acceleration_mm_per_s2[E_AXIS]); + #endif + } + CurrentMenu->draw(); +} + +#if HAS_CLASSIC_JERK + void Draw_MaxJerk_Menu() { + checkkey = Menu; + if (!MaxJerkMenu) MaxJerkMenu = new MenuClass(); + if (CurrentMenu != MaxJerkMenu) { + CurrentMenu = MaxJerkMenu; + SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_JERK)); + MenuItemsPrepare(5); + BACK_ITEM(Draw_Motion_Menu); + EDIT_ITEM_F(ICON_MaxSpeedJerkX, MSG_VA_JERK, onDrawMaxJerkX, SetMaxJerkX, &planner.max_jerk[X_AXIS]); + EDIT_ITEM_F(ICON_MaxSpeedJerkY, MSG_VB_JERK, onDrawMaxJerkY, SetMaxJerkY, &planner.max_jerk[Y_AXIS]); + EDIT_ITEM_F(ICON_MaxSpeedJerkZ, MSG_VC_JERK, onDrawMaxJerkZ, SetMaxJerkZ, &planner.max_jerk[Z_AXIS]); + #if HAS_HOTEND + EDIT_ITEM_F(ICON_MaxSpeedJerkE, MSG_VE_JERK, onDrawMaxJerkE, SetMaxJerkE, &planner.max_jerk[E_AXIS]); + #endif + } + CurrentMenu->draw(); + } +#endif + +void Draw_Steps_Menu() { + checkkey = Menu; + if (!StepsMenu) StepsMenu = new MenuClass(); + if (CurrentMenu != StepsMenu) { + CurrentMenu = StepsMenu; + SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_STEPS_PER_MM)); + MenuItemsPrepare(5); + BACK_ITEM(Draw_Motion_Menu); + EDIT_ITEM_F(ICON_StepX, MSG_A_STEPS, onDrawStepsX, SetStepsX, &planner.settings.axis_steps_per_mm[X_AXIS]); + EDIT_ITEM_F(ICON_StepY, MSG_B_STEPS, onDrawStepsY, SetStepsY, &planner.settings.axis_steps_per_mm[Y_AXIS]); + EDIT_ITEM_F(ICON_StepZ, MSG_C_STEPS, onDrawStepsZ, SetStepsZ, &planner.settings.axis_steps_per_mm[Z_AXIS]); + #if HAS_HOTEND + EDIT_ITEM_F(ICON_StepE, MSG_E_STEPS, onDrawStepsE, SetStepsE, &planner.settings.axis_steps_per_mm[E_AXIS]); + #endif + } + CurrentMenu->draw(); +} + +#if HAS_HOTEND + void Draw_HotendPID_Menu() { + checkkey = Menu; + if (SetMenu(HotendPIDMenu, F(STR_HOTEND_PID " Settings"),8)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + MENU_ITEM(ICON_PIDNozzle, F(STR_HOTEND_PID), onDrawMenuItem, HotendPID); + EDIT_ITEM(ICON_PIDValue, F("Set" STR_KP), onDrawPFloat2Menu, SetKp, &thermalManager.temp_hotend[0].pid.Kp); + EDIT_ITEM(ICON_PIDValue, F("Set" STR_KI), onDrawPIDi, SetKi, &thermalManager.temp_hotend[0].pid.Ki); + EDIT_ITEM(ICON_PIDValue, F("Set" STR_KD), onDrawPIDd, SetKd, &thermalManager.temp_hotend[0].pid.Kd); + EDIT_ITEM_F(ICON_Temperature, MSG_TEMPERATURE, onDrawPIntMenu, SetHotendPidT, &HMI_data.HotendPidT); + EDIT_ITEM_F(ICON_PIDcycles, MSG_PID_CYCLE, onDrawPIntMenu, SetPidCycles, &HMI_data.PidCycles); + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM_F(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawMenuItem, WriteEeprom); + #endif + } + UpdateMenu(HotendPIDMenu); + } +#endif + +#if HAS_HEATED_BED + void Draw_BedPID_Menu() { + checkkey = Menu; + if (SetMenu(BedPIDMenu, F(STR_BED_PID " Settings"),8)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + MENU_ITEM(ICON_PIDNozzle, F(STR_BED_PID), onDrawMenuItem,BedPID); + EDIT_ITEM(ICON_PIDValue, F("Set" STR_KP), onDrawPFloat2Menu, SetKp, &thermalManager.temp_bed.pid.Kp); + EDIT_ITEM(ICON_PIDValue, F("Set" STR_KI), onDrawPIDi, SetKi, &thermalManager.temp_bed.pid.Ki); + EDIT_ITEM(ICON_PIDValue, F("Set" STR_KD), onDrawPIDd, SetKd, &thermalManager.temp_bed.pid.Kd); + EDIT_ITEM_F(ICON_Temperature, MSG_TEMPERATURE, onDrawPIntMenu, SetBedPidT, &HMI_data.BedPidT); + EDIT_ITEM_F(ICON_PIDcycles, MSG_PID_CYCLE, onDrawPIntMenu, SetPidCycles, &HMI_data.PidCycles); + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM_F(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawMenuItem, WriteEeprom); + #endif + } + UpdateMenu(BedPIDMenu); + } +#endif + +#if ENABLED(BABYSTEP_ZPROBE_OFFSET) + void Draw_ZOffsetWiz_Menu() { + checkkey = Menu; + if (SetMenu(ZOffsetWizMenu, GET_TEXT_F(MSG_PROBE_WIZARD), 4)) { + BACK_ITEM(Draw_Prepare_Menu); + MENU_ITEM_F(ICON_Homing, MSG_AUTO_HOME, onDrawMenuItem, AutoHome); + MENU_ITEM(ICON_MoveZ0, F("Move Z to Home"), onDrawMenuItem, SetMoveZto0); + EDIT_ITEM_F(ICON_Zoffset, MSG_ZPROBE_ZOFFSET, onDrawPFloat2Menu, SetZOffset, &BABY_Z_VAR); + } + UpdateMenu(ZOffsetWizMenu); + if (!axis_is_trusted(Z_AXIS)) LCD_MESSAGE_F("WARNING: Z position unknown, move Z to home"); + } +#endif + +#if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) + void Draw_Homing_Menu() { + checkkey = Menu; + if (SetMenu(HomingMenu, GET_TEXT_F(MSG_HOMING), 5)) { + BACK_ITEM(Draw_Prepare_Menu); + MENU_ITEM_F(ICON_Homing, MSG_AUTO_HOME, onDrawMenuItem, AutoHome); + MENU_ITEM_F(ICON_HomeX, MSG_AUTO_HOME_X, onDrawMenuItem, HomeX); + MENU_ITEM_F(ICON_HomeY, MSG_AUTO_HOME_Y, onDrawMenuItem, HomeY); + MENU_ITEM_F(ICON_HomeZ, MSG_AUTO_HOME_Z, onDrawMenuItem, HomeZ); + } + UpdateMenu(HomingMenu); + } +#endif + +#if ENABLED(FWRETRACT) + void Draw_FWRetract_Menu() { + checkkey = Menu; + if (SetMenu(FWRetractMenu, GET_TEXT_F(MSG_FWRETRACT), 6)) { + BACK_ITEM(Return_FWRetract_Menu); + EDIT_ITEM_F(ICON_FWRetLength, MSG_CONTROL_RETRACT, onDrawPFloatMenu, SetRetractLength, &fwretract.settings.retract_length); + EDIT_ITEM_F(ICON_FWRetSpeed, MSG_SINGLENOZZLE_RETRACT_SPEED, onDrawPFloatMenu, SetRetractSpeed, &fwretract.settings.retract_feedrate_mm_s); + EDIT_ITEM_F(ICON_FWRetZRaise, MSG_CONTROL_RETRACT_ZHOP, onDrawPFloat2Menu, SetZRaise, &fwretract.settings.retract_zraise); + EDIT_ITEM_F(ICON_FWRecSpeed, MSG_SINGLENOZZLE_UNRETRACT_SPEED, onDrawPFloatMenu, SetRecoverSpeed, &fwretract.settings.retract_recover_feedrate_mm_s); + EDIT_ITEM_F(ICON_FWRecExtra, MSG_CONTROL_RETRACT_RECOVER, onDrawPFloatMenu, SetAddRecover, &fwretract.settings.retract_recover_extra); + } + UpdateMenu(FWRetractMenu); + } +#endif + +//============================================================================= +// Mesh Bed Leveling +//============================================================================= + +#if HAS_MESH + + void ApplyMeshFadeHeight() { set_z_fade_height(planner.z_fade_height); } + void SetMeshFadeHeight() { SetPFloatOnClick(0, 100, 1, ApplyMeshFadeHeight); } + + void SetMeshActive() { + set_bed_leveling_enabled(!planner.leveling_active); + Draw_Chkb_Line(CurrentMenu->line(), planner.leveling_active); + DWIN_UpdateLCD(); + } + + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + void SetBedLevT() { SetPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); } + #endif + + #if ENABLED(MESH_EDIT_MENU) + #define Z_OFFSET_MIN -3 + #define Z_OFFSET_MAX 3 + + void LiveEditMesh() { ((MenuItemPtrClass*)EditZValueItem)->value = &bedlevel.z_values[HMI_value.Select ? BedLevelTools.mesh_x : MenuData.Value][HMI_value.Select ? MenuData.Value : BedLevelTools.mesh_y]; EditZValueItem->redraw(); } + void ApplyEditMeshX() { BedLevelTools.mesh_x = MenuData.Value; } + void SetEditMeshX() { HMI_value.Select = 0; SetIntOnClick(0, GRID_MAX_POINTS_X - 1, BedLevelTools.mesh_x, ApplyEditMeshX, LiveEditMesh); } + void ApplyEditMeshY() { BedLevelTools.mesh_y = MenuData.Value; } + void SetEditMeshY() { HMI_value.Select = 1; SetIntOnClick(0, GRID_MAX_POINTS_Y - 1, BedLevelTools.mesh_y, ApplyEditMeshY, LiveEditMesh); } + void SetEditZValue() { SetPFloatOnClick(Z_OFFSET_MIN, Z_OFFSET_MAX, 3); } + #endif +#endif + +#if ENABLED(AUTO_BED_LEVELING_UBL) + + void ApplyUBLSlot() { bedlevel.storage_slot = MenuData.Value; } + void SetUBLSlot() { SetIntOnClick(0, settings.calc_num_meshes() - 1, bedlevel.storage_slot, ApplyUBLSlot); } + void onDrawUBLSlot(MenuItemClass* menuitem, int8_t line) { + if (bedlevel.storage_slot < 0) bedlevel.storage_slot = 0; + onDrawIntMenu(menuitem, line, bedlevel.storage_slot); + } + + void ApplyUBLTiltGrid() { BedLevelTools.tilt_grid = MenuData.Value; } + void SetUBLTiltGrid() { SetIntOnClick(1, 3, BedLevelTools.tilt_grid, ApplyUBLTiltGrid); } + + void UBLTiltMesh() { + if (bedlevel.storage_slot < 0) bedlevel.storage_slot = 0; + char buf[15]; + if (BedLevelTools.tilt_grid > 1) { + sprintf_P(buf, PSTR("G28O\nG29 J%i"), BedLevelTools.tilt_grid); + gcode.process_subcommands_now(buf); + } + else + gcode.process_subcommands_now(F("G28O\nG29J")); + LCD_MESSAGE(MSG_UBL_MESH_TILTED); + } + + void UBLSmartFillMesh() { + LOOP_L_N(x, GRID_MAX_POINTS_Y) bedlevel.smart_fill_mesh(); + LCD_MESSAGE(MSG_UBL_MESH_FILLED); + } + + void UBLSaveMesh() { + if (bedlevel.storage_slot < 0) bedlevel.storage_slot = 0; + settings.store_mesh(bedlevel.storage_slot); + ui.status_printf(0, GET_TEXT_F(MSG_MESH_SAVED), bedlevel.storage_slot); + DONE_BUZZ(true); + } + + void UBLLoadMesh() { + if (bedlevel.storage_slot < 0) bedlevel.storage_slot = 0; + settings.load_mesh(bedlevel.storage_slot); + } + +#endif // AUTO_BED_LEVELING_UBL + +#if HAS_MESH + + void Draw_MeshSet_Menu() { + checkkey = Menu; + if (SetMenu(MeshMenu, GET_TEXT_F(MSG_MESH_LEVELING), 15)) { + BACK_ITEM(Draw_AdvancedSettings_Menu); + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + EDIT_ITEM_F(ICON_Temperature, MSG_UBL_SET_TEMP_BED, onDrawPIntMenu, SetBedLevT, &HMI_data.BedLevT); + #endif + EDIT_ITEM_F(ICON_SetZOffset, MSG_Z_FADE_HEIGHT, onDrawPFloatMenu, SetMeshFadeHeight, &planner.z_fade_height); + EDIT_ITEM_F(ICON_UBLActive, MSG_ACTIVATE_MESH, onDrawChkbMenu, SetMeshActive, &planner.leveling_active); + #if HAS_BED_PROBE + MENU_ITEM_F(ICON_Level, MSG_AUTO_MESH, onDrawMenuItem, AutoLev); + #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) + EDIT_ITEM_F(ICON_UBLActive, MSG_UBL_STORAGE_SLOT, onDrawUBLSlot, SetUBLSlot, &bedlevel.storage_slot); + MENU_ITEM_F(ICON_UBLActive, MSG_UBL_SAVE_MESH, onDrawMenuItem, UBLSaveMesh); + MENU_ITEM_F(ICON_UBLActive, MSG_UBL_LOAD_MESH, onDrawMenuItem, UBLLoadMesh); + EDIT_ITEM_F(ICON_UBLActive, MSG_UBL_TILTING_GRID, onDrawPInt8Menu, SetUBLTiltGrid, &BedLevelTools.tilt_grid); + MENU_ITEM_F(ICON_UBLActive, MSG_UBL_TILT_MESH, onDrawMenuItem, UBLTiltMesh); + MENU_ITEM_F(ICON_UBLActive, MSG_UBL_SMART_FILLIN, onDrawMenuItem, UBLSmartFillMesh); + #endif + #if ENABLED(MESH_EDIT_MENU) + MENU_ITEM_F(ICON_UBLActive, MSG_EDIT_MESH, onDrawSubMenu, Draw_EditMesh_Menu); + #endif + MENU_ITEM_F(ICON_MeshViewer, MSG_MESH_VIEW, onDrawSubMenu, DWIN_MeshViewer); + } + UpdateMenu(MeshMenu); + } + + #if ENABLED(MESH_EDIT_MENU) + void Draw_EditMesh_Menu() { + if (!leveling_is_valid()) { LCD_MESSAGE(MSG_UBL_MESH_INVALID); return; } + set_bed_leveling_enabled(false); + checkkey = Menu; + if (SetMenu(EditMeshMenu, GET_TEXT_F(MSG_EDIT_MESH), 4)) { + BedLevelTools.mesh_x = BedLevelTools.mesh_y = 0; + BACK_ITEM(Draw_MeshSet_Menu); + EDIT_ITEM_F(ICON_UBLActive, MSG_MESH_X, onDrawPInt8Menu, SetEditMeshX,&BedLevelTools.mesh_x); + EDIT_ITEM_F(ICON_UBLActive, MSG_MESH_Y, onDrawPInt8Menu, SetEditMeshY,&BedLevelTools.mesh_y); + EditZValueItem = EDIT_ITEM_F(ICON_UBLActive, MSG_MESH_EDIT_Z, onDrawPFloat3Menu, SetEditZValue, &bedlevel.z_values[BedLevelTools.mesh_x][BedLevelTools.mesh_y]); + } + UpdateMenu(EditMeshMenu); + } + #endif + +#endif // HAS_MESH + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/dwin.h b/src/lcd/e3v2/proui/dwin.h new file mode 100644 index 0000000..6d36cca --- /dev/null +++ b/src/lcd/e3v2/proui/dwin.h @@ -0,0 +1,293 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.17.2 + * Date: 2022/04/08 + */ + +#include "dwin_defines.h" +#include "dwinui.h" +#include "../common/encoder.h" +#include "../../../libs/BL24CXX.h" + +#include "../../../inc/MarlinConfig.h" + +enum processID : uint8_t { + // Process ID + MainMenu, + Menu, + SetInt, + SetPInt, + SetIntNoDraw, + SetFloat, + SetPFloat, + SelectFile, + PrintProcess, + Popup, + Leveling, + Locked, + Reboot, + PrintDone, + ESDiagProcess, + WaitResponse, + Homing, + PidProcess, + NothingToDo +}; + +enum pidresult_t : uint8_t { + PID_BAD_EXTRUDER_NUM, + PID_TEMP_TOO_HIGH, + PID_TUNING_TIMEOUT, + PID_EXTR_START, + PID_BED_START, + PID_DONE +}; + +#define DWIN_CHINESE 123 +#define DWIN_ENGLISH 0 + +typedef struct { + int8_t Color[3]; // Color components + pidresult_t pidresult = PID_DONE; + uint8_t Select = 0; // Auxiliary selector variable + AxisEnum axis = X_AXIS; // Axis Select +} HMI_value_t; + +typedef struct { + uint8_t language; + bool percent_flag:1; // percent was override by M73 + bool remain_flag:1; // remain was override by M73 + bool pause_flag:1; // printing is paused + bool pause_action:1; // flag a pause action + bool abort_flag:1; // printing is aborting + bool abort_action:1; // flag a aborting action + bool print_finish:1; // print was finished + bool select_flag:1; // Popup button selected + bool home_flag:1; // homing in course + bool heat_flag:1; // 0: heating done 1: during heating +} HMI_flag_t; + +extern HMI_value_t HMI_value; +extern HMI_flag_t HMI_flag; +extern uint8_t checkkey; +extern millis_t dwin_heat_time; + +// Popups +#if HAS_HOTEND || HAS_HEATED_BED + void DWIN_Popup_Temperature(const bool toohigh); +#endif +#if ENABLED(POWER_LOSS_RECOVERY) + void Popup_PowerLossRecovery(); +#endif + +// Tool Functions +#if ENABLED(EEPROM_SETTINGS) + void WriteEeprom(); + void ReadEeprom(); + void ResetEeprom(); + #if HAS_MESH + void SaveMesh(); + #endif +#endif +void RebootPrinter(); +void DisableMotors(); +void AutoLev(); +void AutoHome(); +#if HAS_PREHEAT + void DoPreheat0(); + void DoPreheat1(); + void DoPreheat2(); +#endif +void DoCoolDown(); +#if HAS_HOTEND + void HotendPID(); +#endif +#if HAS_HEATED_BED + void BedPID(); +#endif +#if ENABLED(BAUD_RATE_GCODE) + void HMI_SetBaudRate(); + void SetBaud115K(); + void SetBaud250K(); +#endif +#if HAS_LCD_BRIGHTNESS + void TurnOffBacklight(); +#endif +void ApplyExtMinT(); +void ParkHead(); +#if HAS_ONESTEP_LEVELING + void Trammingwizard(); +#endif +#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) + void ApplyLEDColor(); +#endif +#if ENABLED(AUTO_BED_LEVELING_UBL) + void UBLTiltMesh(); + bool UBLValidMesh(); + void UBLSaveMesh(); + void UBLLoadMesh(); +#endif + +// Other +void Goto_PrintProcess(); +void Goto_Main_Menu(); +void Goto_Info_Menu(); +void Goto_PowerLossRecovery(); +void Goto_ConfirmToPrint(); +void DWIN_Draw_Dashboard(const bool with_update); // Status Area +void Draw_Main_Area(); // Redraw main area +void DWIN_DrawStatusLine(); // Draw simple status text +void DWIN_RedrawDash(); // Redraw Dash and Status line +void DWIN_RedrawScreen(); // Redraw all screen elements +void HMI_MainMenu(); // Main process screen +void HMI_SelectFile(); // File page +void HMI_Printing(); // Print page +void HMI_ReturnScreen(); // Return to previous screen before popups +void HMI_WaitForUser(); +void HMI_SaveProcessID(const uint8_t id); +void HMI_SDCardInit(); +void HMI_SDCardUpdate(); +void EachMomentUpdate(); +void update_variable(); +void DWIN_InitScreen(); +void DWIN_HandleScreen(); +void DWIN_CheckStatusMessage(); +void DWIN_HomingStart(); +void DWIN_HomingDone(); +#if HAS_MESH + void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval); +#endif +void DWIN_LevelingStart(); +void DWIN_LevelingDone(); +void DWIN_PidTuning(pidresult_t result); +void DWIN_Print_Started(const bool sd=false); +void DWIN_Print_Pause(); +void DWIN_Print_Resume(); +void DWIN_Print_Finished(); +void DWIN_Print_Aborted(); +#if HAS_FILAMENT_SENSOR + void DWIN_FilamentRunout(const uint8_t extruder); +#endif +void DWIN_M73(); +void DWIN_Print_Header(const char *text); +void DWIN_SetColorDefaults(); +void DWIN_ApplyColor(); +void DWIN_CopySettingsTo(char * const buff); +void DWIN_CopySettingsFrom(const char * const buff); +void DWIN_SetDataDefaults(); +void DWIN_RebootScreen(); + +#if ENABLED(ADVANCED_PAUSE_FEATURE) + void DWIN_Popup_Pause(FSTR_P const fmsg, uint8_t button=0); + void Draw_Popup_FilamentPurge(); + void Goto_FilamentPurge(); + void HMI_FilamentPurge(); +#endif + +// Utility and extensions +#if HAS_LOCKSCREEN + void DWIN_LockScreen(); + void DWIN_UnLockScreen(); + void HMI_LockScreen(); +#endif +#if HAS_MESH + void DWIN_MeshViewer(); +#endif +#if HAS_GCODE_PREVIEW + void HMI_ConfirmToPrint(); +#endif +#if HAS_ESDIAG + void Draw_EndStopDiag(); +#endif +#if ENABLED(PRINTCOUNTER) + void Draw_PrintStats(); +#endif + +// Menu drawing functions +void Draw_Control_Menu(); +void Draw_AdvancedSettings_Menu(); +void Draw_Prepare_Menu(); +void Draw_Move_Menu(); +void Draw_Tramming_Menu(); +#if HAS_HOME_OFFSET + void Draw_HomeOffset_Menu(); +#endif +#if HAS_BED_PROBE + void Draw_ProbeSet_Menu(); +#endif +void Draw_FilSet_Menu(); +#if ENABLED(NOZZLE_PARK_FEATURE) + void Draw_ParkPos_Menu(); +#endif +void Draw_PhySet_Menu(); +void Draw_SelectColors_Menu(); +void Draw_GetColor_Menu(); +#if BOTH(CASE_LIGHT_MENU, CASELIGHT_USES_BRIGHTNESS) + void Draw_CaseLight_Menu(); +#endif +#if ENABLED(LED_CONTROL_MENU) + void Draw_LedControl_Menu(); +#endif +void Draw_Tune_Menu(); +void Draw_Motion_Menu(); +#if ENABLED(ADVANCED_PAUSE_FEATURE) + void Draw_FilamentMan_Menu(); +#endif +#if ENABLED(MESH_BED_LEVELING) + void Draw_ManualMesh_Menu(); +#endif +#if HAS_HOTEND + void Draw_Preheat1_Menu(); + void Draw_Preheat2_Menu(); + void Draw_Preheat3_Menu(); + void Draw_HotendPID_Menu(); +#endif +void Draw_Temperature_Menu(); +void Draw_MaxSpeed_Menu(); +void Draw_MaxAccel_Menu(); +#if HAS_CLASSIC_JERK + void Draw_MaxJerk_Menu(); +#endif +void Draw_Steps_Menu(); +#if HAS_HEATED_BED + void Draw_BedPID_Menu(); +#endif +#if EITHER(HAS_BED_PROBE, BABYSTEPPING) + void Draw_ZOffsetWiz_Menu(); +#endif +#if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) + void Draw_Homing_Menu(); +#endif +#if ENABLED(FWRETRACT) + void Draw_FWRetract_Menu(); +#endif +#if HAS_MESH + void Draw_MeshSet_Menu(); + #if ENABLED(MESH_EDIT_MENU) + void Draw_EditMesh_Menu(); + #endif +#endif diff --git a/src/lcd/e3v2/proui/dwin_defines.h b/src/lcd/e3v2/proui/dwin_defines.h new file mode 100644 index 0000000..dffc264 --- /dev/null +++ b/src/lcd/e3v2/proui/dwin_defines.h @@ -0,0 +1,122 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * DWIN general defines and data structs for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.11.2 + * Date: 2022/02/28 + */ + +#define HAS_GCODE_PREVIEW 1 +#define HAS_PIDPLOT 1 +#define HAS_ESDIAG 1 +#define HAS_LOCKSCREEN 1 +//#define DEBUG_DWIN 1 +//#define NEED_HEX_PRINT 1 + +#include "../../../inc/MarlinConfigPre.h" +#include "../common/dwin_color.h" +#if ENABLED(LED_CONTROL_MENU) + #include "../../../feature/leds/leds.h" +#endif +#include + +#if defined(__STM32F1__) || defined(STM32F1) + #define DASH_REDRAW 1 +#endif + +#define Def_Background_Color RGB( 1, 12, 8) +#define Def_Cursor_color RGB(20, 49, 31) +#define Def_TitleBg_color RGB( 0, 23, 16) +#define Def_TitleTxt_color Color_White +#define Def_Text_Color Color_White +#define Def_Selected_Color Select_Color +#define Def_SplitLine_Color RGB( 0, 23, 16) +#define Def_Highlight_Color Color_White +#define Def_StatusBg_Color RGB( 0, 23, 16) +#define Def_StatusTxt_Color Color_Yellow +#define Def_PopupBg_color Color_Bg_Window +#define Def_PopupTxt_Color Popup_Text_Color +#define Def_AlertBg_Color Color_Bg_Red +#define Def_AlertTxt_Color Color_Yellow +#define Def_PercentTxt_Color Percent_Color +#define Def_Barfill_Color BarFill_Color +#define Def_Indicator_Color Color_White +#define Def_Coordinate_Color Color_White +#define Def_Button_Color RGB( 0, 23, 16) +#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) + #define Def_Leds_Color LEDColorWhite() +#endif + +typedef struct { + // Color settings + uint16_t Background_Color = Def_Background_Color; + uint16_t Cursor_color = Def_Cursor_color; + uint16_t TitleBg_color = Def_TitleBg_color; + uint16_t TitleTxt_color = Def_TitleTxt_color; + uint16_t Text_Color = Def_Text_Color; + uint16_t Selected_Color = Def_Selected_Color; + uint16_t SplitLine_Color = Def_SplitLine_Color; + uint16_t Highlight_Color = Def_Highlight_Color; + uint16_t StatusBg_Color = Def_StatusBg_Color; + uint16_t StatusTxt_Color = Def_StatusTxt_Color; + uint16_t PopupBg_color = Def_PopupBg_color; + uint16_t PopupTxt_Color = Def_PopupTxt_Color; + uint16_t AlertBg_Color = Def_AlertBg_Color; + uint16_t AlertTxt_Color = Def_AlertTxt_Color; + uint16_t PercentTxt_Color = Def_PercentTxt_Color; + uint16_t Barfill_Color = Def_Barfill_Color; + uint16_t Indicator_Color = Def_Indicator_Color; + uint16_t Coordinate_Color = Def_Coordinate_Color; + // Temperatures + #if HAS_HOTEND && defined(PREHEAT_1_TEMP_HOTEND) + int16_t HotendPidT = PREHEAT_1_TEMP_HOTEND; + #endif + #if HAS_HEATED_BED && defined(PREHEAT_1_TEMP_BED) + int16_t BedPidT = PREHEAT_1_TEMP_BED; + #endif + #if HAS_HOTEND || HAS_HEATED_BED + int16_t PidCycles = 10; + #endif + #if ENABLED(PREVENT_COLD_EXTRUSION) + int16_t ExtMinT = EXTRUDE_MINTEMP; + #endif + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + int16_t BedLevT = LEVELING_BED_TEMP; + #endif + #if ENABLED(BAUD_RATE_GCODE) + bool Baud115K = false; + #endif + bool FullManualTramming = false; + #if ENABLED(MESH_BED_LEVELING) + float ManualZOffset = 0; + #endif + // Led + #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) + LEDColor Led_Color = Def_Leds_Color; + #endif +} HMI_data_t; + +static constexpr size_t eeprom_data_size = sizeof(HMI_data_t); +extern HMI_data_t HMI_data; diff --git a/src/lcd/e3v2/proui/dwin_lcd.cpp b/src/lcd/e3v2/proui/dwin_lcd.cpp new file mode 100644 index 0000000..6cdafc8 --- /dev/null +++ b/src/lcd/e3v2/proui/dwin_lcd.cpp @@ -0,0 +1,160 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.10.1 + * Date: 2022/03/06 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "../../../inc/MarlinConfig.h" + +#include "dwin_lcd.h" + +/*---------------------------------------- Picture related functions ----------------------------------------*/ + +// Display QR code +// The size of the QR code is (46*QR_Pixel)*(46*QR_Pixel) dot matrix +// QR_Pixel: The pixel size occupied by each point of the QR code: 0x01-0x0F (1-16) +// (Nx, Ny): The coordinates of the upper left corner displayed by the QR code +// str: multi-bit data +void DWIN_Draw_QR(uint8_t QR_Pixel, uint16_t x, uint16_t y, char *string) { + size_t i = 0; + DWIN_Byte(i, 0x21); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Byte(i, QR_Pixel); + DWIN_Text(i, string); + DWIN_Send(i); +} + +// Draw an Icon with transparent background +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + DWIN_ICON_Show(false, false, true, libID, picID, x, y); +} + +// Copy area from current virtual display area to current screen +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + size_t i = 0; + DWIN_Byte(i, 0x26); + DWIN_Word(i, xStart); + DWIN_Word(i, yStart); + DWIN_Word(i, xEnd); + DWIN_Word(i, yEnd); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Send(i); +} + +// Copy area from virtual display area to current screen +// IBD: background display: 0=Background filtering is not displayed, 1=Background display \\When setting the background filtering not to display, the background must be pure black +// BIR: Background image restoration: 0=Background image is not restored, 1=Automatically use virtual display area image for background restoration +// BFI: Background filtering strength: 0=normal, 1=enhanced, (only valid when the icon background display=0) +// cacheID: virtual area number +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(bool IBD, bool BIR, bool BFI, uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + size_t i = 0; + DWIN_Byte(i, 0x27); + DWIN_Byte(i, (IBD & 1) << 7 | (BIR & 1) << 6 | (BFI & 1) << 5 | cacheID); + DWIN_Word(i, xStart); + DWIN_Word(i, yStart); + DWIN_Word(i, xEnd); + DWIN_Word(i, yEnd); + DWIN_Word(i, x); + DWIN_Word(i, y); + DWIN_Send(i); +} + +// Copy area from virtual display area to current screen with transparent background +// cacheID: virtual area number +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + DWIN_Frame_AreaCopy(false, false, true, cacheID, xStart, yStart, xEnd, yEnd, x, y); +} + +// Write buffer data to the SRAM or Flash +// mem: 0x5A=32KB SRAM, 0xA5=16KB Flash +// addr: start address +// length: Bytes to write +// data: address of the buffer with data +void DWIN_WriteToMem(uint8_t mem, uint16_t addr, uint16_t length, uint8_t *data) { + const uint8_t max_size = 128; + uint16_t pending = length; + uint16_t to_send; + uint16_t indx; + uint8_t block = 0; + + while (pending > 0) { + indx = block * max_size; + to_send = _MIN(pending, max_size); + size_t i = 0; + DWIN_Byte(i, 0x31); + DWIN_Byte(i, mem); + DWIN_Word(i, addr + indx); // start address of the data block + ++i; + LOOP_L_N(j, i) { LCD_SERIAL.write(DWIN_SendBuf[j]); delayMicroseconds(1); } // Buf header + for (uint16_t j = indx; j <= indx + to_send - 1; j++) LCD_SERIAL.write(*(data + j)); delayMicroseconds(1); // write block of data + LOOP_L_N(j, 4) { LCD_SERIAL.write(DWIN_BufTail[j]); delayMicroseconds(1); } + block++; + pending -= to_send; + } +} + +// Write the contents of the 32KB SRAM data memory into the designated image memory space. +// picID: Picture memory space location, 0x00-0x0F, each space is 32Kbytes +void DWIN_SRAMToPic(uint8_t picID) { + size_t i = 0; + DWIN_Byte(i, 0x33); + DWIN_Byte(i, 0x5A); + DWIN_Byte(i, 0xA5); + DWIN_Byte(i, picID); + DWIN_Send(i); +} + +//--------------------------Test area ------------------------- + +//void DWIN_ReadSRAM(uint16_t addr, const uint8_t length, const char * const data) { +// size_t i = 0; +// DWIN_Byte(i, 0x32); +// DWIN_Byte(i, 0x5A); // 0x5A Read from SRAM - 0xA5 Read from Flash +// DWIN_Word(i, addr); // 0x0000 to 0x7FFF +// const size_t len = _MIN(0xF0, length); +// DWIN_Byte(i, len); +// DWIN_Send(i); +//} + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/dwin_lcd.h b/src/lcd/e3v2/proui/dwin_lcd.h new file mode 100644 index 0000000..6e0a254 --- /dev/null +++ b/src/lcd/e3v2/proui/dwin_lcd.h @@ -0,0 +1,76 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.10.1 + * Date: 2022/03/06 + */ + +#include "../common/dwin_api.h" + +// Display QR code +// The size of the QR code is (46*QR_Pixel)*(46*QR_Pixel) dot matrix +// QR_Pixel: The pixel size occupied by each point of the QR code: 0x01-0x0F (1-16) +// (Nx, Ny): The coordinates of the upper left corner displayed by the QR code +// str: multi-bit data +void DWIN_Draw_QR(uint8_t QR_Pixel, uint16_t x, uint16_t y, char *string); + +inline void DWIN_Draw_QR(uint8_t QR_Pixel, uint16_t x, uint16_t y, FSTR_P title) { + DWIN_Draw_QR(QR_Pixel, x, y, (char *)title); +} + +// Copy area from virtual display area to current screen +// cacheID: virtual area number +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y); + +// Copy area from current virtual display area to current screen +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y); + +// Copy area from virtual display area to current screen +// IBD: background display: 0=Background filtering is not displayed, 1=Background display \\When setting the background filtering not to display, the background must be pure black +// BIR: Background image restoration: 0=Background image is not restored, 1=Automatically use virtual display area image for background restoration +// BFI: Background filtering strength: 0=normal, 1=enhanced, (only valid when the icon background display=0) +// cacheID: virtual area number +// xStart/yStart: Upper-left of virtual area +// xEnd/yEnd: Lower-right of virtual area +// x/y: Screen paste point +void DWIN_Frame_AreaCopy(bool IBD, bool BIR, bool BFI, uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y); + +// Write buffer data to the SRAM or Flash +// mem: 0x5A=32KB SRAM, 0xA5=16KB Flash +// addr: start address +// length: Bytes to write +// data: address of the buffer with data +void DWIN_WriteToMem(uint8_t mem, uint16_t addr, uint16_t length, uint8_t *data); + +// Write the contents of the 32KB SRAM data memory into the designated image memory space. +// picID: Picture memory space location, 0x00-0x0F, each space is 32Kbytes +void DWIN_SRAMToPic(uint8_t picID); diff --git a/src/lcd/e3v2/proui/dwin_popup.cpp b/src/lcd/e3v2/proui/dwin_popup.cpp new file mode 100644 index 0000000..59b6c0d --- /dev/null +++ b/src/lcd/e3v2/proui/dwin_popup.cpp @@ -0,0 +1,95 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.11.1 + * Date: 2022/02/28 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "dwin.h" +#include "dwinui.h" +#include "dwin_popup.h" + +#include "../../../MarlinCore.h" // for wait_for_user + +popupDrawFunc_t popupDraw = nullptr; +popupClickFunc_t popupClick = nullptr; +popupChangeFunc_t popupChange = nullptr; + +uint16_t HighlightYPos = 280; + +void Draw_Select_Highlight(const bool sel, const uint16_t ypos) { + HighlightYPos = ypos; + HMI_flag.select_flag = sel; + const uint16_t c1 = sel ? HMI_data.Highlight_Color : HMI_data.PopupBg_color, + c2 = sel ? HMI_data.PopupBg_color : HMI_data.Highlight_Color; + DWIN_Draw_Rectangle(0, c1, 25, ypos - 1, 126, ypos + 38); + DWIN_Draw_Rectangle(0, c1, 24, ypos - 2, 127, ypos + 39); + DWIN_Draw_Rectangle(0, c2, 145, ypos - 1, 246, ypos + 38); + DWIN_Draw_Rectangle(0, c2, 144, ypos - 2, 247, ypos + 39); +} + +void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) { + HMI_SaveProcessID(WaitResponse); + DWIN_Draw_Popup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue + DWIN_UpdateLCD(); +} + +void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) { + DWIN_Draw_Popup(ICON_BLTouch, F("Please confirm"), fmsg2); + DWINUI::Draw_Button(BTN_Confirm, 26, 280); + DWINUI::Draw_Button(BTN_Cancel, 146, 280); + Draw_Select_Highlight(HMI_flag.select_flag); + DWIN_UpdateLCD(); +} + +void Goto_Popup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) { + popupDraw = fnDraw; + popupClick = fnClick; + popupChange = fnChange; + HMI_SaveProcessID(Popup); + HMI_flag.select_flag = false; + popupDraw(); +} + +void HMI_Popup() { + if (!wait_for_user) { + if (popupClick) popupClick(); + return; + } + else { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_CW || encoder_diffState == ENCODER_DIFF_CCW) { + const bool change = encoder_diffState != ENCODER_DIFF_CW; + if (popupChange) popupChange(change); else Draw_Select_Highlight(change, HighlightYPos); + DWIN_UpdateLCD(); + } + } +} + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/dwin_popup.h b/src/lcd/e3v2/proui/dwin_popup.h new file mode 100644 index 0000000..b4503ea --- /dev/null +++ b/src/lcd/e3v2/proui/dwin_popup.h @@ -0,0 +1,73 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.11.1 + * Date: 2022/02/28 + */ + +#include "dwinui.h" +#include "dwin.h" + +typedef void (*popupDrawFunc_t)(); +typedef void (*popupClickFunc_t)(); +typedef void (*popupChangeFunc_t)(const bool state); +extern popupDrawFunc_t popupDraw; + +void Draw_Select_Highlight(const bool sel, const uint16_t ypos); +inline void Draw_Select_Highlight(const bool sel) { Draw_Select_Highlight(sel, 280); }; +void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2); +void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2); +void Goto_Popup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick=nullptr, const popupChangeFunc_t fnChange=nullptr); +void HMI_Popup(); + +inline void Draw_Popup_Bkgd() { + DWIN_Draw_Rectangle(1, HMI_data.PopupBg_color, 14, 60, 258, 330); + DWIN_Draw_Rectangle(0, HMI_data.Highlight_Color, 14, 60, 258, 330); +} + +template +void DWIN_Draw_Popup(const uint8_t icon, T amsg1=nullptr, U amsg2=nullptr, uint8_t button=0) { + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + if (icon) DWINUI::Draw_Icon(icon, 101, 105); + if (amsg1) DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 210, amsg1); + if (amsg2) DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 240, amsg2); + if (button) DWINUI::Draw_Button(button, 86, 280); +} + +template +void DWIN_Show_Popup(const uint8_t icon, T amsg1=nullptr, U amsg2=nullptr, uint8_t button=0) { + DWIN_Draw_Popup(icon, amsg1, amsg2, button); + DWIN_UpdateLCD(); +} + +template +void DWIN_Popup_Confirm(const uint8_t icon, T amsg1, U amsg2) { + HMI_SaveProcessID(WaitResponse); + DWIN_Draw_Popup(icon, amsg1, amsg2, BTN_Confirm); // Button Confirm + DWIN_UpdateLCD(); +} + diff --git a/src/lcd/e3v2/proui/dwinui.cpp b/src/lcd/e3v2/proui/dwinui.cpp new file mode 100644 index 0000000..5ed36e7 --- /dev/null +++ b/src/lcd/e3v2/proui/dwinui.cpp @@ -0,0 +1,372 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.18.1 + * Date: 2022/07/05 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "../../../inc/MarlinConfig.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin_defines.h" + +//#define DEBUG_OUT 1 +#include "../../../core/debug_out.h" + +xy_int_t DWINUI::cursor = { 0 }; +uint16_t DWINUI::pencolor = Color_White; +uint16_t DWINUI::textcolor = Def_Text_Color; +uint16_t DWINUI::backcolor = Def_Background_Color; +uint16_t DWINUI::buttoncolor = Def_Button_Color; +uint8_t DWINUI::fontid = font8x16; +FSTR_P const DWINUI::Author = F(STRING_CONFIG_H_AUTHOR); + +void (*DWINUI::onTitleDraw)(TitleClass* title) = nullptr; + +void DWINUI::init() { + delay(750); // Delay for wait to wakeup screen + const bool hs = DWIN_Handshake(); UNUSED(hs); + #if ENABLED(DEBUG_DWIN) + SERIAL_ECHOPGM("DWIN_Handshake "); + SERIAL_ECHOLNF(hs ? F("ok.") : F("error.")); + #endif + DWIN_Frame_SetDir(1); + cursor.reset(); + pencolor = Color_White; + textcolor = Def_Text_Color; + backcolor = Def_Background_Color; + buttoncolor = Def_Button_Color; + fontid = font8x16; +} + +// Set text/number font +void DWINUI::setFont(fontid_t fid) { fontid = fid; } + +// Get font character width +uint8_t DWINUI::fontWidth(fontid_t fid) { + switch (fid) { + case font6x12 : return 6; + case font8x16 : return 8; + case font10x20: return 10; + case font12x24: return 12; + case font14x28: return 14; + case font16x32: return 16; + case font20x40: return 20; + case font24x48: return 24; + case font28x56: return 28; + case font32x64: return 32; + default: return 0; + } +} + +// Get font character height +uint8_t DWINUI::fontHeight(fontid_t fid) { + switch (fid) { + case font6x12 : return 12; + case font8x16 : return 16; + case font10x20: return 20; + case font12x24: return 24; + case font14x28: return 28; + case font16x32: return 32; + case font20x40: return 40; + case font24x48: return 48; + case font28x56: return 56; + case font32x64: return 64; + default: return 0; + } +} + +// Get screen x coordinates from text column +uint16_t DWINUI::ColToX(uint8_t col) { return col * fontWidth(fontid); } + +// Get screen y coordinates from text row +uint16_t DWINUI::RowToY(uint8_t row) { return row * fontHeight(fontid); } + +// Set text/number color +void DWINUI::SetColors(uint16_t fgcolor, uint16_t bgcolor, uint16_t alcolor) { + textcolor = fgcolor; + backcolor = bgcolor; + buttoncolor = alcolor; +} +void DWINUI::SetTextColor(uint16_t fgcolor) { + textcolor = fgcolor; +} +void DWINUI::SetBackgroundColor(uint16_t bgcolor) { + backcolor = bgcolor; +} + +// Moves cursor to point +// x: abscissa of the display +// y: ordinate of the display +// point: xy coordinate +void DWINUI::MoveTo(int16_t x, int16_t y) { + cursor.x = x; + cursor.y = y; +} +void DWINUI::MoveTo(xy_int_t point) { + cursor = point; +} + +// Moves cursor relative to the actual position +// x: abscissa of the display +// y: ordinate of the display +// point: xy coordinate +void DWINUI::MoveBy(int16_t x, int16_t y) { + cursor.x += x; + cursor.y += y; +} +void DWINUI::MoveBy(xy_int_t point) { + cursor += point; +} + +// Draw a Centered string using arbitrary x1 and x2 margins +void DWINUI::Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t x1, uint16_t x2, uint16_t y, const char * const string) { + const uint16_t x = _MAX(0U, x2 + x1 - strlen_P(string) * fontWidth(fid)) / 2 - 1; + DWIN_Draw_String(bShow, fid, color, bColor, x, y, string); +} + +// Draw a char +// color: Character color +// x: abscissa of the display +// y: ordinate of the display +// c: ASCII code of char +void DWINUI::Draw_Char(uint16_t color, uint16_t x, uint16_t y, const char c) { + const char string[2] = { c, 0}; + DWIN_Draw_String(false, fontid, color, backcolor, x, y, string, 1); +} + +// Draw a char at cursor position and increment cursor +void DWINUI::Draw_Char(uint16_t color, const char c) { + Draw_Char(color, cursor.x, cursor.y, c); + MoveBy(fontWidth(fontid), 0); +} + +// Draw a string at cursor position +// color: Character color +// *string: The string +// rlimit: For draw less chars than string length use rlimit +void DWINUI::Draw_String(const char * const string, uint16_t rlimit) { + DWIN_Draw_String(false, fontid, textcolor, backcolor, cursor.x, cursor.y, string, rlimit); + MoveBy(strlen(string) * fontWidth(fontid), 0); +} +void DWINUI::Draw_String(uint16_t color, const char * const string, uint16_t rlimit) { + DWIN_Draw_String(false, fontid, color, backcolor, cursor.x, cursor.y, string, rlimit); + MoveBy(strlen(string) * fontWidth(fontid), 0); +} + +// Draw a numeric integer value +// bShow: true=display background color; false=don't display background color +// signedMode: 1=signed; 0=unsigned +// fid: Font ID +// color: Character color +// bColor: Background color +// iNum: Number of digits +// x/y: Upper-left coordinate +// value: Integer value +void DWINUI::Draw_Int(uint8_t bShow, bool signedMode, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, int32_t value) { + char nstr[10]; + sprintf_P(nstr, PSTR("%*li"), (signedMode ? iNum + 1 : iNum), value); + DWIN_Draw_String(bShow, fid, color, bColor, x, y, nstr); +} + +// Draw a numeric float value +// bShow: true=display background color; false=don't display background color +// signedMode: 1=signed; 0=unsigned +// fid: Font ID +// color: Character color +// bColor: Background color +// iNum: Number of digits +// fNum: Number of decimal digits +// x/y: Upper-left coordinate +// value: float value +void DWINUI::Draw_Float(uint8_t bShow, bool signedMode, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + char nstr[10]; + DWIN_Draw_String(bShow, fid, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr)); +} + +// ------------------------- Buttons ------------------------------// + +void DWINUI::Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) { + DWIN_Draw_Rectangle(1, bcolor, x1, y1, x2, y2); + Draw_CenteredString(0, fontid, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption); +} + +void DWINUI::Draw_Button(uint8_t id, uint16_t x, uint16_t y) { + switch (id) { + case BTN_Cancel : Draw_Button(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break; + case BTN_Confirm : Draw_Button(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break; + case BTN_Continue: Draw_Button(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break; + case BTN_Print : Draw_Button(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break; + case BTN_Save : Draw_Button(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break; + case BTN_Purge : Draw_Button(GET_TEXT_F(MSG_BUTTON_PURGE), x, y); break; + default: break; + } +} + +// -------------------------- Extra -------------------------------// + +// Draw a circle +// color: circle color +// x: the abscissa of the center of the circle +// y: ordinate of the center of the circle +// r: circle radius +void DWINUI::Draw_Circle(uint16_t color, uint16_t x, uint16_t y, uint8_t r) { + int a = 0, b = 0; + while (a <= b) { + b = SQRT(sq(r) - sq(a)); + if (a == 0) b--; + DWIN_Draw_Point(color, 1, 1, x + a, y + b); // Draw some sector 1 + DWIN_Draw_Point(color, 1, 1, x + b, y + a); // Draw some sector 2 + DWIN_Draw_Point(color, 1, 1, x + b, y - a); // Draw some sector 3 + DWIN_Draw_Point(color, 1, 1, x + a, y - b); // Draw some sector 4 + DWIN_Draw_Point(color, 1, 1, x - a, y - b); // Draw some sector 5 + DWIN_Draw_Point(color, 1, 1, x - b, y - a); // Draw some sector 6 + DWIN_Draw_Point(color, 1, 1, x - b, y + a); // Draw some sector 7 + DWIN_Draw_Point(color, 1, 1, x - a, y + b); // Draw some sector 8 + a++; + } +} + +// Draw a circle filled with color +// bcolor: fill color +// x: the abscissa of the center of the circle +// y: ordinate of the center of the circle +// r: circle radius +void DWINUI::Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) { + int a = 0, b = 0; + while (a <= b) { + b = SQRT(sq(r) - sq(a)); // b=sqrt(r*r-a*a); + if (a == 0) b--; + DWIN_Draw_Line(bcolor, x-b,y-a,x+b,y-a); + DWIN_Draw_Line(bcolor, x-a,y-b,x+a,y-b); + DWIN_Draw_Line(bcolor, x-b,y+a,x+b,y+a); + DWIN_Draw_Line(bcolor, x-a,y+b,x+a,y+b); + a++; + } +} + +// Color Interpolator +// val : Interpolator minv..maxv +// minv : Minimum value +// maxv : Maximum value +// color1 : Start color +// color2 : End color +uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) { + uint8_t B, G, R; + const float n = (float)(val - minv) / (maxv - minv); + R = (1 - n) * GetRColor(color1) + n * GetRColor(color2); + G = (1 - n) * GetGColor(color1) + n * GetGColor(color2); + B = (1 - n) * GetBColor(color1) + n * GetBColor(color2); + return RGB(R, G, B); +} + +// Color Interpolator through Red->Yellow->Green->Blue (Pro UI) +// val : Interpolator minv..maxv +// minv : Minimum value +// maxv : Maximum value +uint16_t DWINUI::RainbowInt(int16_t val, int16_t minv, int16_t maxv) { + uint8_t B, G, R; + const uint8_t maxB = 28, maxR = 28, maxG = 38; + const int16_t limv = _MAX(abs(minv), abs(maxv)); + float n = minv >= 0 ? (float)(val - minv) / (maxv - minv) : (float)val / limv; + LIMIT(n, -1, 1); + if (n < 0) { + R = 0; + G = (1 + n) * maxG; + B = (-n) * maxB; + } + else if (n < 0.5) { + R = maxR * n * 2; + G = maxG; + B = 0; + } + else { + R = maxR; + G = maxG * (1 - n); + B = 0; + } + return RGB(R, G, B); +} + +// Draw a checkbox +// Color: frame color +// bColor: Background color +// x/y: Upper-left point +// mode : 0 : unchecked, 1 : checked +void DWINUI::Draw_Checkbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked=false) { + DWIN_Draw_String(true, font8x16, color, bcolor, x + 4, y, checked ? F("x") : F(" ")); + DWIN_Draw_Rectangle(0, color, x + 2, y + 2, x + 17, y + 17); +} + +// Clear Menu by filling the menu area with background color +void DWINUI::ClearMainArea() { + DWIN_Draw_Rectangle(1, backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); +} + +/* Title Class ==============================================================*/ + +TitleClass Title; + +void TitleClass::draw() { + if (DWINUI::onTitleDraw != nullptr) (*DWINUI::onTitleDraw)(this); +} + +void TitleClass::SetCaption(const char * const title) { + frameid = 0; + if ( caption == title ) return; + const uint8_t len = _MIN(sizeof(caption) - 1, strlen(title)); + memcpy(&caption[0], title, len); + caption[len] = '\0'; +} + +void TitleClass::ShowCaption(const char * const title) { + SetCaption(title); + draw(); +} + +void TitleClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + caption[0] = '\0'; + frameid = id; + frame = { x1, y1, x2, y2 }; +} + +void TitleClass::SetFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + SetFrame(1, x, y, x + w - 1, y + h - 1); +} + +void TitleClass::FrameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + SetFrame(id, x1, y1, x2, y2); + draw(); +} + +void TitleClass::FrameCopy(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + FrameCopy(1, x, y, x + w - 1, y + h - 1); +} + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/dwinui.h b/src/lcd/e3v2/proui/dwinui.h new file mode 100644 index 0000000..a544471 --- /dev/null +++ b/src/lcd/e3v2/proui/dwinui.h @@ -0,0 +1,562 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * DWIN Enhanced implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 3.18.1 + * Date: 2022/07/05 + */ + +#include "dwin_lcd.h" +#include "../common/dwin_set.h" +#include "../common/dwin_font.h" +#include "../common/dwin_color.h" + +// Extra Icons +#define ICON_AdvSet ICON_Language +#define ICON_BedSizeX ICON_PrintSize +#define ICON_BedSizeY ICON_PrintSize +#define ICON_BedTramming ICON_SetHome +#define ICON_Binary ICON_Contact +#define ICON_BltouchReset ICON_StockConfiguration +#define ICON_Brightness ICON_Motion +#define ICON_Cancel ICON_StockConfiguration +#define ICON_CustomPreheat ICON_SetEndTemp +#define ICON_Error ICON_TempTooHigh +#define ICON_ESDiag ICON_Info +#define ICON_ExtrudeMinT ICON_HotendTemp +#define ICON_FilLoad ICON_WriteEEPROM +#define ICON_FilMan ICON_ResumeEEPROM +#define ICON_FilSet ICON_ResumeEEPROM +#define ICON_FilUnload ICON_ReadEEPROM +#define ICON_Flow ICON_StepE +#define ICON_Folder ICON_More +#define ICON_FWRetract ICON_StepE +#define ICON_FWRetLength ICON_StepE +#define ICON_FWRetSpeed ICON_Setspeed +#define ICON_FWRetZRaise ICON_MoveZ +#define ICON_FWRecSpeed ICON_Setspeed +#define ICON_FWRecExtra ICON_StepE +#define ICON_HomeX ICON_MoveX +#define ICON_HomeY ICON_MoveY +#define ICON_HomeZ ICON_MoveZ +#define ICON_HomeOffset ICON_AdvSet +#define ICON_HomeOffsetX ICON_StepX +#define ICON_HomeOffsetY ICON_StepY +#define ICON_HomeOffsetZ ICON_StepZ +#define ICON_HSMode ICON_StockConfiguration +#define ICON_InvertE0 ICON_StepE +#define ICON_Tram ICON_SetEndTemp +#define ICON_Level ICON_HotendTemp +#define ICON_Lock ICON_Cool +#define ICON_ManualMesh ICON_HotendTemp +#define ICON_MaxPosX ICON_MoveX +#define ICON_MaxPosY ICON_MoveY +#define ICON_MaxPosZ ICON_MoveZ +#define ICON_MeshNext ICON_Axis +#define ICON_MeshPoints ICON_SetEndTemp +#define ICON_MeshSave ICON_WriteEEPROM +#define ICON_MeshViewer ICON_HotendTemp +#define ICON_MoveZ0 ICON_HotendTemp +#define ICON_Park ICON_Motion +#define ICON_ParkPos ICON_AdvSet +#define ICON_ParkPosX ICON_StepX +#define ICON_ParkPosY ICON_StepY +#define ICON_ParkPosZ ICON_StepZ +#define ICON_PhySet ICON_PrintSize +#define ICON_PIDbed ICON_SetBedTemp +#define ICON_PIDcycles ICON_ResumeEEPROM +#define ICON_PIDValue ICON_Contact +#define ICON_PrintStats ICON_PrintTime +#define ICON_PrintStatsReset ICON_RemainTime +#define ICON_ProbeDeploy ICON_SetEndTemp +#define ICON_ProbeMargin ICON_PrintSize +#define ICON_ProbeOffsetX ICON_StepX +#define ICON_ProbeOffsetY ICON_StepY +#define ICON_ProbeOffsetZ ICON_StepZ +#define ICON_ProbeSet ICON_SetEndTemp +#define ICON_ProbeStow ICON_SetEndTemp +#define ICON_ProbeTest ICON_SetEndTemp +#define ICON_ProbeZSpeed ICON_MaxSpeedZ +#define ICON_Pwrlossr ICON_Motion +#define ICON_Reboot ICON_ResumeEEPROM +#define ICON_Runout ICON_MaxAccE +#define ICON_Scolor ICON_MaxSpeed +#define ICON_SetBaudRate ICON_Setspeed +#define ICON_SetCustomPreheat ICON_SetEndTemp +#define ICON_Sound ICON_Cool +#define ICON_TBSetup ICON_Contact +#define ICON_UBLActive ICON_HotendTemp + +#define ICON_CaseLight ICON_Motion +#define ICON_LedControl ICON_Motion + +// Buttons +#define BTN_Continue 85 +#define BTN_Cancel 87 +#define BTN_Confirm 89 +#define BTN_Print 90 +#define BTN_Save 91 +#define BTN_Purge 92 + +// Extended and default UI Colors +#define Color_Black 0 +#define Color_Green RGB(0,63,0) +#define Color_Aqua RGB(0,63,31) +#define Color_Blue RGB(0,0,31) +#define Color_Light_White 0xBDD7 +#define Color_Light_Green 0x3460 +#define Color_Cyan 0x07FF +#define Color_Light_Cyan 0x04F3 +#define Color_Light_Blue 0x3A6A +#define Color_Magenta 0xF81F +#define Color_Light_Magenta 0x9813 +#define Color_Light_Red 0x8800 +#define Color_Orange 0xFA20 +#define Color_Light_Orange 0xFBC0 +#define Color_Light_Yellow 0x8BE0 +#define Color_Brown 0xCC27 +#define Color_Light_Brown 0x6204 +#define Color_Grey 0x18E3 + +// UI element defines and constants +#define DWIN_FONT_MENU font8x16 +#define DWIN_FONT_STAT font10x20 +#define DWIN_FONT_HEAD font10x20 +#define DWIN_FONT_ALERT font10x20 +#define STATUS_Y 354 +#define LCD_WIDTH (DWIN_WIDTH / 8) // only if the default fontid is font8x16 + +// Minimum unit (0.1) : multiple (10) +#define UNITFDIGITS 1 +#define MINUNITMULT POW(10, UNITFDIGITS) + +constexpr uint8_t TITLE_HEIGHT = 30, // Title bar height + MLINE = 53, // Menu line height + TROWS = (STATUS_Y - TITLE_HEIGHT) / MLINE, // Total rows + MROWS = TROWS - 1, // Other-than-Back + ICOX = 26, // Menu item icon X position + LBLX = 55, // Menu item label X position + VALX = 210, // Menu item value X position + MENU_CHR_W = 8, MENU_CHR_H = 16, // Menu font 8x16 + STAT_CHR_W = 10; + +// Menuitem Y position +#define MYPOS(L) (TITLE_HEIGHT + MLINE * (L)) + +// Menuitem caption Offset +#define CAPOFF ((MLINE - MENU_CHR_H) / 2) + +// Menuitem caption Y position +#define MBASE(L) (MYPOS(L) + CAPOFF) + +typedef struct { uint16_t left, top, right, bottom; } rect_t; +typedef struct { uint16_t x, y, w, h; } frame_rect_t; + +class TitleClass { +public: + char caption[32] = ""; + uint8_t frameid = 0; + rect_t frame = {0}; + void draw(); + void SetCaption(const char * const title); + inline void SetCaption(FSTR_P title) { SetCaption((char *)title); } + void ShowCaption(const char * const title); + inline void ShowCaption(FSTR_P title) { ShowCaption((char *)title); } + void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); + void SetFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h); + void FrameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); + void FrameCopy(uint16_t x, uint16_t y, uint16_t h, uint16_t v); +}; +extern TitleClass Title; + +namespace DWINUI { + extern xy_int_t cursor; + extern uint16_t pencolor; + extern uint16_t textcolor; + extern uint16_t backcolor; + extern uint16_t buttoncolor; + extern fontid_t fontid; + extern FSTR_P const Author; + + extern void (*onTitleDraw)(TitleClass* title); + + // DWIN LCD Initialization + void init(); + + // Set text/number font + void setFont(fontid_t cfont); + + // Get font character width + uint8_t fontWidth(fontid_t cfont); + inline uint8_t fontWidth() { return fontWidth(fontid); }; + + // Get font character height + uint8_t fontHeight(fontid_t cfont); + inline uint8_t fontHeight() { return fontHeight(fontid); }; + + // Get screen x coordinates from text column + uint16_t ColToX(uint8_t col); + + // Get screen y coordinates from text row + uint16_t RowToY(uint8_t row); + + // Set text/number color + void SetColors(uint16_t fgcolor, uint16_t bgcolor, uint16_t alcolor); + void SetTextColor(uint16_t fgcolor); + void SetBackgroundColor(uint16_t bgcolor); + + // Moves cursor to point + // x: abscissa of the display + // y: ordinate of the display + // point: xy coordinate + void MoveTo(int16_t x, int16_t y); + void MoveTo(xy_int_t point); + + // Moves cursor relative to the actual position + // x: abscissa of the display + // y: ordinate of the display + // point: xy coordinate + void MoveBy(int16_t x, int16_t y); + void MoveBy(xy_int_t point); + + // Draw a line from the cursor to xy position + // color: Line segment color + // x/y: End point + inline void LineTo(uint16_t color, uint16_t x, uint16_t y) { + DWIN_Draw_Line(color, cursor.x, cursor.y, x, y); + } + inline void LineTo(uint16_t x, uint16_t y) { + DWIN_Draw_Line(pencolor, cursor.x, cursor.y, x, y); + } + + // Extend a frame box + // v: value to extend + inline frame_rect_t ExtendFrame(frame_rect_t frame, uint8_t v) { + frame_rect_t t; + t.x = frame.x - v; + t.y = frame.y - v; + t.w = frame.w + 2 * v; + t.h = frame.h + 2 * v; + return t; + } + + // Draw an Icon with transparent background from the library ICON + // icon: Icon ID + // x/y: Upper-left point + inline void Draw_Icon(uint8_t icon, uint16_t x, uint16_t y) { + DWIN_ICON_Show(ICON, icon, x, y); + } + + // Draw an Icon from the library ICON with its background + // icon: Icon ID + // x/y: Upper-left point + inline void Draw_IconWB(uint8_t icon, uint16_t x, uint16_t y) { + DWIN_ICON_Show(true, false, false, ICON, icon, x, y); + } + + // Draw a numeric integer value + // bShow: true=display background color; false=don't display background color + // signedMode: 1=signed; 0=unsigned + // fid: Font ID + // color: Character color + // bColor: Background color + // iNum: Number of digits + // x/y: Upper-left coordinate + // value: Integer value + void Draw_Int(uint8_t bShow, bool signedMode, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, int32_t value); + + // Draw a positive integer + inline void Draw_Int(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(bShow, 0, fid, color, bColor, iNum, x, y, value); + } + inline void Draw_Int(uint8_t iNum, long value) { + Draw_Int(false, 0, fontid, textcolor, backcolor, iNum, cursor.x, cursor.y, value); + MoveBy(iNum * fontWidth(fontid), 0); + } + inline void Draw_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(false, 0, fontid, textcolor, backcolor, iNum, x, y, value); + } + inline void Draw_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(false, 0, fontid, color, backcolor, iNum, x, y, value); + } + inline void Draw_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(true, 0, fontid, color, bColor, iNum, x, y, value); + } + inline void Draw_Int(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(true, 0, fid, color, bColor, iNum, x, y, value); + } + + // Draw a signed integer + inline void Draw_Signed_Int(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(bShow, 1, fid, color, bColor, iNum, x, y, value); + } + inline void Draw_Signed_Int(uint8_t iNum, long value) { + Draw_Int(false, 1, fontid, textcolor, backcolor, iNum, cursor.x, cursor.y, value); + MoveBy(iNum * fontWidth(fontid), 0); + } + inline void Draw_Signed_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(false, 1, fontid, textcolor, backcolor, iNum, x, y, value); + } + inline void Draw_Signed_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(false, 1, fontid, color, backcolor, iNum, x, y, value); + } + inline void Draw_Signed_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(true, 1, fontid, color, bColor, iNum, x, y, value); + } + inline void Draw_Signed_Int(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + Draw_Int(true, 1, fid, color, bColor, iNum, x, y, value); + } + + // Draw a numeric float value + // bShow: true=display background color; false=don't display background color + // signedMode: 1=signed; 0=unsigned + // fid: Font ID + // color: Character color + // bColor: Background color + // iNum: Number of digits + // fNum: Number of decimal digits + // x/y: Upper-left coordinate + // value: float value + void Draw_Float(uint8_t bShow, bool signedMode, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value); + + // Draw a positive floating point number + inline void Draw_Float(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(bShow, 0, fid, color, bColor, iNum, fNum, x, y, value); + } + inline void Draw_Float(uint8_t iNum, uint8_t fNum, float value) { + Draw_Float(false, 0, fontid, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value); + MoveBy((iNum + fNum + 1) * fontWidth(fontid), 0); + } + inline void Draw_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(false, 0, fontid, textcolor, backcolor, iNum, fNum, x, y, value); + } + inline void Draw_Float(fontid_t fid, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(false, 0, fid, textcolor, backcolor, iNum, fNum, x, y, value); + } + inline void Draw_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(true, 0, fontid, color, bColor, iNum, fNum, x, y, value); + } + inline void Draw_Float(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(true, 0, fid, color, bColor, iNum, fNum, x, y, value); + } + + // Draw a signed floating point number + inline void Draw_Signed_Float(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(bShow, 1, fid, color, bColor, iNum, fNum, x, y, value); + } + inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, float value) { + Draw_Float(false, 1, fontid, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value); + MoveBy((iNum + fNum + 1) * fontWidth(fontid), 0); + } + inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(false, 1, fontid, textcolor, backcolor, iNum, fNum, x, y, value); + } + inline void Draw_Signed_Float(fontid_t fid, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(false, 1, fid, textcolor, backcolor, iNum, fNum, x, y, value); + } + inline void Draw_Signed_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(true, 1, fontid, color, bColor, iNum, fNum, x, y, value); + } + inline void Draw_Signed_Float(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + Draw_Float(true, 1, fid, color, bColor, iNum, fNum, x, y, value); + } + + // Draw a char + // color: Character color + // x: abscissa of the display + // y: ordinate of the display + // c: ASCII code of char + void Draw_Char(uint16_t color, uint16_t x, uint16_t y, const char c); + inline void Draw_Char(uint16_t x, uint16_t y, const char c) { Draw_Char(textcolor, x, y, c); }; + // Draw a char at cursor position and increment cursor + void Draw_Char(uint16_t color, const char c); + inline void Draw_Char(const char c) { Draw_Char(textcolor, c); } + + // Draw a string at cursor position + // color: Character color + // *string: The string + // rlimit: For draw less chars than string length use rlimit + void Draw_String(const char * const string, uint16_t rlimit = 0xFFFF); + void Draw_String(uint16_t color, const char * const string, uint16_t rlimit = 0xFFFF); + inline void Draw_String(FSTR_P string, uint16_t rlimit = 0xFFFF) { + Draw_String(FTOP(string), rlimit); + } + inline void Draw_String(uint16_t color, FSTR_P string, uint16_t rlimit = 0xFFFF) { + Draw_String(color, FTOP(string), rlimit); + } + + // Draw a string + // fid: Font ID + // color: Character color + // bColor: Background color + // x/y: Upper-left coordinate of the string + // *string: The string + inline void Draw_String(uint16_t x, uint16_t y, const char * const string) { + DWIN_Draw_String(false, fontid, textcolor, backcolor, x, y, string); + } + inline void Draw_String(uint16_t x, uint16_t y, FSTR_P title) { + DWIN_Draw_String(false, fontid, textcolor, backcolor, x, y, FTOP(title)); + } + inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, const char * const string) { + DWIN_Draw_String(false, fontid, color, backcolor, x, y, string); + } + inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, FSTR_P title) { + DWIN_Draw_String(false, fontid, color, backcolor, x, y, title); + } + inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) { + DWIN_Draw_String(true, fontid, color, bgcolor, x, y, string); + } + inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) { + DWIN_Draw_String(true, fontid, color, bgcolor, x, y, title); + } + inline void Draw_String(fontid_t fid, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) { + DWIN_Draw_String(true, fid, color, bgcolor, x, y, string); + } + inline void Draw_String(fontid_t fid, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) { + DWIN_Draw_String(true, fid, color, bgcolor, x, y, title); + } + + // Draw a centered string using DWIN_WIDTH + // bShow: true=display background color; false=don't display background color + // fid: Font ID + // color: Character color + // bColor: Background color + // y: Upper coordinate of the string + // *string: The string + void Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t x1, uint16_t x2, uint16_t y, const char * const string); + inline void Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) { + Draw_CenteredString(bShow, fid, color, bColor, 0, DWIN_WIDTH, y, string); + } + inline void Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t y, FSTR_P string) { + Draw_CenteredString(bShow, fid, color, bColor, y, FTOP(string)); + } + inline void Draw_CenteredString(uint16_t color, uint16_t bcolor, uint16_t y, const char * const string) { + Draw_CenteredString(true, fontid, color, bcolor, y, string); + } + inline void Draw_CenteredString(fontid_t fid, uint16_t color, uint16_t y, const char * const string) { + Draw_CenteredString(false, fid, color, backcolor, y, string); + } + inline void Draw_CenteredString(fontid_t fid, uint16_t color, uint16_t y, FSTR_P title) { + Draw_CenteredString(false, fid, color, backcolor, y, title); + } + inline void Draw_CenteredString(uint16_t color, uint16_t y, const char * const string) { + Draw_CenteredString(false, fontid, color, backcolor, y, string); + } + inline void Draw_CenteredString(uint16_t color, uint16_t y, FSTR_P title) { + Draw_CenteredString(false, fontid, color, backcolor, y, title); + } + inline void Draw_CenteredString(uint16_t y, const char * const string) { + Draw_CenteredString(false, fontid, textcolor, backcolor, y, string); + } + inline void Draw_CenteredString(uint16_t y, FSTR_P title) { + Draw_CenteredString(false, fontid, textcolor, backcolor, y, title); + } + + // Draw a box + // mode: 0=frame, 1=fill, 2=XOR fill + // color: Rectangle color + // frame: Box coordinates and size + inline void Draw_Box(uint8_t mode, uint16_t color, frame_rect_t frame) { + DWIN_Draw_Box(mode, color, frame.x, frame.y, frame.w, frame.h); + } + + // Draw a circle + // Color: circle color + // x: abscissa of the center of the circle + // y: ordinate of the center of the circle + // r: circle radius + void Draw_Circle(uint16_t color, uint16_t x,uint16_t y,uint8_t r); + inline void Draw_Circle(uint16_t color, uint8_t r) { + Draw_Circle(color, cursor.x, cursor.y, r); + } + + // Draw a checkbox + // Color: frame color + // bColor: Background color + // x/y: Upper-left point + // checked : 0 : unchecked, 1 : checked + void Draw_Checkbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked); + inline void Draw_Checkbox(uint16_t x, uint16_t y, bool checked=false) { + Draw_Checkbox(textcolor, backcolor, x, y, checked); + } + + // Color Interpolator + // val : Interpolator minv..maxv + // minv : Minimum value + // maxv : Maximum value + // color1 : Start color + // color2 : End color + uint16_t ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2); + + // ------------------------- Buttons ------------------------------// + + void Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption); + inline void Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, FSTR_P caption) { + Draw_Button(color, bcolor, x1, y1, x2, y2, FTOP(caption)); + } + inline void Draw_Button(FSTR_P caption, uint16_t x, uint16_t y) { + Draw_Button(textcolor, buttoncolor, x, y, x + 99, y + 37, caption); + } + void Draw_Button(uint8_t id, uint16_t x, uint16_t y); + + // -------------------------- Extra -------------------------------// + + // Draw a circle filled with color + // bcolor: fill color + // x: abscissa of the center of the circle + // y: ordinate of the center of the circle + // r: circle radius + void Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r); + inline void Draw_FillCircle(uint16_t bcolor, uint8_t r) { + Draw_FillCircle(bcolor, cursor.x, cursor.y, r); + } + + // Color Interpolator through Red->Yellow->Green->Blue + // val : Interpolator minv..maxv + // minv : Minimum value + // maxv : Maximum value + uint16_t RainbowInt(int16_t val, int16_t minv, int16_t maxv); + + // Write buffer data to the SRAM + // addr: SRAM start address 0x0000-0x7FFF + // length: Bytes to write + // data: address of the buffer with data + inline void WriteToSRAM(uint16_t addr, uint16_t length, uint8_t *data) { + DWIN_WriteToMem(0x5A, addr, length, data); + } + + // Write buffer data to the Flash + // addr: Flash start address 0x0000-0x3FFF + // length: Bytes to write + // data: address of the buffer with data + inline void WriteToFlash(uint16_t addr, uint16_t length, uint8_t *data) { + DWIN_WriteToMem(0xA5, addr, length, data); + } + + // Clear by filling the area with background color + // Area (0, TITLE_HEIGHT, DWIN_WIDTH, STATUS_Y - 1) + void ClearMainArea(); + +}; diff --git a/src/lcd/e3v2/proui/endstop_diag.cpp b/src/lcd/e3v2/proui/endstop_diag.cpp new file mode 100644 index 0000000..19d7260 --- /dev/null +++ b/src/lcd/e3v2/proui/endstop_diag.cpp @@ -0,0 +1,113 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * DWIN Endstops diagnostic page for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 1.2.2 + * Date: 2022/02/24 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "dwin_defines.h" + +#if HAS_ESDIAG + +#include "endstop_diag.h" + +#include "../../../core/types.h" +#include "../../marlinui.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin_popup.h" +#include "dwin.h" + +#if HAS_FILAMENT_SENSOR + #include "../../../feature/runout.h" +#endif + +#if HAS_BED_PROBE + #include "../../../module/probe.h" +#endif + +ESDiagClass ESDiag; + +void draw_es_label(FSTR_P const flabel=nullptr) { + DWINUI::cursor.x = 40; + if (flabel) DWINUI::Draw_String(F(flabel)); + DWINUI::Draw_String(F(": ")); + DWINUI::MoveBy(0, 25); +} + +void draw_es_state(const bool is_hit) { + const uint8_t LM = 130; + DWINUI::cursor.x = LM; + DWIN_Draw_Rectangle(1, HMI_data.PopupBg_color, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20); + is_hit ? DWINUI::Draw_String(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::Draw_String(RGB(16,63,16), F(STR_ENDSTOP_OPEN)); + DWINUI::MoveBy(0, 25); +} + +void ESDiagClass::Draw() { + Title.ShowCaption(F("End-stops Diagnostic")); + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + DWINUI::Draw_Button(BTN_Continue, 86, 250); + DWINUI::cursor.y = 80; + #define ES_LABEL(S) draw_es_label(F(STR_##S)) + #if HAS_X_MIN + ES_LABEL(X_MIN); + #endif + #if HAS_Y_MIN + ES_LABEL(Y_MIN); + #endif + #if HAS_Z_MIN + ES_LABEL(Z_MIN); + #endif + #if HAS_FILAMENT_SENSOR + draw_es_label(F(STR_FILAMENT)); + #endif + Update(); +} + +void ESDiagClass::Update() { + DWINUI::cursor.y = 80; + #define ES_REPORT(S) draw_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING) + #if HAS_X_MIN + ES_REPORT(X_MIN); + #endif + #if HAS_Y_MIN + ES_REPORT(Y_MIN); + #endif + #if HAS_Z_MIN + ES_REPORT(Z_MIN); + #endif + #if HAS_FILAMENT_SENSOR + draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE); + #endif + DWIN_UpdateLCD(); +} + +#endif // HAS_ESDIAG +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/endstop_diag.h b/src/lcd/e3v2/proui/endstop_diag.h new file mode 100644 index 0000000..316a1e1 --- /dev/null +++ b/src/lcd/e3v2/proui/endstop_diag.h @@ -0,0 +1,37 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * DWIN End Stops diagnostic page for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 1.2.3 + * Date: 2022/02/24 + */ + +class ESDiagClass { +public: + void Draw(); + void Update(); +}; + +extern ESDiagClass ESDiag; diff --git a/src/lcd/e3v2/proui/gcode_preview.cpp b/src/lcd/e3v2/proui/gcode_preview.cpp new file mode 100644 index 0000000..adb23a9 --- /dev/null +++ b/src/lcd/e3v2/proui/gcode_preview.cpp @@ -0,0 +1,258 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * DWIN g-code thumbnail preview + * Author: Miguel A. Risco-Castillo + * version: 2.1 + * Date: 2021/06/19 + * + * This program 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 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 Lesser General Public License + * along with this program. If not, see . + * + * For commercial applications additional licenses can be requested + */ + +#include "../../../inc/MarlinConfigPre.h" +#if ENABLED(DWIN_LCD_PROUI) + +#include "dwin_defines.h" + +#if HAS_GCODE_PREVIEW + +#include "../../../core/types.h" +#include "../../marlinui.h" +#include "../../../sd/cardreader.h" +#include "../../../MarlinCore.h" // for wait_for_user +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin.h" +#include "dwin_popup.h" +#include "base64.hpp" +#include "gcode_preview.h" + +typedef struct { + char name[13] = ""; //8.3 + null + uint32_t thumbstart = 0; + int thumbsize = 0; + int thumbheight = 0; + int thumbwidth = 0; + uint8_t *thumbdata = nullptr; + float time = 0; + float filament = 0; + float layer = 0; + float width = 0; + float height = 0; + float length = 0; + void setname(const char * const fn); + void clear(); +} fileprop_t; +fileprop_t fileprop; + +void fileprop_t::setname(const char * const fn) { + const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); + memcpy(&name[0], fn, len); + name[len] = '\0'; +} + +void fileprop_t::clear() { + fileprop.name[0] = '\0'; + fileprop.thumbstart = 0; + fileprop.thumbsize = 0; + fileprop.thumbheight = 0; + fileprop.thumbwidth = 0; + fileprop.thumbdata = nullptr; + fileprop.time = 0; + fileprop.filament = 0; + fileprop.layer = 0; + fileprop.height = 0; + fileprop.width = 0; + fileprop.length = 0; +} + +void Get_Value(char *buf, const char * const key, float &value) { + char num[10] = ""; + char * posptr = 0; + uint8_t i = 0; + if (!!value) return; + posptr = strstr(buf, key); + if (posptr != nullptr) { + while (i < sizeof(num)) { + char c = posptr[0]; + if (!ISEOL(c) && (c != 0)) { + if ((c > 47 && c < 58) || (c == '.')) num[i++] = c; + posptr++; + } + else { + num[i] = '\0'; + value = atof(num); + return; + } + } + } +} + +bool Has_Preview() { + const char * tbstart = "; thumbnail begin 230x180"; + char * posptr = 0; + uint8_t nbyte = 1; + uint32_t indx = 0; + char buf[256]; + float tmp = 0; + + fileprop.clear(); + fileprop.setname(card.filename); + + card.openFileRead(fileprop.name); + + while ((nbyte > 0) && (indx < 4 * sizeof(buf)) && !fileprop.thumbstart) { + nbyte = card.read(buf, sizeof(buf) - 1); + if (nbyte > 0) { + buf[nbyte] = '\0'; + Get_Value(buf, ";TIME:", fileprop.time); + Get_Value(buf, ";Filament used:", fileprop.filament); + Get_Value(buf, ";Layer height:", fileprop.layer); + Get_Value(buf, ";MINX:", tmp); + Get_Value(buf, ";MAXX:", fileprop.width); + fileprop.width -= tmp; + tmp = 0; + Get_Value(buf, ";MINY:", tmp); + Get_Value(buf, ";MAXY:", fileprop.length); + fileprop.length -= tmp; + tmp = 0; + Get_Value(buf, ";MINZ:", tmp); + Get_Value(buf, ";MAXZ:", fileprop.height); + fileprop.height -= tmp; + posptr = strstr(buf, tbstart); + if (posptr != NULL) { + fileprop.thumbstart = indx + (posptr - &buf[0]); + } + else { + indx += _MAX(10, nbyte - (signed)strlen(tbstart)); + card.setIndex(indx); + } + } + } + + if (!fileprop.thumbstart) { + card.closefile(); + LCD_MESSAGE_F("Thumbnail not found"); + return 0; + } + + // Get the size of the thumbnail + card.setIndex(fileprop.thumbstart + strlen(tbstart)); + for (uint8_t i = 0; i < 16; i++) { + char c = card.get(); + if (!ISEOL(c)) { + buf[i] = c; + } + else { + buf[i] = 0; + break; + } + } + fileprop.thumbsize = atoi(buf); + + // Exit if there isn't a thumbnail + if (!fileprop.thumbsize) { + card.closefile(); + LCD_MESSAGE_F("Invalid Thumbnail Size"); + return 0; + } + + uint16_t readed = 0; + uint8_t buf64[fileprop.thumbsize]; + + fileprop.thumbdata = new uint8_t[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail + + while (readed < fileprop.thumbsize) { + uint8_t c = card.get(); + if (!ISEOL(c) && (c != ';') && (c != ' ')) { + buf64[readed] = c; + readed++; + } + } + card.closefile(); + buf64[readed] = 0; + + fileprop.thumbsize = decode_base64(buf64, fileprop.thumbdata); card.closefile(); + DWINUI::WriteToSRAM(0x00, fileprop.thumbsize, fileprop.thumbdata); + delete[] fileprop.thumbdata; + return true; +} + +void Preview_DrawFromSD() { + if (Has_Preview()) { + char buf[46]; + char str_1[6] = ""; + char str_2[6] = ""; + char str_3[6] = ""; + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, 0, DWIN_WIDTH, STATUS_Y - 1); + if (fileprop.time) { + sprintf_P(buf, PSTR("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60); + DWINUI::Draw_String(20, 10, buf); + } + if (fileprop.filament) { + sprintf_P(buf, PSTR("Filament used: %s m"), dtostrf(fileprop.filament, 1, 2, str_1)); + DWINUI::Draw_String(20, 30, buf); + } + if (fileprop.layer) { + sprintf_P(buf, PSTR("Layer height: %s mm"), dtostrf(fileprop.layer, 1, 2, str_1)); + DWINUI::Draw_String(20, 50, buf); + } + if (fileprop.width) { + sprintf_P(buf, PSTR("Volume: %sx%sx%s mm"), dtostrf(fileprop.width, 1, 1, str_1), dtostrf(fileprop.length, 1, 1, str_2), dtostrf(fileprop.height, 1, 1, str_3)); + DWINUI::Draw_String(20, 70, buf); + } + DWINUI::Draw_Button(BTN_Print, 26, 290); + DWINUI::Draw_Button(BTN_Cancel, 146, 290); + DWIN_ICON_Show(0, 0, 1, 21, 90, 0x00); + Draw_Select_Highlight(true, 290); + DWIN_UpdateLCD(); + } + else { + HMI_flag.select_flag = 1; + wait_for_user = false; + } +} + +bool Preview_Valid() { + return !!fileprop.thumbstart; +} + +void Preview_Reset() { + fileprop.thumbsize = 0; +} + +#endif // HAS_GCODE_PREVIEW +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/gcode_preview.h b/src/lcd/e3v2/proui/gcode_preview.h new file mode 100644 index 0000000..4417084 --- /dev/null +++ b/src/lcd/e3v2/proui/gcode_preview.h @@ -0,0 +1,27 @@ +/** + * DWIN g-code thumbnail preview + * Author: Miguel A. Risco-Castillo + * version: 2.1 + * Date: 2021/06/19 + * + * This program 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 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 Lesser General Public License + * along with this program. If not, see . + * + * For commercial applications additional licenses can be requested + */ + +#pragma once + +void Preview_DrawFromSD(); +bool Preview_Valid(); +void Preview_Reset(); diff --git a/src/lcd/e3v2/proui/lockscreen.cpp b/src/lcd/e3v2/proui/lockscreen.cpp new file mode 100644 index 0000000..86c2095 --- /dev/null +++ b/src/lcd/e3v2/proui/lockscreen.cpp @@ -0,0 +1,80 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * Lock screen implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 2.2.0 + * Date: 2022/04/11 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "dwin_defines.h" + +#if HAS_LOCKSCREEN + +#include "dwinui.h" +#include "dwin.h" +#include "lockscreen.h" + +LockScreenClass lockScreen; + +uint8_t LockScreenClass::lock_pos = 0; +bool LockScreenClass::unlocked = false; +uint8_t LockScreenClass::rprocess = 0; + +void LockScreenClass::init() { + lock_pos = 0; + unlocked = false; + draw(); +} + +void LockScreenClass::draw() { + Title.SetCaption(GET_TEXT_F(MSG_LOCKSCREEN)); + DWINUI::ClearMainArea(); + DWINUI::Draw_Icon(ICON_LOGO, 71, 120); // CREALITY logo + DWINUI::Draw_CenteredString(Color_White, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED)); + DWINUI::Draw_CenteredString(Color_White, 200, GET_TEXT_F(MSG_LOCKSCREEN_UNLOCK)); + DWINUI::Draw_CenteredString(Color_White, 240, F("-> | <-")); + DWIN_Draw_Box(1, HMI_data.Barfill_Color, 0, 260, DWIN_WIDTH, 20); + DWIN_Draw_VLine(Color_Yellow, lock_pos * DWIN_WIDTH / 255, 260, 20); + DWIN_UpdateLCD(); +} + +void LockScreenClass::onEncoder(EncoderState encoder_diffState) { + switch (encoder_diffState) { + case ENCODER_DIFF_CW: lock_pos += 8; break; + case ENCODER_DIFF_CCW: lock_pos -= 8; break; + case ENCODER_DIFF_ENTER: unlocked = (lock_pos == 128); break; + default: break; + } + DWIN_Draw_Box(1, HMI_data.Barfill_Color, 0, 260, DWIN_WIDTH, 20); + DWIN_Draw_VLine(Color_Yellow, lock_pos * DWIN_WIDTH / 255, 260, 20); + DWIN_UpdateLCD(); +} + +#endif // HAS_LOCKSCREEN + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/lockscreen.h b/src/lcd/e3v2/proui/lockscreen.h new file mode 100644 index 0000000..83d5530 --- /dev/null +++ b/src/lcd/e3v2/proui/lockscreen.h @@ -0,0 +1,46 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * Lock screen implementation for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 2.2.0 + * Date: 2022/04/11 + */ + +#include "../common/encoder.h" +#include + +class LockScreenClass { +private: + static bool unlocked; + static uint8_t lock_pos; +public: + static uint8_t rprocess; + static void init(); + static void onEncoder(EncoderState encoder_diffState); + static void draw(); + static bool isUnlocked() { return unlocked; } +}; + +extern LockScreenClass lockScreen; diff --git a/src/lcd/e3v2/proui/menus.cpp b/src/lcd/e3v2/proui/menus.cpp new file mode 100644 index 0000000..85594fe --- /dev/null +++ b/src/lcd/e3v2/proui/menus.cpp @@ -0,0 +1,566 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * Menu functions for ProUI + * Author: Miguel A. Risco-Castillo + * Version: 1.5.1 + * Date: 2022/05/23 + * + * This program 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 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "../common/encoder.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin.h" +#include "menus.h" + +int8_t MenuItemTotal = 0; +int8_t MenuItemCount = 0; +MenuItemClass** MenuItems = nullptr; +MenuClass *CurrentMenu = nullptr; +MenuClass *PreviousMenu = nullptr; +void (*onMenuDraw)(MenuClass* menu) = nullptr; +void (*onCursorErase)(const int8_t line) = nullptr; +void (*onCursorDraw)(const int8_t line) = nullptr; +MenuData_t MenuData; + +// Menuitem Drawing functions ================================================= + +void Draw_Title(TitleClass* title) { + DWIN_Draw_Rectangle(1, HMI_data.TitleBg_color, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); + if (title->frameid) + DWIN_Frame_AreaCopy(title->frameid, title->frame.left, title->frame.top, title->frame.right, title->frame.bottom, 14, (TITLE_HEIGHT - (title->frame.bottom - title->frame.top)) / 2 - 1); + else + DWIN_Draw_String(false, DWIN_FONT_HEAD, HMI_data.TitleTxt_color, HMI_data.TitleBg_color, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, title->caption); +} + +void Draw_Menu(MenuClass* menu) { + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + DWIN_Draw_Rectangle(1, DWINUI::backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); +} + +void Draw_Menu_Cursor(const int8_t line) { + const uint16_t ypos = MYPOS(line); + DWINUI::Draw_Box(1, HMI_data.Cursor_color, {0, ypos, 15, MLINE - 1}); +} + +void Erase_Menu_Cursor(const int8_t line) { + const uint16_t ypos = MYPOS(line); + DWINUI::Draw_Box(1, HMI_data.Background_Color, {0, ypos, 15, MLINE - 1}); +} + +void Draw_Menu_Line(const uint8_t line, const uint8_t icon /*=0*/, const char * const label /*=nullptr*/, bool more /*=false*/) { + if (icon) DWINUI::Draw_Icon(icon, ICOX, MBASE(line) - 3); + if (label) DWINUI::Draw_String(LBLX, MBASE(line) - 1, (char*)label); + if (more) DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); +} + +void Draw_Chkb_Line(const uint8_t line, const bool checked) { + DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); +} + +void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value /*=0*/) { + DWINUI::Draw_Signed_Int(HMI_data.Text_Color, bcolor, iNum , VALX, MBASE(line) - 1, value); +} + +void onDrawMenuItem(MenuItemClass* menuitem, int8_t line) { + if (menuitem->icon) DWINUI::Draw_Icon(menuitem->icon, ICOX, MBASE(line) - 3); + if (menuitem->frameid) + DWIN_Frame_AreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); + else if (menuitem->caption) + DWINUI::Draw_String(LBLX, MBASE(line) - 1, menuitem->caption); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); +} + +void onDrawSubMenu(MenuItemClass* menuitem, int8_t line) { + onDrawMenuItem(menuitem, line); + DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3); +} + +void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, int32_t value) { + onDrawMenuItem(menuitem, line); + Draw_Menu_IntValue(HMI_data.Background_Color, line, 4, value); +} + +void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line) { + const int16_t value = *(int16_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line) { + const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line) { + const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value) { + onDrawMenuItem(menuitem, line); + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); +} + +void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line) { + const float value = *(float*)static_cast(menuitem)->value; + const int8_t dp = UNITFDIGITS; + onDrawFloatMenu(menuitem, line, dp, value); +} + +void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line) { + const float value = *(float*)static_cast(menuitem)->value; + onDrawFloatMenu(menuitem, line, 2, value); +} + +void onDrawPFloat3Menu(MenuItemClass* menuitem, int8_t line) { + const float value = *(float*)static_cast(menuitem)->value; + onDrawFloatMenu(menuitem, line, 3, value); +} + +void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked) { + onDrawMenuItem(menuitem, line); + Draw_Chkb_Line(line, checked); +} + +void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line) { + const bool val = *(bool*)static_cast(menuitem)->value; + onDrawChkbMenu(menuitem, line, val); +} + +void DrawItemEdit() { + switch (checkkey) { + case SetIntNoDraw: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case SetInt: + case SetPInt: DWINUI::Draw_Signed_Int(HMI_data.Text_Color, HMI_data.Selected_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, MenuData.Value); break; + case SetFloat: + case SetPFloat: DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, MenuData.dp, VALX - MenuData.dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), MenuData.Value / POW(10, MenuData.dp)); break; + default: break; + } +} + +//----------------------------------------------------------------------------- +// On click functions +//----------------------------------------------------------------------------- + +// Generic onclick event without draw +// process: process id HMI destiny +// lo: low limit +// hi: high limit +// dp: decimal places, 0 for integers +// val: value / scaled value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + checkkey = process; + MenuData.MinValue = lo; + MenuData.MaxValue = hi; + MenuData.dp = dp; + MenuData.Apply = Apply; + MenuData.LiveUpdate = LiveUpdate; + MenuData.Value = constrain(val, lo, hi); + EncoderRate.enabled = true; +} + +// Generic onclick event for integer values +// process: process id HMI destiny +// lo: scaled low limit +// hi: scaled high limit +// val: value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + SetOnClick(process, lo, hi, 0, val, Apply, LiveUpdate); + Draw_Menu_IntValue(HMI_data.Selected_Color, CurrentMenu->line(), 4, MenuData.Value); +} + +// Generic onclick event for float values +// process: process id HMI destiny +// lo: scaled low limit +// hi: scaled high limit +// val: value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + const int32_t value = round(val * POW(10, dp)); + SetOnClick(process, lo * POW(10, dp), hi * POW(10, dp), dp, value, Apply, LiveUpdate); + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), val); +} + +// Generic onclick event for integer values +// lo: scaled low limit +// hi: scaled high limit +// val: value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + SetValueOnClick(SetInt, lo, hi, val, Apply, LiveUpdate); +} + +// Generic onclick event for set pointer to 16 bit uinteger values +// lo: low limit +// hi: high limit +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + MenuData.P_Int = (int16_t*)static_cast(CurrentMenu->SelectedItem())->value; + const int32_t value = *MenuData.P_Int; + SetValueOnClick(SetPInt, lo, hi, value, Apply, LiveUpdate); +} + +// Generic onclick event for float values +// process: process id HMI destiny +// lo: low limit +// hi: high limit +// dp: decimal places +// val: value +void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + SetValueOnClick(SetFloat, lo, hi, dp, val, Apply, LiveUpdate); +} + +// Generic onclick event for set pointer to float values +// lo: low limit +// hi: high limit +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + MenuData.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; + SetValueOnClick(SetPFloat, lo, hi, dp, *MenuData.P_Float, Apply, LiveUpdate); +} + +// HMI Control functions ====================================================== + +// Generic menu control using the encoder +void HMI_Menu() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (CurrentMenu) { + if (encoder_diffState == ENCODER_DIFF_ENTER) + CurrentMenu->onClick(); + else + CurrentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); + } +} + +// Get an integer value using the encoder without draw anything +// lo: low limit +// hi: high limit +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) { + const int32_t cval = MenuData.Value; + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (Apply_Encoder(encoder_diffState, MenuData.Value)) { + EncoderRate.enabled = false; + checkkey = Menu; + return 2; + } + LIMIT(MenuData.Value, lo, hi); + } + return int8_t(cval != MenuData.Value); +} + +// Get an integer value using the encoder +// lo: low limit +// hi: high limit +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t HMI_GetInt(const int32_t lo, const int32_t hi) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (Apply_Encoder(encoder_diffState, MenuData.Value)) { + EncoderRate.enabled = false; + DWINUI::Draw_Signed_Int(HMI_data.Text_Color, HMI_data.Background_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, MenuData.Value); + checkkey = Menu; + return 2; + } + LIMIT(MenuData.Value, lo, hi); + DrawItemEdit(); + return 1; + } + return 0; +} + +// Set an integer using the encoder +void HMI_SetInt() { + int8_t val = HMI_GetInt(MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; break; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Set an integer without drawing +void HMI_SetIntNoDraw() { + int8_t val = HMI_GetIntNoDraw(MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; break; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Set an integer pointer variable using the encoder +void HMI_SetPInt() { + int8_t val = HMI_GetInt(MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: *MenuData.P_Int = MenuData.Value; if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Get a scaled float value using the encoder +// dp: decimal places +// lo: scaled low limit +// hi: scaled high limit +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t HMI_GetFloat(uint8_t dp, int32_t lo, int32_t hi) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (Apply_Encoder(encoder_diffState, MenuData.Value)) { + EncoderRate.enabled = false; + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), MenuData.Value / POW(10, dp)); + checkkey = Menu; + return 2; + } + LIMIT(MenuData.Value, lo, hi); + DrawItemEdit(); + return 1; + } + return 0; +} + +// Set a scaled float using the encoder +void HMI_SetFloat() { + const int8_t val = HMI_GetFloat(MenuData.dp, MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Set a scaled float pointer variable using the encoder +void HMI_SetPFloat() { + const int8_t val = HMI_GetFloat(MenuData.dp, MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: *MenuData.P_Float = MenuData.Value / POW(10, MenuData.dp); if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Menu Classes =============================================================== + +MenuClass::MenuClass() { + selected = 0; + topline = 0; +} + +void MenuClass::draw() { + MenuTitle.draw(); + if (onMenuDraw != nullptr) onMenuDraw(this); + for (int8_t i = 0; i < MenuItemCount; i++) + MenuItems[i]->draw(i - topline); + if (onCursorDraw != nullptr) onCursorDraw(line()); + DWIN_UpdateLCD(); +} + +void MenuClass::onScroll(bool dir) { + int8_t sel = selected; + if (dir) sel++; else sel--; + LIMIT(sel, 0, MenuItemCount - 1); + if (sel != selected) { + if (onCursorErase != nullptr) onCursorErase(line()); + DWIN_UpdateLCD(); + if ((sel - topline) == TROWS) { + DWIN_Frame_AreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); + topline++; + MenuItems[sel]->draw(TROWS - 1); + } + if ((sel < topline)) { + DWIN_Frame_AreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); + topline--; + MenuItems[sel]->draw(0); + } + selected = sel; + if (onCursorDraw != nullptr) onCursorDraw(line()); + DWIN_UpdateLCD(); + } +} + +void MenuClass::onClick() { + if (MenuItems[selected]->onClick != nullptr) (*MenuItems[selected]->onClick)(); +} + +MenuItemClass *MenuClass::SelectedItem() { + return MenuItems[selected]; +} + +MenuItemClass** MenuClass::Items() { + return MenuItems; +} + +int8_t MenuClass::count() { + return MenuItemCount; +}; + +/* MenuItem Class ===========================================================*/ + +MenuItemClass::MenuItemClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) { + icon = cicon; + onClick = onclick; + onDraw = ondraw; + const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text)); + memcpy(&caption[0], text, len); + caption[len] = '\0'; +} + +MenuItemClass::MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) { + icon = cicon; + onClick = onclick; + onDraw = ondraw; + caption[0] = '\0'; + frameid = id; + frame = { x1, y1, x2, y2 }; +} + +void MenuItemClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + caption[0] = '\0'; + frameid = id; + frame = { x1, y1, x2, y2 }; +} + +void MenuItemClass::draw(int8_t line) { + if (!WITHIN(line, 0, TROWS - 1)) return; + if (onDraw != nullptr) (*onDraw)(this, line); +}; + +void MenuItemClass::redraw() { + draw(CurrentMenu->line(this->pos)); +} + +MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemClass(cicon, text, ondraw, onclick) { + value = val; +}; + +// Menu auxiliary functions =================================================== + +void MenuItemsClear() { + if (MenuItems == nullptr) return; + for (int8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i]; + delete[] MenuItems; + MenuItems = nullptr; + MenuItemCount = 0; + MenuItemTotal = 0; +} + +void MenuItemsPrepare(int8_t totalitems) { + MenuItemsClear(); + MenuItemTotal = totalitems; + MenuItems = new MenuItemClass*[totalitems]; +} + +MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem) { + MenuItems[MenuItemCount] = menuitem; + menuitem->pos = MenuItemCount++; + return menuitem; +} + +MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text/*=nullptr*/, void (*ondraw)(MenuItemClass* menuitem, int8_t line)/*=nullptr*/, void (*onclick)()/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + MenuItemClass* menuitem = new MenuItemClass(cicon, text, ondraw, onclick); + return MenuItemsAdd(menuitem); + } + else return nullptr; +} + +MenuItemClass* MenuItemsAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)/*=nullptr*/, void (*onclick)()/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + MenuItemClass* menuitem = new MenuItemClass(cicon, id, x1, y1, x2, y2, ondraw, onclick); + return MenuItemsAdd(menuitem); + } + else return nullptr; +} + +MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) { + if (MenuItemCount < MenuItemTotal) { + MenuItemClass* menuitem = new MenuItemPtrClass(cicon, text, ondraw, onclick, val); + return MenuItemsAdd(menuitem); + } + else return nullptr; +} + +bool SetMenu(MenuClass* &menu, FSTR_P title, int8_t totalitems) { + if (!menu) menu = new MenuClass(); + const bool NotCurrent = (CurrentMenu != menu); + if (NotCurrent) { + menu->MenuTitle.SetCaption(title); + MenuItemsPrepare(totalitems); + } + return NotCurrent; +} + +void UpdateMenu(MenuClass* &menu) { + if (!menu) return; + if (CurrentMenu != menu) { + PreviousMenu = CurrentMenu; + CurrentMenu = menu; + } + menu->draw(); +} + +void ReDrawMenu(const bool force/*=false*/) { + if (CurrentMenu && (force || checkkey == Menu)) CurrentMenu->draw(); + if (force) DrawItemEdit(); +} + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/menus.h b/src/lcd/e3v2/proui/menus.h new file mode 100644 index 0000000..6a5f878 --- /dev/null +++ b/src/lcd/e3v2/proui/menus.h @@ -0,0 +1,188 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * Menu functions for ProUI + * Author: Miguel A. Risco-Castillo + * Version: 1.5.1 + * Date: 2022/05/23 + * + * This program 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 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 Lesser General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include "dwinui.h" + +typedef struct { + int32_t MaxValue = 0; // Auxiliar max integer/scaled float value + int32_t MinValue = 0; // Auxiliar min integer/scaled float value + int8_t dp = 0; // Auxiliar decimal places + int32_t Value = 0; // Auxiliar integer / scaled float value + int16_t *P_Int = nullptr; // Auxiliar pointer to 16 bit integer variable + float *P_Float = nullptr; // Auxiliar pointer to float variable + void (*Apply)() = nullptr; // Auxiliar apply function + void (*LiveUpdate)() = nullptr; // Auxiliar live update function +} MenuData_t; + +extern MenuData_t MenuData; +extern void (*onCursorErase)(const int8_t line); +extern void (*onCursorDraw)(const int8_t line); + +// Auxiliary Macros =========================================================== + +// Create and add a MenuItem object to the menu array +#define BACK_ITEM(H) MenuItemsAdd(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawMenuItem, H) +#define MENU_ITEM(V...) MenuItemsAdd(V) +#define EDIT_ITEM(V...) MenuItemsAdd(V) +#define MENU_ITEM_F(I,L,V...) MenuItemsAdd(I, GET_TEXT_F(L), V) +#define EDIT_ITEM_F(I,L,V...) MenuItemsAdd(I, GET_TEXT_F(L), V) + +// Menu Classes =============================================================== + +class MenuItemClass { +protected: +public: + int8_t pos = 0; + uint8_t icon = 0; + char caption[32] = ""; + uint8_t frameid = 0; + rect_t frame = {0}; + void (*onDraw)(MenuItemClass* menuitem, int8_t line) = nullptr; + void (*onClick)() = nullptr; + MenuItemClass() {}; + MenuItemClass(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr); + // MenuItemClass(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) : MenuItemClass(cicon, FTOP(text), ondraw, onclick){} + MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr); + void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); + virtual ~MenuItemClass(){}; + virtual void draw(int8_t line); + void redraw(); +}; + +class MenuItemPtrClass: public MenuItemClass { +public: + void *value = nullptr; + using MenuItemClass::MenuItemClass; + MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val); + MenuItemPtrClass(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemPtrClass(cicon, FTOP(text), ondraw, onclick, val){} +}; + +class MenuClass { +public: + int8_t topline = 0; + int8_t selected = 0; + TitleClass MenuTitle; + MenuClass(); + virtual ~MenuClass(){}; + inline int8_t line() { return selected - topline; }; + inline int8_t line(uint8_t pos) {return pos - topline; }; + int8_t count(); + virtual void draw(); + virtual void onScroll(bool dir); + void onClick(); + MenuItemClass* SelectedItem(); + static MenuItemClass** Items(); +}; +extern MenuClass *CurrentMenu; +extern MenuClass *PreviousMenu; +extern void (*onMenuDraw)(MenuClass* menu); + +// Menuitem Drawing functions ================================================= + +void Draw_Title(TitleClass* title); +void Draw_Menu(MenuClass* menu); +void Draw_Menu_Cursor(const int8_t line); +void Erase_Menu_Cursor(const int8_t line); +void Draw_Menu_Line(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false); +void Draw_Chkb_Line(const uint8_t line, const bool checked); +void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value=0); +void onDrawMenuItem(MenuItemClass* menuitem, int8_t line); +void onDrawSubMenu(MenuItemClass* menuitem, int8_t line); +void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, int32_t value); +void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line); +void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line); +void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line); +void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value); +void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line); +void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line); +void onDrawPFloat3Menu(MenuItemClass* menuitem, int8_t line); +void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked); +void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line); + +// On click functions ========================================================= + +void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); + +// HMI user control functions ================================================= + +void HMI_Menu(); +void HMI_SetInt(); +void HMI_SetPInt(); +void HMI_SetIntNoDraw(); +void HMI_SetFloat(); +void HMI_SetPFloat(); + +// Menu auxiliary functions =================================================== + +// Create a new menu +bool SetMenu(MenuClass* &menu, FSTR_P title, int8_t totalitems); + +//Update the Menu and Draw if it is valid +void UpdateMenu(MenuClass* &menu); + +//Redraw the current Menu if it is valid +void ReDrawMenu(const bool force=false); + +// Clear MenuItems array and free MenuItems elements +void MenuItemsClear(); + +// Prepare MenuItems array +void MenuItemsPrepare(int8_t totalitems); + +// Add elements to the MenuItems array +MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr); +inline MenuItemClass* MenuItemsAdd(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) { + return MenuItemsAdd(cicon, FTOP(text), ondraw, onclick); +} +MenuItemClass* MenuItemsAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr); +MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val); +inline MenuItemClass* MenuItemsAdd(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) { + return MenuItemsAdd(cicon, FTOP(text), ondraw, onclick, val); +} diff --git a/src/lcd/e3v2/proui/meshviewer.cpp b/src/lcd/e3v2/proui/meshviewer.cpp new file mode 100644 index 0000000..2511d33 --- /dev/null +++ b/src/lcd/e3v2/proui/meshviewer.cpp @@ -0,0 +1,144 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * Mesh Viewer for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * version: 3.14.1 + * Date: 2022/04/11 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if BOTH(DWIN_LCD_PROUI, HAS_MESH) + +#include "../../../core/types.h" +#include "../../marlinui.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin.h" +#include "dwin_popup.h" +#include "../../../feature/bedlevel/bedlevel.h" +#include "meshviewer.h" + +#if ENABLED(AUTO_BED_LEVELING_UBL) + #include "bedlevel_tools.h" +#endif + +MeshViewerClass MeshViewer; + +void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey) { + const int8_t mx = 25, my = 25; // Margins + const int16_t stx = (DWIN_WIDTH - 2 * mx) / (sizex - 1), // Steps + sty = (DWIN_WIDTH - 2 * my) / (sizey - 1); + const int8_t rmax = _MIN(mx - 2, stx / 2); + const int8_t rmin = 7; + int16_t zmesh[sizex][sizey]; + #define px(xp) (mx + (xp) * stx) + #define py(yp) (30 + DWIN_WIDTH - my - (yp) * sty) + #define rm(z) ((z - minz) * (rmax - rmin) / _MAX(1, (maxz - minz)) + rmin) + #define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 18, py(yp) - 6, zv) + #define DrawMeshHLine(yp) DWIN_Draw_HLine(HMI_data.SplitLine_Color, px(0), py(yp), DWIN_WIDTH - 2 * mx) + #define DrawMeshVLine(xp) DWIN_Draw_VLine(HMI_data.SplitLine_Color, px(xp), py(sizey - 1), DWIN_WIDTH - 2 * my) + int16_t maxz =-32000; int16_t minz = 32000; + LOOP_L_N(y, sizey) LOOP_L_N(x, sizex) { + const float v = isnan(zval[x][y]) ? 0 : round(zval[x][y] * 100); + zmesh[x][y] = v; + NOLESS(maxz, v); + NOMORE(minz, v); + } + max = (float)maxz / 100; + min = (float)minz / 100; + DWINUI::ClearMainArea(); + DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(sizex - 1), py(sizey - 1)); + LOOP_S_L_N(x, 1, sizex - 1) DrawMeshVLine(x); + LOOP_S_L_N(y, 1, sizey - 1) DrawMeshHLine(y); + LOOP_L_N(y, sizey) { + hal.watchdog_refresh(); + LOOP_L_N(x, sizex) { + uint16_t color = DWINUI::RainbowInt(zmesh[x][y], _MIN(-5, minz), _MAX(5, maxz)); + uint8_t radius = rm(zmesh[x][y]); + DWINUI::Draw_FillCircle(color, px(x), py(y), radius); + if (sizex < 9) { + if (zmesh[x][y] == 0) DWINUI::Draw_Float(font6x12, 1, 2, px(x) - 12, py(y) - 6, 0); + else DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 18, py(y) - 6, zval[x][y]); + } + else { + char str_1[9]; + str_1[0] = 0; + switch (zmesh[x][y]) { + case -999 ... -100: + DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 18, py(y) - 6, zval[x][y]); + break; + case -99 ... -1: + sprintf_P(str_1, PSTR("-.%02i"), -zmesh[x][y]); + break; + case 0: + DWIN_Draw_String(false, font6x12, DWINUI::textcolor, DWINUI::backcolor, px(x) - 4, py(y) - 6, "0"); + break; + case 1 ... 99: + sprintf_P(str_1, PSTR(".%02i"), zmesh[x][y]); + break; + case 100 ... 999: + DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 18, py(y) - 6, zval[x][y]); + break; + } + if (str_1[0]) + DWIN_Draw_String(false, font6x12, DWINUI::textcolor, DWINUI::backcolor, px(x) - 12, py(y) - 6, str_1); + } + } + } +} + +void MeshViewerClass::Draw(bool withsave /*= false*/) { + Title.ShowCaption(GET_TEXT_F(MSG_MESH_VIEWER)); + #if USE_UBL_VIEWER + DWINUI::ClearMainArea(); + BedLevelTools.viewer_print_value = true; + BedLevelTools.Draw_Bed_Mesh(-1, 1, 8, 10 + TITLE_HEIGHT); + #else + DrawMesh(bedlevel.z_values, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); + #endif + if (withsave) { + DWINUI::Draw_Button(BTN_Save, 26, 305); + DWINUI::Draw_Button(BTN_Continue, 146, 305); + Draw_Select_Highlight(HMI_flag.select_flag, 305); + } + else + DWINUI::Draw_Button(BTN_Continue, 86, 305); + + #if USE_UBL_VIEWER + BedLevelTools.Set_Mesh_Viewer_Status(); + #else + char str_1[6], str_2[6] = ""; + ui.status_printf(0, F("Mesh minZ: %s, maxZ: %s"), + dtostrf(min, 1, 2, str_1), + dtostrf(max, 1, 2, str_2) + ); + #endif +} + +void Draw_MeshViewer() { MeshViewer.Draw(true); } +void onClick_MeshViewer() { if (HMI_flag.select_flag) SaveMesh(); HMI_ReturnScreen(); } +void Goto_MeshViewer() { if (leveling_is_valid()) Goto_Popup(Draw_MeshViewer, onClick_MeshViewer); else HMI_ReturnScreen(); } + +#endif // DWIN_LCD_PROUI && HAS_MESH diff --git a/src/lcd/e3v2/proui/meshviewer.h b/src/lcd/e3v2/proui/meshviewer.h new file mode 100644 index 0000000..3aafe16 --- /dev/null +++ b/src/lcd/e3v2/proui/meshviewer.h @@ -0,0 +1,40 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * Mesh Viewer for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * version: 3.14.1 + * Date: 2022/04/11 + */ + +class MeshViewerClass { +public: + float max, min; + void Draw(bool withsave = false); + void DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey); +}; + +extern MeshViewerClass MeshViewer; + +void Goto_MeshViewer(); diff --git a/src/lcd/e3v2/proui/plot.cpp b/src/lcd/e3v2/proui/plot.cpp new file mode 100644 index 0000000..cb1f6c2 --- /dev/null +++ b/src/lcd/e3v2/proui/plot.cpp @@ -0,0 +1,99 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * DWIN Single var plot + * Author: Miguel A. Risco-Castillo + * Version: 2.0 + * Date: 2022/01/31 + * + * This program 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 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 Lesser General Public License + * along with this program. If not, see . + * + * For commercial applications additional licenses can be requested + */ + +#include "../../../inc/MarlinConfigPre.h" + +#ifdef DWIN_LCD_PROUI + +#include "dwin_defines.h" + +#if HAS_PIDPLOT + +#include "plot.h" + +#include "../../../core/types.h" +#include "../../marlinui.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin.h" + +#define Plot_Bg_Color RGB( 1, 12, 8) + +PlotClass Plot; + +uint16_t grphpoints, r, x2, y2 = 0; +frame_rect_t grphframe = {0}; +float scale = 0; + +void PlotClass::Draw(const frame_rect_t frame, const float max, const float ref) { + grphframe = frame; + grphpoints = 0; + scale = frame.h / max; + x2 = frame.x + frame.w - 1; + y2 = frame.y + frame.h - 1; + r = round((y2) - ref * scale); + DWINUI::Draw_Box(1, Plot_Bg_Color, frame); + for (uint8_t i = 1; i < 4; i++) if (i * 50 < frame.w) DWIN_Draw_VLine(Line_Color, i * 50 + frame.x, frame.y, frame.h); + DWINUI::Draw_Box(0, Color_White, DWINUI::ExtendFrame(frame, 1)); + DWIN_Draw_HLine(Color_Red, frame.x, r, frame.w); +} + +void PlotClass::Update(const float value) { + if (!scale) return; + uint16_t y = round((y2) - value * scale); + if (grphpoints < grphframe.w) { + DWIN_Draw_Point(Color_Yellow, 1, 1, grphpoints + grphframe.x, y); + } + else { + DWIN_Frame_AreaMove(1, 0, 1, Plot_Bg_Color, grphframe.x, grphframe.y, x2, y2); + if ((grphpoints % 50) == 0) DWIN_Draw_VLine(Line_Color, x2 - 1, grphframe.y + 1, grphframe.h - 2); + DWIN_Draw_Point(Color_Red, 1, 1, x2 - 1, r); + DWIN_Draw_Point(Color_Yellow, 1, 1, x2 - 1, y); + } + grphpoints++; +} + +#endif // HAS_PIDPLOT + +#endif // DWIN_LCD_PROUI diff --git a/src/lcd/e3v2/proui/plot.h b/src/lcd/e3v2/proui/plot.h new file mode 100644 index 0000000..8522c53 --- /dev/null +++ b/src/lcd/e3v2/proui/plot.h @@ -0,0 +1,54 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 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 . + * + */ + +/** + * DWIN Single var plot + * Author: Miguel A. Risco-Castillo + * Version: 1.0 + * Date: 2022/01/30 + * + * This program 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 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 Lesser General Public License + * along with this program. If not, see . + * + * For commercial applications additional licenses can be requested + */ +#pragma once + +#include "dwinui.h" + +class PlotClass { +public: + void Draw(frame_rect_t frame, float max, float ref = 0); + void Update(float value); +}; + +extern PlotClass Plot; diff --git a/src/lcd/e3v2/proui/printstats.cpp b/src/lcd/e3v2/proui/printstats.cpp new file mode 100644 index 0000000..5a7b6c9 --- /dev/null +++ b/src/lcd/e3v2/proui/printstats.cpp @@ -0,0 +1,82 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 . + * + */ + +/** + * Print Stats page for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 1.3.0 + * Date: 2022/02/24 + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if BOTH(DWIN_LCD_PROUI, PRINTCOUNTER) + +#include "printstats.h" + +#include "../../../core/types.h" +#include "../../../MarlinCore.h" +#include "../../marlinui.h" +#include "../../../module/printcounter.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin_popup.h" +#include "dwin.h" + +PrintStatsClass PrintStats; + +void PrintStatsClass::Draw() { + char buf[50] = ""; + char str[30] = ""; + constexpr int8_t MRG = 30; + + Title.ShowCaption(GET_TEXT_F(MSG_INFO_STATS_MENU)); + DWINUI::ClearMainArea(); + Draw_Popup_Bkgd(); + DWINUI::Draw_Button(BTN_Continue, 86, 250); + printStatistics ps = print_job_timer.getStats(); + + sprintf_P(buf, PSTR(S_FMT ": %i"), GET_TEXT(MSG_INFO_PRINT_COUNT), ps.totalPrints); + DWINUI::Draw_String(MRG, 80, buf); + sprintf_P(buf, PSTR(S_FMT ": %i"), GET_TEXT(MSG_INFO_COMPLETED_PRINTS), ps.finishedPrints); + DWINUI::Draw_String(MRG, 100, buf); + duration_t(print_job_timer.getStats().printTime).toDigital(str, true); + sprintf_P(buf, PSTR(S_FMT ": %s"), GET_TEXT(MSG_INFO_PRINT_TIME), str); + DWINUI::Draw_String(MRG, 120, buf); + duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true); + sprintf_P(buf, PSTR(S_FMT ": %s"), GET_TEXT(MSG_INFO_PRINT_LONGEST), str); + DWINUI::Draw_String(MRG, 140, buf); + sprintf_P(buf, PSTR(S_FMT ": %s m"), GET_TEXT(MSG_INFO_PRINT_FILAMENT), dtostrf(ps.filamentUsed / 1000, 1, 2, str)); + DWINUI::Draw_String(MRG, 160, buf); +} + +void PrintStatsClass::Reset() { + print_job_timer.initStats(); + DONE_BUZZ(true); +} + +void Goto_PrintStats() { + PrintStats.Draw(); + HMI_SaveProcessID(WaitResponse); +} + +#endif // DWIN_LCD_PROUI && PRINTCOUNTER diff --git a/src/lcd/e3v2/proui/printstats.h b/src/lcd/e3v2/proui/printstats.h new file mode 100644 index 0000000..705c923 --- /dev/null +++ b/src/lcd/e3v2/proui/printstats.h @@ -0,0 +1,39 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 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 + +/** + * Print Stats page for PRO UI + * Author: Miguel A. Risco-Castillo (MRISCOC) + * Version: 1.3.0 + * Date: 2022/02/24 + */ + +class PrintStatsClass { +public: + static void Draw(); + static void Reset(); +}; + +extern PrintStatsClass PrintStats; + +void Goto_PrintStats();