From 73693bbfc3d13f01c11f1d005f0184e76eae9a5c Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Fri, 17 Nov 2023 00:07:08 -0500 Subject: [PATCH 01/20] Fix typo in stm32f4.ini --- ini/stm32f4.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ini/stm32f4.ini b/ini/stm32f4.ini index 5582a6349a78..f094b96c9bd2 100644 --- a/ini/stm32f4.ini +++ b/ini/stm32f4.ini @@ -733,7 +733,7 @@ debug_tool = jlink upload_protocol = jlink [env:STM32F401RE_creality_stlink] -extends = env:STM32F401RC_creality +extends = env:STM32F401RE_creality debug_tool = stlink upload_protocol = stlink From f60abea53afe43e0e035a7087c1979abdf87f256 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Fri, 17 Nov 2023 03:09:34 -0500 Subject: [PATCH 02/20] Add ProUI feature options The following file changes allows fuller utilization of ProUI features. dwin.h dwin_defines.h SanityCheck.h MarlinConfigPre.h --- Marlin/src/inc/MarlinConfigPre.h | 2 ++ Marlin/src/inc/SanityCheck.h | 4 ++++ Marlin/src/lcd/e3v2/proui/dwin.h | 24 ++++++++++---------- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 28 ++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Marlin/src/inc/MarlinConfigPre.h b/Marlin/src/inc/MarlinConfigPre.h index c2191ab1b74f..df263b98e73f 100644 --- a/Marlin/src/inc/MarlinConfigPre.h +++ b/Marlin/src/inc/MarlinConfigPre.h @@ -60,3 +60,5 @@ #ifndef __MARLIN_DEPS__ #include HAL_PATH(.., inc/Conditionals_adv.h) #endif + +#include "../lcd/e3v2/proui/dwin_defines.h" diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 8796ea224fdc..e825543c6c34 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -2756,6 +2756,10 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #error "JD_TUNE_ITEM requires HAS_JUNCTION_DEVIATION." #elif ENABLED(ADVK_TUNE_ITEM) && DISABLED(LIN_ADVANCE) #error "ADVK_TUNE_ITEM requires LIN_ADVANCE." + #elif ENABLED(MESH_EDIT_MENU) && !HAS_MESH + #error "MESH_EDIT_MENU requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR or AUTO_BED_LEVELING_UBL." + #elif (SDSORT_GCODE == false) && ENABLED(MEDIASORT_MENU_ITEM) + #error "MEDIASORT_MENU_ITEM requires SDSORT_GCODE to be defined 'true'." #endif #endif diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index 9c11cc49167f..d8a655413244 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -39,13 +39,6 @@ #include "../../../feature/leds/leds.h" #endif -#if ANY(BABYSTEPPING, HAS_BED_PROBE) - #define HAS_ZOFFSET_ITEM 1 - #if !HAS_BED_PROBE - #define JUST_BABYSTEP 1 - #endif -#endif - namespace GET_LANG(LCD_LANGUAGE) { #define _MSG_PREHEAT(N) \ LSTR MSG_PREHEAT_##N = _UxGT("Preheat ") PREHEAT_## N ##_LABEL; \ @@ -141,9 +134,12 @@ typedef struct { #if ENABLED(BAUD_RATE_GCODE) bool baud115K = false; #endif - - bool fullManualTramming = false; - bool mediaSort = true; + #if ALL(LCD_BED_TRAMMING, HAS_BED_PROBE) + bool fullManualTramming = false; + #endif + #if ENABLED(MEDIASORT_MENU_ITEM) + bool mediaSort = true; + #endif bool mediaAutoMount = ENABLED(HAS_SD_EXTENDER); #if ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) uint8_t zAfterHoming = DEF_Z_AFTER_HOMING; @@ -151,8 +147,12 @@ typedef struct { #if ALL(LED_CONTROL_MENU, HAS_COLOR_LEDS) LEDColor ledColor = defColorLeds; #endif - bool adaptiveStepSmoothing = true; - bool enablePreview = true; + #if ENABLED(ADAPTIVE_STEP_SMOOTHING) + bool adaptiveStepSmoothing = true; + #endif + #if HAS_GCODE_PREVIEW + bool enablePreview = true; + #endif } hmi_data_t; extern hmi_data_t hmiData; diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index e3526849a808..81826a6ebbd4 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -78,3 +78,31 @@ #define DEF_BEDPIDT TERN(PREHEAT_1_TEMP_BED, PREHEAT_1_TEMP_HOTEND, 60) #define DEF_PIDCYCLES 5 +/** +* ProUI Menu Options +* Choose which feature you would like to Enable or Disable +*/ +#if ENABLED(SDCARD_SORT_ALPHA) + #define MEDIASORT_MENU_ITEM +#endif +#if ENABLED(HAS_FILAMENT_SENSOR) + #define RUNOUT_TUNE_ITEM +#endif +#if ENABLED(POWER_LOSS_RECOVERY) + #define PLR_TUNE_ITEM // Power-loss Recovery option in Tune Menu +#endif +#if ENABLED(HAS_JUNCTION_DEVIATION) + #define JD_TUNE_ITEM // Juntion Deviation item in Tune Menu +#endif +#if ENABLED(LIN_ADVANCE) + #define ADVK_TUNE_ITEM // Linear Advance item in Tune Menu +#endif +#if HAS_MESH + #define MESH_EDIT_MENU // Add a menu to edit mesh points +#endif + +#define HAS_GCODE_PREVIEW 1 +#define HAS_CUSTOM_COLORS 1 // Change display colors +#define HAS_ESDIAG 1 // View End-stop/Runout switch continuity +#define HAS_LOCKSCREEN 1 // Simple lockscreen +#define HAS_SD_EXTENDER 1 // Enable to support SD card extender cables From 3d8088bb92ad02eae152bdad7dd3670d4a8e79c2 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Fri, 17 Nov 2023 03:29:55 -0500 Subject: [PATCH 03/20] fix `SDSORT_GCODE false` warning --- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index 81826a6ebbd4..2d751bb0d713 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -84,6 +84,11 @@ */ #if ENABLED(SDCARD_SORT_ALPHA) #define MEDIASORT_MENU_ITEM + #if ENABLED(MEDIASORT_MENU_ITEM) && (SDSORT_GCODE == false) + // MEDIASORT_MENU_ITEM needs SDSORT_GCODE to be 'true' + #undef SDSORT_GCODE + #define SDSORT_GCODE true + #endif #endif #if ENABLED(HAS_FILAMENT_SENSOR) #define RUNOUT_TUNE_ITEM From 3a461321236a094faf546388c3b8d4bba4a309f7 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Sun, 19 Nov 2023 09:14:00 -0500 Subject: [PATCH 04/20] include #ifdef in MarlinConfigPre.h for DWIN_LCD_PROUI --- Marlin/src/inc/MarlinConfigPre.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Marlin/src/inc/MarlinConfigPre.h b/Marlin/src/inc/MarlinConfigPre.h index df263b98e73f..feac1703d0ba 100644 --- a/Marlin/src/inc/MarlinConfigPre.h +++ b/Marlin/src/inc/MarlinConfigPre.h @@ -61,4 +61,6 @@ #include HAL_PATH(.., inc/Conditionals_adv.h) #endif -#include "../lcd/e3v2/proui/dwin_defines.h" +#ifdef DWIN_LCD_PROUI + #include "../lcd/e3v2/proui/dwin_defines.h" +#endif From 9fe4190d5354d75afad9de1f52b234196f798309 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 20 Nov 2023 00:59:43 -0600 Subject: [PATCH 05/20] enabled --- Marlin/src/inc/MarlinConfigPre.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/inc/MarlinConfigPre.h b/Marlin/src/inc/MarlinConfigPre.h index feac1703d0ba..3772127f3a16 100644 --- a/Marlin/src/inc/MarlinConfigPre.h +++ b/Marlin/src/inc/MarlinConfigPre.h @@ -61,6 +61,6 @@ #include HAL_PATH(.., inc/Conditionals_adv.h) #endif -#ifdef DWIN_LCD_PROUI +#if ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin_defines.h" #endif From cc1715176f4bc1802a544f0fb8b442569f4db46c Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 20 Nov 2023 01:48:49 -0600 Subject: [PATCH 06/20] tweak errors --- Marlin/src/inc/SanityCheck.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index e825543c6c34..e3e390d7e919 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1533,7 +1533,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L * Allow only one bed leveling option to be defined */ #if MANY(AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT, AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_UBL, MESH_BED_LEVELING) - #error "Select only one of: MESH_BED_LEVELING, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT, AUTO_BED_LEVELING_BILINEAR or AUTO_BED_LEVELING_UBL." + #error "Select only one of: MESH_BED_LEVELING, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL." #endif /** @@ -1541,7 +1541,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L */ #if IS_SCARA && ANY(AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT, AUTO_BED_LEVELING_UBL) - #error "SCARA machines can only use AUTO_BED_LEVELING_BILINEAR or MESH_BED_LEVELING leveling." + #error "SCARA machines can only use AUTO_BED_LEVELING_BILINEAR or MESH_BED_LEVELING." #elif ENABLED(AUTO_BED_LEVELING_LINEAR) && !(WITHIN(GRID_MAX_POINTS_X, 2, 255) && WITHIN(GRID_MAX_POINTS_Y, 2, 255)) #error "GRID_MAX_POINTS_[XY] must be between 2 and 255 with AUTO_BED_LEVELING_LINEAR." #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) && !(WITHIN(GRID_MAX_POINTS_X, 3, 255) && WITHIN(GRID_MAX_POINTS_Y, 3, 255)) @@ -1610,7 +1610,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #elif !(ENABLED(MESH_BED_LEVELING) || HAS_ABL_NOT_UBL) #error "LCD_BED_LEVELING requires MESH_BED_LEVELING or AUTO_BED_LEVELING." #elif ENABLED(MESH_EDIT_MENU) && !HAS_MESH - #error "MESH_EDIT_MENU requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR or AUTO_BED_LEVELING_UBL." + #error "MESH_EDIT_MENU requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL." #endif #endif @@ -2746,8 +2746,8 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #error "DWIN_LCD_PROUI requires SDSUPPORT to be enabled." #elif ALL(LCD_BED_LEVELING, PROBE_MANUALLY) #error "DWIN_LCD_PROUI does not support LCD_BED_LEVELING with PROBE_MANUALLY." - #elif ENABLED(MEDIASORT_MENU_ITEM) && DISABLED(SDCARD_SORT_ALPHA) - #error "MEDIASORT_MENU_ITEM requires SDCARD_SORT_ALPHA." + #elif ENABLED(MEDIASORT_MENU_ITEM) && !ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE) + #error "MEDIASORT_MENU_ITEM requires SDCARD_SORT_ALPHA and SDSORT_GCODE." #elif ENABLED(RUNOUT_TUNE_ITEM) && DISABLED(HAS_FILAMENT_SENSOR) #error "RUNOUT_TUNE_ITEM requires HAS_FILAMENT_SENSOR." #elif ENABLED(PLR_TUNE_ITEM) && DISABLED(POWER_LOSS_RECOVERY) @@ -2757,9 +2757,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #elif ENABLED(ADVK_TUNE_ITEM) && DISABLED(LIN_ADVANCE) #error "ADVK_TUNE_ITEM requires LIN_ADVANCE." #elif ENABLED(MESH_EDIT_MENU) && !HAS_MESH - #error "MESH_EDIT_MENU requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR or AUTO_BED_LEVELING_UBL." - #elif (SDSORT_GCODE == false) && ENABLED(MEDIASORT_MENU_ITEM) - #error "MEDIASORT_MENU_ITEM requires SDSORT_GCODE to be defined 'true'." + #error "MESH_EDIT_MENU requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL." #endif #endif From 28b857119da975114f970d6b0230dc026e435620 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 20 Nov 2023 01:56:39 -0600 Subject: [PATCH 07/20] clarify --- Marlin/src/inc/MarlinConfigPre.h | 4 ---- Marlin/src/inc/SanityCheck.h | 12 ----------- Marlin/src/lcd/e3v2/proui/dwin.cpp | 20 +++++++++--------- Marlin/src/lcd/e3v2/proui/dwin.h | 4 ++-- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 26 ++++++++---------------- Marlin/src/lcd/e3v2/proui/lockscreen.cpp | 9 +++++--- 6 files changed, 26 insertions(+), 49 deletions(-) diff --git a/Marlin/src/inc/MarlinConfigPre.h b/Marlin/src/inc/MarlinConfigPre.h index 3772127f3a16..c2191ab1b74f 100644 --- a/Marlin/src/inc/MarlinConfigPre.h +++ b/Marlin/src/inc/MarlinConfigPre.h @@ -60,7 +60,3 @@ #ifndef __MARLIN_DEPS__ #include HAL_PATH(.., inc/Conditionals_adv.h) #endif - -#if ENABLED(DWIN_LCD_PROUI) - #include "../lcd/e3v2/proui/dwin_defines.h" -#endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index e3e390d7e919..3b08e6635f33 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -2746,18 +2746,6 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #error "DWIN_LCD_PROUI requires SDSUPPORT to be enabled." #elif ALL(LCD_BED_LEVELING, PROBE_MANUALLY) #error "DWIN_LCD_PROUI does not support LCD_BED_LEVELING with PROBE_MANUALLY." - #elif ENABLED(MEDIASORT_MENU_ITEM) && !ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE) - #error "MEDIASORT_MENU_ITEM requires SDCARD_SORT_ALPHA and SDSORT_GCODE." - #elif ENABLED(RUNOUT_TUNE_ITEM) && DISABLED(HAS_FILAMENT_SENSOR) - #error "RUNOUT_TUNE_ITEM requires HAS_FILAMENT_SENSOR." - #elif ENABLED(PLR_TUNE_ITEM) && DISABLED(POWER_LOSS_RECOVERY) - #error "PLR_TUNE_ITEM requires POWER_LOSS_RECOVERY." - #elif ENABLED(JD_TUNE_ITEM) && DISABLED(HAS_JUNCTION_DEVIATION) - #error "JD_TUNE_ITEM requires HAS_JUNCTION_DEVIATION." - #elif ENABLED(ADVK_TUNE_ITEM) && DISABLED(LIN_ADVANCE) - #error "ADVK_TUNE_ITEM requires LIN_ADVANCE." - #elif ENABLED(MESH_EDIT_MENU) && !HAS_MESH - #error "MESH_EDIT_MENU requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL." #endif #endif diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 843009c27461..a585f254de82 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -268,7 +268,7 @@ Menu *stepsMenu = nullptr; #endif #if HAS_MESH Menu *meshMenu = nullptr; - #if ENABLED(MESH_EDIT_MENU) + #if ENABLED(PROUI_MESH_EDIT) Menu *editMeshMenu = nullptr; #endif #endif @@ -847,7 +847,7 @@ void updateVariable() { bool DWIN_lcd_sd_status = false; -#if ENABLED(MEDIASORT_MENU_ITEM) +#if ENABLED(PROUI_MEDIASORT) void setMediaSort() { toggleCheckboxLine(hmiData.mediaSort); card.setSortOn(hmiData.mediaSort ? TERN(SDSORT_REVERSE, AS_REV, AS_FWD) : AS_OFF); @@ -1759,7 +1759,7 @@ void dwinSetDataDefaults() { #if ALL(LCD_BED_TRAMMING, HAS_BED_PROBE) hmiData.fullManualTramming = DISABLED(BED_TRAMMING_USE_PROBE); #endif - #if ENABLED(MEDIASORT_MENU_ITEM) + #if ENABLED(PROUI_MEDIASORT) hmiData.mediaSort = true; card.setSortOn(TERN(SDSORT_REVERSE, AS_REV, AS_FWD)); #endif @@ -3130,7 +3130,7 @@ void drawAdvancedSettingsMenu() { #if HAS_GCODE_PREVIEW EDIT_ITEM(ICON_File, MSG_HAS_PREVIEW, onDrawChkbMenu, setPreview, &hmiData.enablePreview); #endif - #if ENABLED(MEDIASORT_MENU_ITEM) + #if ENABLED(PROUI_MEDIASORT) EDIT_ITEM(ICON_File, MSG_MEDIA_SORT, onDrawChkbMenu, setMediaSort, &hmiData.mediaSort); #endif EDIT_ITEM(ICON_File, MSG_MEDIA_UPDATE, onDrawChkbMenu, setMediaAutoMount, &hmiData.mediaAutoMount); @@ -3323,16 +3323,16 @@ void drawTuneMenu() { #if HAS_FILAMENT_SENSOR EDIT_ITEM(ICON_Runout, MSG_RUNOUT_ENABLE, onDrawChkbMenu, setRunoutEnable, &runout.enabled); #endif - #if ENABLED(PLR_TUNE_ITEM) + #if ENABLED(PROUI_ITEM_PLR) EDIT_ITEM(ICON_Pwrlossr, MSG_OUTAGE_RECOVERY, onDrawChkbMenu, setPwrLossr, &recovery.enabled); #endif #if ENABLED(FWRETRACT) MENU_ITEM(ICON_FWRetract, MSG_FWRETRACT, onDrawSubMenu, drawFWRetractMenu); #endif - #if ENABLED(JD_TUNE_ITEM) + #if ENABLED(PROUI_ITEM_JD) EDIT_ITEM(ICON_JDmm, MSG_JUNCTION_DEVIATION, onDrawPFloat3Menu, setJDmm, &planner.junction_deviation_mm); #endif - #if ENABLED(ADVK_TUNE_ITEM) + #if ENABLED(PROUI_ITEM_ADVK) EDIT_ITEM(ICON_MaxAccelerated, MSG_ADVANCE_K, onDrawPFloat3Menu, setLA_K, &planner.extruder_advance_K[0]); #endif #if HAS_LOCKSCREEN @@ -3952,7 +3952,7 @@ void drawStepsMenu() { void setBedLevT() { setPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); } #endif - #if ENABLED(MESH_EDIT_MENU) + #if ENABLED(PROUI_MESH_EDIT) #define Z_OFFSET_MIN -3 #define Z_OFFSET_MAX 3 @@ -4029,7 +4029,7 @@ void drawStepsMenu() { MENU_ITEM(ICON_UBLTiltGrid, MSG_UBL_TILT_MESH, onDrawMenuItem, ublMeshTilt); MENU_ITEM(ICON_UBLSmartFill, MSG_UBL_SMART_FILLIN, onDrawMenuItem, ublSmartFillMesh); #endif - #if ENABLED(MESH_EDIT_MENU) + #if ENABLED(PROUI_MESH_EDIT) MENU_ITEM(ICON_MeshReset, MSG_MESH_RESET, onDrawMenuItem, ResetMesh); MENU_ITEM(ICON_MeshEdit, MSG_EDIT_MESH, onDrawSubMenu, drawEditMeshMenu); #endif @@ -4038,7 +4038,7 @@ void drawStepsMenu() { updateMenu(meshMenu); } - #if ENABLED(MESH_EDIT_MENU) + #if ENABLED(PROUI_MESH_EDIT) void drawEditMeshMenu() { if (!leveling_is_valid()) { LCD_MESSAGE(MSG_UBL_MESH_INVALID); return; } set_bed_leveling_enabled(false); diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index d8a655413244..26b7fec5fda8 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -137,7 +137,7 @@ typedef struct { #if ALL(LCD_BED_TRAMMING, HAS_BED_PROBE) bool fullManualTramming = false; #endif - #if ENABLED(MEDIASORT_MENU_ITEM) + #if ENABLED(PROUI_MEDIASORT) bool mediaSort = true; #endif bool mediaAutoMount = ENABLED(HAS_SD_EXTENDER); @@ -343,7 +343,7 @@ void drawStepsMenu(); #endif #if HAS_MESH void drawMeshSetMenu(); - #if ENABLED(MESH_EDIT_MENU) + #if ENABLED(PROUI_MESH_EDIT) void drawEditMeshMenu(); #endif #endif diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index 2d751bb0d713..df4196edfef0 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -79,33 +79,23 @@ #define DEF_PIDCYCLES 5 /** -* ProUI Menu Options -* Choose which feature you would like to Enable or Disable -*/ -#if ENABLED(SDCARD_SORT_ALPHA) - #define MEDIASORT_MENU_ITEM - #if ENABLED(MEDIASORT_MENU_ITEM) && (SDSORT_GCODE == false) - // MEDIASORT_MENU_ITEM needs SDSORT_GCODE to be 'true' - #undef SDSORT_GCODE - #define SDSORT_GCODE true - #endif -#endif -#if ENABLED(HAS_FILAMENT_SENSOR) - #define RUNOUT_TUNE_ITEM + * ProUI internal feature flags + */ +#if ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE) + #define PROUI_MEDIASORT #endif #if ENABLED(POWER_LOSS_RECOVERY) - #define PLR_TUNE_ITEM // Power-loss Recovery option in Tune Menu + #define PROUI_ITEM_PLR // Tune > Power-loss Recovery #endif #if ENABLED(HAS_JUNCTION_DEVIATION) - #define JD_TUNE_ITEM // Juntion Deviation item in Tune Menu + #define PROUI_ITEM_JD // Tune > Junction Deviation #endif #if ENABLED(LIN_ADVANCE) - #define ADVK_TUNE_ITEM // Linear Advance item in Tune Menu + #define PROUI_ITEM_ADVK // Tune > Linear Advance #endif #if HAS_MESH - #define MESH_EDIT_MENU // Add a menu to edit mesh points + #define PROUI_MESH_EDIT // Add a menu to edit mesh points #endif - #define HAS_GCODE_PREVIEW 1 #define HAS_CUSTOM_COLORS 1 // Change display colors #define HAS_ESDIAG 1 // View End-stop/Runout switch continuity diff --git a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp index ebe3568c9879..cc18bdd214d6 100644 --- a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp +++ b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp @@ -29,10 +29,12 @@ #include "../../../inc/MarlinConfigPre.h" -#if ALL(DWIN_LCD_PROUI, HAS_LOCKSCREEN) +#if ENABLED(DWIN_LCD_PROUI) #include "dwin_defines.h" -#include "dwinui.h" + +#if HAS_LOCKSCREEN + #include "dwin.h" #include "lockscreen.h" @@ -72,4 +74,5 @@ void LockScreen::onEncoder(EncoderState encoder_diffState) { dwinUpdateLCD(); } -#endif // DWIN_LCD_PROUI && HAS_LOCKSCREEN +#endif // HAS_LOCKSCREEN +#endif // DWIN_LCD_PROUI From b7078786668b0e225ebd1e6fc6a51937a203bb55 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Mon, 20 Nov 2023 16:24:25 -0500 Subject: [PATCH 08/20] =?UTF-8?q?Fix=20warning:=20narrowing=20conversion?= =?UTF-8?q?=20introduced=20in=20commit=20"=F0=9F=9A=B8=20Minor=20touch=20c?= =?UTF-8?q?alibration=20improvement=20(#26445)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp index 87930a18799e..a9ee754387a9 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -247,7 +247,7 @@ bool BedLevelTools::meshValidate() { // Draw value text on const uint8_t fs = DWINUI::fontWidth(meshfont); if (viewer_print_value) { - xy_int8_t offset { 0, cell_height_px / 2 - fs }; + xy_long_t offset { 0, cell_height_px / 2 - fs }; if (isnan(bedlevel.z_values[x][y])) { // undefined dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); } From 2920b3d152ac3a0eb7b35ecb2c4eebed4aa01f89 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 20 Nov 2023 22:17:53 -0600 Subject: [PATCH 09/20] fix file wrappers --- Marlin/src/inc/Conditionals_post.h | 8 +------- Marlin/src/lcd/e3v2/proui/dwin.cpp | 8 ++++---- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 3 +++ Marlin/src/lcd/e3v2/proui/endstop_diag.cpp | 11 +++++++---- Marlin/src/lcd/e3v2/proui/gcode_preview.cpp | 10 +++++++--- Marlin/src/lcd/e3v2/proui/plot.cpp | 10 +++++++--- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 002e5621d472..b98ca4d371f8 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -2491,15 +2491,9 @@ // PID heating #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) #define HAS_PID_HEATING 1 -#endif - -#if ENABLED(DWIN_LCD_PROUI) - #if ANY(PIDTEMP, PIDTEMPBED) + #if ENABLED(DWIN_LCD_PROUI) && ANY(PIDTEMP, PIDTEMPBED) #define PROUI_PID_TUNE 1 #endif - #if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) && DISABLED(DISABLE_TUNING_GRAPH) - #define PROUI_TUNING_GRAPH 1 - #endif #endif // Thermal protection diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index a585f254de82..678a7a6abcf8 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -31,6 +31,10 @@ #if ENABLED(DWIN_LCD_PROUI) +#include "dwin.h" +#include "menus.h" +#include "dwin_popup.h" + #include "../../utf8.h" #include "../../marlinui.h" #include "../../../MarlinCore.h" @@ -105,10 +109,6 @@ #include "../../../feature/tmc_util.h" #endif -#include "dwin.h" -#include "menus.h" -#include "dwin_popup.h" - #if HAS_GCODE_PREVIEW #include "gcode_preview.h" #endif diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index df4196edfef0..30df9ff8c076 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -96,6 +96,9 @@ #if HAS_MESH #define PROUI_MESH_EDIT // Add a menu to edit mesh points #endif +#if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) && DISABLED(DISABLE_TUNING_GRAPH) + #define PROUI_TUNING_GRAPH 1 +#endif #define HAS_GCODE_PREVIEW 1 #define HAS_CUSTOM_COLORS 1 // Change display colors #define HAS_ESDIAG 1 // View End-stop/Runout switch continuity diff --git a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp index d76c10dfdb2a..21c83dc8faa0 100644 --- a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp +++ b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp @@ -29,11 +29,13 @@ #include "../../../inc/MarlinConfigPre.h" -#if ALL(DWIN_LCD_PROUI, HAS_ESDIAG) +#if ENABLED(DWIN_LCD_PROUI) -#include "endstop_diag.h" +#include "dwin_defines.h" + +#if HAS_ESDIAG -#include "../../../core/types.h" +#include "endstop_diag.h" #include "../../marlinui.h" #include "dwin.h" #include "dwin_popup.h" @@ -87,4 +89,5 @@ void ESDiag::update() { dwinUpdateLCD(); } -#endif // DWIN_LCD_PROUI && HAS_ESDIAG +#endif // HAS_ESDIAG +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp b/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp index e6e8384d9065..045615f3c2ae 100644 --- a/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp +++ b/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp @@ -29,11 +29,14 @@ #include "../../../inc/MarlinConfigPre.h" -#if ALL(DWIN_LCD_PROUI, HAS_GCODE_PREVIEW) +#if ENABLED(DWIN_LCD_PROUI) + +#include "dwin_defines.h" + +#if HAS_GCODE_PREVIEW #include "gcode_preview.h" -#include "../../../core/types.h" #include "../../marlinui.h" #include "../../../sd/cardreader.h" #include "../../../MarlinCore.h" // for wait_for_user @@ -226,4 +229,5 @@ void Preview::show() { dwinIconShow(xpos, ypos, 0x00); } -#endif // DWIN_LCD_PROUI && HAS_GCODE_PREVIEW +#endif // HAS_GCODE_PREVIEW +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/plot.cpp b/Marlin/src/lcd/e3v2/proui/plot.cpp index 3ea0d555fe62..92c6c947177b 100644 --- a/Marlin/src/lcd/e3v2/proui/plot.cpp +++ b/Marlin/src/lcd/e3v2/proui/plot.cpp @@ -29,10 +29,13 @@ #include "../../../inc/MarlinConfig.h" -#if ALL(DWIN_LCD_PROUI, PROUI_TUNING_GRAPH) +#if ENABLED(DWIN_LCD_PROUI) + +#include "dwin_defines.h" + +#if PROUI_TUNING_GRAPH #include "dwin.h" -#include "../../../core/types.h" #include "../../marlinui.h" #include "plot.h" @@ -75,4 +78,5 @@ void Plot::update(const_float_t value) { #endif } -#endif // DWIN_LCD_PROUI && PROUI_TUNING_GRAPH +#endif // PROUI_TUNING_GRAPH +#endif // DWIN_LCD_PROUI From 8a5faf14f8a841b4dd71c4dc446d9bc7007a321c Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 00:17:19 -0500 Subject: [PATCH 10/20] =?UTF-8?q?Fix=20warning:=20narrowing=20conversion?= =?UTF-8?q?=20in=20JyersUI=20introduced=20in=20commit=20"=F0=9F=9A=B8=20Mi?= =?UTF-8?q?nor=20touch=20calibration=20improvement=20(#26445)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marlin/src/lcd/e3v2/jyersui/dwin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp index 0222f1e1d045..e1282f8c9877 100644 --- a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp @@ -389,7 +389,7 @@ class TextScroller { // Draw value text on if (viewer_print_value) { - xy_int8_t offset { 0, cell_height_px / 2 - 6 }; + xy_long_t offset { 0, cell_height_px / 2 - 6 }; if (isnan(bedlevel.z_values[x][y])) { // undefined dwinDrawString(false, font6x12, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); } From 031eecc13afdf6a273e3e6fe55a29c5cb179cac8 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 00:30:21 -0500 Subject: [PATCH 11/20] fixes for dwin.cpp onDrawManualTramming() has no use - removed change "&&" to ALL, and "||" to ANY --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 678a7a6abcf8..6c18af9248fd 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -72,7 +72,7 @@ #define HAS_ONESTEP_LEVELING 1 #endif -#if HAS_MESH || (HAS_LEVELING && HAS_ZOFFSET_ITEM) +#if HAS_MESH || ALL(HAS_LEVELING, HAS_ZOFFSET_ITEM) #include "../../../feature/bedlevel/bedlevel.h" #include "bedlevel_tools.h" #endif @@ -164,7 +164,7 @@ #define DWIN_VAR_UPDATE_INTERVAL 500 #define DWIN_UPDATE_INTERVAL 1000 -#if HAS_MESH && HAS_BED_PROBE +#if ALL(HAS_MESH, HAS_BED_PROBE) #define BABY_Z_VAR probe.offset.z #else float z_offset = 0; @@ -443,7 +443,7 @@ void popupPauseOrStop() { #endif -#if HAS_HOTEND || HAS_HEATED_BED +#if ANY(HAS_HOTEND, HAS_HEATED_BED) void dwinPopupTemperature(const bool toohigh) { hmiSaveProcessID(ID_WaitResponse); if (hmiIsChinese()) { @@ -2390,7 +2390,7 @@ void setFlow() { setPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW, []{ planner.refr #endif - #if HAS_BED_PROBE && HAS_MESH + #if ALL(HAS_BED_PROBE, HAS_MESH) void trammingwizard() { if (hmiData.fullManualTramming) { @@ -2976,10 +2976,6 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { #endif -#if HAS_ONESTEP_LEVELING - void onDrawManualTramming(MenuItem* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, hmiData.fullManualTramming); } -#endif - // Menu Creation and Drawing functions ====================================================== frame_rect_t selrect(frame_rect_t) { @@ -3030,10 +3026,10 @@ void drawPrepareMenu() { checkkey = ID_Menu; if (SET_MENU(trammingMenu, MSG_BED_TRAMMING, 8)) { BACK_ITEM(drawPrepareMenu); - #if HAS_BED_PROBE && HAS_MESH + #if ALL(HAS_BED_PROBE, HAS_MESH) MENU_ITEM(ICON_ProbeSet, MSG_TRAMMING_WIZARD, onDrawMenuItem, trammingwizard); EDIT_ITEM(ICON_ProbeSet, MSG_BED_TRAMMING_MANUAL, onDrawChkbMenu, setManualTramming, &hmiData.fullManualTramming); - #elif !HAS_BED_PROBE && HAS_ZOFFSET_ITEM + #elif ALL(!HAS_BED_PROBE, HAS_ZOFFSET_ITEM) MENU_ITEM_F(ICON_MoveZ0, "Home Z and disable", onDrawMenuItem, homeZAndDisable); #endif MENU_ITEM(ICON_Axis, MSG_TRAM_FL, onDrawMenuItem, []{ (void)tram(0); }); From 6358adebedae1c904b1f74fea2880d498d5d4bef Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 01:14:22 -0500 Subject: [PATCH 12/20] indent --- Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp | 398 +++---- Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp | 286 ++--- Marlin/src/lcd/e3v2/proui/dwin_popup.cpp | 100 +- Marlin/src/lcd/e3v2/proui/dwinui.cpp | 660 ++++++------ Marlin/src/lcd/e3v2/proui/endstop_diag.cpp | 98 +- Marlin/src/lcd/e3v2/proui/gcode_preview.cpp | 390 +++---- Marlin/src/lcd/e3v2/proui/lockscreen.cpp | 72 +- Marlin/src/lcd/e3v2/proui/menus.cpp | 1020 +++++++++--------- Marlin/src/lcd/e3v2/proui/meshviewer.cpp | 206 ++-- Marlin/src/lcd/e3v2/proui/plot.cpp | 80 +- Marlin/src/lcd/e3v2/proui/printstats.cpp | 78 +- 11 files changed, 1694 insertions(+), 1694 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp index a9ee754387a9..d54a458c6d25 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -48,234 +48,234 @@ #if ALL(DWIN_LCD_PROUI, HAS_LEVELING) -#include "../../marlinui.h" -#include "../../../core/types.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" - -#include "dwin.h" -#include "dwinui.h" -#include "dwin_popup.h" -#include "bedlevel_tools.h" - -BedLevelTools bedLevelTools; - -#if ENABLED(USE_GRID_MESHVIEWER) - bool BedLevelTools::viewer_print_value = false; -#endif -bool BedLevelTools::goto_mesh_value = false; -uint8_t BedLevelTools::mesh_x = 0; -uint8_t BedLevelTools::mesh_y = 0; -uint8_t BedLevelTools::tilt_grid = 1; - -bool drawing_mesh = false; - -#if ENABLED(AUTO_BED_LEVELING_UBL) - - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { - MString cmd; - cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); - if (undefined) cmd += F(" N"); - gcode.process_subcommands_now(cmd); - planner.synchronize(); - } + #include "../../marlinui.h" + #include "../../../core/types.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" + + #include "dwin.h" + #include "dwinui.h" + #include "dwin_popup.h" + #include "bedlevel_tools.h" + + BedLevelTools bedLevelTools; + + #if ENABLED(USE_GRID_MESHVIEWER) + bool BedLevelTools::viewer_print_value = false; + #endif + bool BedLevelTools::goto_mesh_value = false; + uint8_t BedLevelTools::mesh_x = 0; + uint8_t BedLevelTools::mesh_y = 0; + uint8_t BedLevelTools::tilt_grid = 1; + + bool drawing_mesh = false; + + #if ENABLED(AUTO_BED_LEVELING_UBL) + + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { + MString cmd; + cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); + if (undefined) cmd += F(" N"); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } - bool BedLevelTools::createPlaneFromMesh() { - 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]); + bool BedLevelTools::createPlaneFromMesh() { + 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; - } + if (finish_incremental_LSF(&lsf_results)) { + SERIAL_ECHOPGM("Could not complete LSF!"); + return true; + } - bedlevel.set_all_mesh_points_to_value(0); + 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]; + 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_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } - rotation.apply_rotation_xyz(mx, my, mz); + rotation.apply_rotation_xyz(mx, my, mz); - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } + + bedlevel.z_values[i][j] = mz - lsf_results.D; } + return false; + } + + #else - bedlevel.z_values[i][j] = mz - lsf_results.D; + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { + gcode.process_subcommands_now( + TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) + ); + planner.synchronize(); } - return false; - } -#else + #endif + + void BedLevelTools::manualMove(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 { + dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); + hmiSaveProcessID(ID_NothingToDo); + gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); + gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); + 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(); + hmiReturnScreen(); + } + } - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { + // Move / Probe methods. As examples, not yet used. + void BedLevelTools::moveToXYZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, false); + } + void BedLevelTools::moveToXY() { + goto_mesh_value = false; + manualMove(mesh_x, mesh_y, false); + } + void BedLevelTools::moveToZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, true); + } + void BedLevelTools::probeXY() { gcode.process_subcommands_now( - TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) + MString( + F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), + F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), + F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) + ) ); - planner.synchronize(); } -#endif - -void BedLevelTools::manualMove(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(); + void BedLevelTools::meshReset() { + ZERO(bedlevel.z_values); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); } - else { - dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); - hmiSaveProcessID(ID_NothingToDo); - gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); - gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); - 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(); - hmiReturnScreen(); + + // Accessors + float BedLevelTools::getMaxValue() { + float max = -(__FLT_MAX__); + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } + return max; } -} - -// Move / Probe methods. As examples, not yet used. -void BedLevelTools::moveToXYZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, false); -} -void BedLevelTools::moveToXY() { - goto_mesh_value = false; - manualMove(mesh_x, mesh_y, false); -} -void BedLevelTools::moveToZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, true); -} -void BedLevelTools::probeXY() { - gcode.process_subcommands_now( - MString( - F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), - F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), - F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) - ) - ); -} - -void BedLevelTools::meshReset() { - ZERO(bedlevel.z_values); - TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); -} - -// Accessors -float BedLevelTools::getMaxValue() { - float max = -(__FLT_MAX__); - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } - return max; -} - -float BedLevelTools::getMinValue() { - float min = __FLT_MAX__; - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } - return min; -} - -// Return 'true' if mesh is good and within LCD limits -bool BedLevelTools::meshValidate() { - GRID_LOOP(x, y) { - const float v = bedlevel.z_values[x][y]; - if (isnan(v) || !WITHIN(v, UBL_Z_OFFSET_MIN, UBL_Z_OFFSET_MAX)) return false; + + float BedLevelTools::getMinValue() { + float min = __FLT_MAX__; + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } + return min; } - return true; -} - -#if ENABLED(USE_GRID_MESHVIEWER) - - constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - - void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); - - // Clear background from previous selection and select new square - dwinDrawRectangle(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; - dwinDrawRectangle(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 + // Return 'true' if mesh is good and within LCD limits + bool BedLevelTools::meshValidate() { 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; - dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative - (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 - ); + const float v = bedlevel.z_values[x][y]; + if (isnan(v) || !WITHIN(v, UBL_Z_OFFSET_MIN, UBL_Z_OFFSET_MAX)) return false; + } + return true; + } - safe_delay(10); - LCD_SERIAL.flushTX(); + #if ENABLED(USE_GRID_MESHVIEWER) + + constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); + + void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); + + // Clear background from previous selection and select new square + dwinDrawRectangle(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; + dwinDrawRectangle(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 + 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; + dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative + (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 + ); - // Draw value text on - const uint8_t fs = DWINUI::fontWidth(meshfont); - if (viewer_print_value) { - xy_long_t offset { 0, cell_height_px / 2 - fs }; - if (isnan(bedlevel.z_values[x][y])) { // undefined - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); - } - else { // has value - MString<12> msg; - if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) - msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); - else - msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); - offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; - if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); - } safe_delay(10); LCD_SERIAL.flushTX(); + + // Draw value text on + const uint8_t fs = DWINUI::fontWidth(meshfont); + if (viewer_print_value) { + xy_long_t offset { 0, cell_height_px / 2 - fs }; + if (isnan(bedlevel.z_values[x][y])) { // undefined + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); + } + else { // has value + MString<12> msg; + if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) + msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); + else + msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); + offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; + if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); + } + safe_delay(10); + LCD_SERIAL.flushTX(); + } } } - } - void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead - float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); - if (rmax > 3e+10f) rmax = 0.0000001; - if (rmin > 3e+10f) rmin = 0.0000001; - ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); - drawing_mesh = false; - } + void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead + float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); + if (rmax > 3e+10f) rmax = 0.0000001; + if (rmin > 3e+10f) rmin = 0.0000001; + ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); + drawing_mesh = false; + } -#endif // USE_GRID_MESHVIEWER + #endif // USE_GRID_MESHVIEWER #endif // DWIN_LCD_PROUI && HAS_LEVELING diff --git a/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp b/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp index 853da8532e12..497c86e81634 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp @@ -31,150 +31,150 @@ #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 dwinDrawQR(uint8_t QR_Pixel, uint16_t x, uint16_t y, char *string) { - size_t i = 0; - dwinByte(i, 0x21); - dwinWord(i, x); - dwinWord(i, y); - dwinByte(i, QR_Pixel); - dwinText(i, string); - dwinSend(i); -} - -// Draw an Icon with transparent background -// libID: Icon library ID -// picID: Icon ID -// x/y: Upper-left point -void dwinIconShow(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { - dwinIconShow(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 dwinFrameAreaCopy(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { - size_t i = 0; - dwinByte(i, 0x26); - dwinWord(i, xStart); - dwinWord(i, yStart); - dwinWord(i, xEnd); - dwinWord(i, yEnd); - dwinWord(i, x); - dwinWord(i, y); - dwinSend(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 dwinFrameAreaCopy(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; - dwinByte(i, 0x27); - dwinByte(i, (IBD & 1) << 7 | (BIR & 1) << 6 | (BFI & 1) << 5 | cacheID); - dwinWord(i, xStart); - dwinWord(i, yStart); - dwinWord(i, xEnd); - dwinWord(i, yEnd); - dwinWord(i, x); - dwinWord(i, y); - dwinSend(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 dwinFrameAreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { - dwinFrameAreaCopy(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 dwinWriteToMem(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); + #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 dwinDrawQR(uint8_t QR_Pixel, uint16_t x, uint16_t y, char *string) { + size_t i = 0; + dwinByte(i, 0x21); + dwinWord(i, x); + dwinWord(i, y); + dwinByte(i, QR_Pixel); + dwinText(i, string); + dwinSend(i); + } + + // Draw an Icon with transparent background + // libID: Icon library ID + // picID: Icon ID + // x/y: Upper-left point + void dwinIconShow(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + dwinIconShow(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 dwinFrameAreaCopy(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + size_t i = 0; + dwinByte(i, 0x26); + dwinWord(i, xStart); + dwinWord(i, yStart); + dwinWord(i, xEnd); + dwinWord(i, yEnd); + dwinWord(i, x); + dwinWord(i, y); + dwinSend(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 dwinFrameAreaCopy(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; + dwinByte(i, 0x27); + dwinByte(i, (IBD & 1) << 7 | (BIR & 1) << 6 | (BFI & 1) << 5 | cacheID); + dwinWord(i, xStart); + dwinWord(i, yStart); + dwinWord(i, xEnd); + dwinWord(i, yEnd); + dwinWord(i, x); + dwinWord(i, y); + dwinSend(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 dwinFrameAreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + dwinFrameAreaCopy(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 dwinWriteToMem(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; + dwinByte(i, 0x31); + dwinByte(i, mem); + dwinWord(i, addr + indx); // start address of the data block + ++i; + for (uint8_t j = 0; j < i; ++j) { LCD_SERIAL.write(dwinSendBuf[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 + for (uint8_t j = 0; j < 4; ++j) { LCD_SERIAL.write(dwinBufTail[j]); delayMicroseconds(1); } + block++; + pending -= to_send; + } + } + + // Draw an Icon from SRAM without background transparency for DACAI Screens support + void DACAI_ICON_Show(uint16_t x, uint16_t y, uint16_t addr) { + NOMORE(x, DWIN_WIDTH - 1); + NOMORE(y, DWIN_HEIGHT - 1); size_t i = 0; - dwinByte(i, 0x31); - dwinByte(i, mem); - dwinWord(i, addr + indx); // start address of the data block - ++i; - for (uint8_t j = 0; j < i; ++j) { LCD_SERIAL.write(dwinSendBuf[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 - for (uint8_t j = 0; j < 4; ++j) { LCD_SERIAL.write(dwinBufTail[j]); delayMicroseconds(1); } - block++; - pending -= to_send; + dwinByte(i, 0x70); + dwinWord(i, x); + dwinWord(i, y); + dwinWord(i, addr); + dwinSend(i); } -} - -// Draw an Icon from SRAM without background transparency for DACAI Screens support -void DACAI_ICON_Show(uint16_t x, uint16_t y, uint16_t addr) { - NOMORE(x, DWIN_WIDTH - 1); - NOMORE(y, DWIN_HEIGHT - 1); - size_t i = 0; - dwinByte(i, 0x70); - dwinWord(i, x); - dwinWord(i, y); - dwinWord(i, addr); - dwinSend(i); -} - -void dwinIconShow(uint16_t x, uint16_t y, uint16_t addr) { - #if ENABLED(DACAI_DISPLAY) - DACAI_ICON_Show(x, y, addr); - #else - dwinIconShow(0, 0, 1, x, y, addr); - #endif -} - -// 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 dwinSRAMToPic(uint8_t picID) { - size_t i = 0; - dwinByte(i, 0x33); - dwinByte(i, 0x5A); - dwinByte(i, 0xA5); - dwinByte(i, picID); - dwinSend(i); -} - -//--------------------------Test area ------------------------- - -//void dwinReadSRAM(uint16_t addr, const uint8_t length, const char * const data) { -// size_t i = 0; -// dwinByte(i, 0x32); -// dwinByte(i, 0x5A); // 0x5A Read from SRAM - 0xA5 Read from Flash -// dwinWord(i, addr); // 0x0000 to 0x7FFF -// const size_t len = _MIN(0xF0, length); -// dwinByte(i, len); -// dwinSend(i); -//} + + void dwinIconShow(uint16_t x, uint16_t y, uint16_t addr) { + #if ENABLED(DACAI_DISPLAY) + DACAI_ICON_Show(x, y, addr); + #else + dwinIconShow(0, 0, 1, x, y, addr); + #endif + } + + // 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 dwinSRAMToPic(uint8_t picID) { + size_t i = 0; + dwinByte(i, 0x33); + dwinByte(i, 0x5A); + dwinByte(i, 0xA5); + dwinByte(i, picID); + dwinSend(i); + } + + //--------------------------Test area ------------------------- + + //void dwinReadSRAM(uint16_t addr, const uint8_t length, const char * const data) { + // size_t i = 0; + // dwinByte(i, 0x32); + // dwinByte(i, 0x5A); // 0x5A Read from SRAM - 0xA5 Read from Flash + // dwinWord(i, addr); // 0x0000 to 0x7FFF + // const size_t len = _MIN(0xF0, length); + // dwinByte(i, len); + // dwinSend(i); + //} #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp index 91c3ee98e390..71ef7844f7b0 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp @@ -31,65 +31,65 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin.h" -#include "dwinui.h" -#include "dwin_popup.h" + #include "dwin.h" + #include "dwinui.h" + #include "dwin_popup.h" -#include "../../../MarlinCore.h" // for wait_for_user + #include "../../../MarlinCore.h" // for wait_for_user -popupDrawFunc_t popupDraw = nullptr; -popupClickFunc_t popupClick = nullptr; -popupChangeFunc_t popupChange = nullptr; + popupDrawFunc_t popupDraw = nullptr; + popupClickFunc_t popupClick = nullptr; + popupChangeFunc_t popupChange = nullptr; -uint16_t HighlightYPos = 280; + uint16_t HighlightYPos = 280; -void drawSelectHighlight(const bool sel, const uint16_t ypos) { - HighlightYPos = ypos; - hmiFlag.select_flag = sel; - const uint16_t c1 = sel ? hmiData.colorHighlight : hmiData.colorPopupBg, - c2 = sel ? hmiData.colorPopupBg : hmiData.colorHighlight; - dwinDrawRectangle(0, c1, 25, ypos - 1, 126, ypos + 38); - dwinDrawRectangle(0, c1, 24, ypos - 2, 127, ypos + 39); - dwinDrawRectangle(0, c2, 145, ypos - 1, 246, ypos + 38); - dwinDrawRectangle(0, c2, 144, ypos - 2, 247, ypos + 39); -} - -void dwinPopupContinue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) { - hmiSaveProcessID(ID_WaitResponse); - dwinDrawPopup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue - dwinUpdateLCD(); -} + void drawSelectHighlight(const bool sel, const uint16_t ypos) { + HighlightYPos = ypos; + hmiFlag.select_flag = sel; + const uint16_t c1 = sel ? hmiData.colorHighlight : hmiData.colorPopupBg, + c2 = sel ? hmiData.colorPopupBg : hmiData.colorHighlight; + dwinDrawRectangle(0, c1, 25, ypos - 1, 126, ypos + 38); + dwinDrawRectangle(0, c1, 24, ypos - 2, 127, ypos + 39); + dwinDrawRectangle(0, c2, 145, ypos - 1, 246, ypos + 38); + dwinDrawRectangle(0, c2, 144, ypos - 2, 247, ypos + 39); + } -void dwinPopupConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) { - dwinDrawPopup(ICON_BLTouch, F("Please confirm"), fmsg2); - DWINUI::drawButton(BTN_Confirm, 26, 280); - DWINUI::drawButton(BTN_Cancel, 146, 280); - drawSelectHighlight(hmiFlag.select_flag); - dwinUpdateLCD(); -} + void dwinPopupContinue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) { + hmiSaveProcessID(ID_WaitResponse); + dwinDrawPopup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue + dwinUpdateLCD(); + } -void gotoPopup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) { - popupDraw = fnDraw; - popupClick = fnClick; - popupChange = fnChange; - hmiSaveProcessID(ID_Popup); - hmiFlag.select_flag = false; - popupDraw(); -} + void dwinPopupConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) { + dwinDrawPopup(ICON_BLTouch, F("Please confirm"), fmsg2); + DWINUI::drawButton(BTN_Confirm, 26, 280); + DWINUI::drawButton(BTN_Cancel, 146, 280); + drawSelectHighlight(hmiFlag.select_flag); + dwinUpdateLCD(); + } -void hmiPopup() { - if (!wait_for_user) { - if (popupClick) popupClick(); - return; + void gotoPopup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) { + popupDraw = fnDraw; + popupClick = fnClick; + popupChange = fnChange; + hmiSaveProcessID(ID_Popup); + hmiFlag.select_flag = false; + popupDraw(); } - 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 drawSelectHighlight(change, HighlightYPos); - dwinUpdateLCD(); + + void hmiPopup() { + 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 drawSelectHighlight(change, HighlightYPos); + dwinUpdateLCD(); + } } } -} #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwinui.cpp b/Marlin/src/lcd/e3v2/proui/dwinui.cpp index 7e94fc3e5633..df02508e4781 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwinui.cpp @@ -31,335 +31,335 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" -#include "dwinui.h" - -xy_int_t DWINUI::cursor = { 0 }; -uint16_t DWINUI::penColor = COLOR_WHITE; -uint16_t DWINUI::textColor = defColorText; -uint16_t DWINUI::backColor = defColorBackground; -uint16_t DWINUI::buttonColor = defColorButton; -uint8_t DWINUI::fontID = font8x16; -FSTR_P const DWINUI::author = F(STRING_CONFIG_H_AUTHOR); - -void (*DWINUI::onTitleDraw)(Title* t) = nullptr; - -void DWINUI::init() { - cursor.reset(); - penColor = COLOR_WHITE; - textColor = defColorText; - backColor = defColorBackground; - buttonColor = defColorButton; - 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) { - #if DISABLED(TJC_DISPLAY) - case font6x12 : return 6; - case font20x40: return 20; - case font24x48: return 24; - case font28x56: return 28; - case font32x64: return 32; - #endif - case font8x16 : return 8; - case font10x20: return 10; - case font12x24: return 12; - case font14x28: return 14; - case font16x32: return 16; - default: return 0; - } -} - -// Get font character height -uint8_t DWINUI::fontHeight(fontid_t fid) { - switch (fid) { - #if DISABLED(TJC_DISPLAY) - case font6x12 : return 12; - case font20x40: return 40; - case font24x48: return 48; - case font28x56: return 56; - case font32x64: return 64; - #endif - case font8x16 : return 16; - case font10x20: return 20; - case font12x24: return 24; - case font14x28: return 28; - case font16x32: return 32; - 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::drawCenteredString(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; - dwinDrawString(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::drawChar(uint16_t color, uint16_t x, uint16_t y, const char c) { - const char string[2] = { c, 0}; - dwinDrawString(false, fontID, color, backColor, x, y, string, 1); -} - -// Draw a char at cursor position and increment cursor -void DWINUI::drawChar(uint16_t color, const char c) { - drawChar(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::drawString(const char * const string, uint16_t rlimit) { - dwinDrawString(false, fontID, textColor, backColor, cursor.x, cursor.y, string, rlimit); - moveBy(strlen(string) * fontWidth(fontID), 0); -} -void DWINUI::drawString(uint16_t color, const char * const string, uint16_t rlimit) { - dwinDrawString(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::drawInt(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); - dwinDrawString(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::drawFloat(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]; - dwinDrawString(bShow, fid, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr)); -} - -// ------------------------- Icons -------------------------------// - -// Draw an Icon and select library automatically -// BG: The icon background display: false=Background filtering is not displayed, true=Background display -// libID: Icon library ID -// picID: Icon ID -// x/y: Upper-left point -void DWINUI::ICON_Show(bool BG, uint8_t icon, uint16_t x, uint16_t y) { - const uint8_t libID = ICON TERN_(HAS_CUSTOMICONS, + (icon / 100)); - const uint8_t picID = icon TERN_(HAS_CUSTOMICONS, % 100); - dwinIconShow(BG, false, !BG, libID, picID, x, y); -} - -// ------------------------- Buttons ------------------------------// - -void DWINUI::drawButton(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) { - dwinDrawRectangle(1, bcolor, x1, y1, x2, y2); - drawCenteredString(0, fontID, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption); -} - -void DWINUI::drawButton(uint8_t id, uint16_t x, uint16_t y) { - switch (id) { - case BTN_Cancel : drawButton(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break; - case BTN_Confirm : drawButton(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break; - case BTN_Continue: drawButton(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break; - case BTN_Print : drawButton(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break; - case BTN_Save : drawButton(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break; - case BTN_Purge : drawButton(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::drawCircle(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--; - dwinDrawPoint(color, 1, 1, x + a, y + b); // Draw some sector 1 - dwinDrawPoint(color, 1, 1, x + b, y + a); // Draw some sector 2 - dwinDrawPoint(color, 1, 1, x + b, y - a); // Draw some sector 3 - dwinDrawPoint(color, 1, 1, x + a, y - b); // Draw some sector 4 - dwinDrawPoint(color, 1, 1, x - a, y - b); // Draw some sector 5 - dwinDrawPoint(color, 1, 1, x - b, y - a); // Draw some sector 6 - dwinDrawPoint(color, 1, 1, x - b, y + a); // Draw some sector 7 - dwinDrawPoint(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::drawFillCircle(uint16_t bcolor, uint16_t x, uint16_t y, uint8_t r) { - dwinDrawLine(bcolor, x - r, y, x + r, y); - uint16_t b = 1; - while (b <= r) { - uint16_t a = SQRT(sq(r) - sq(b)); - dwinDrawLine(bcolor, x - a, y + b, x + a, y + b); - dwinDrawLine(bcolor, x - a, y - b, x + a, y - b); - b += TERN(TJC_DISPLAY, 2, 1); - } -} - -// 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 + 1); - R = (1.0f - n) * GetRColor(color1) + n * GetRColor(color2); - G = (1.0f - n) * GetGColor(color1) + n * GetGColor(color2); - B = (1.0f - 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) { - const int16_t limv = _MAX(abs(minv), abs(maxv)); - float n = (minv >= 0) ? float(val - minv) / (maxv - minv + 1) : (float)val / limv; - LIMIT(n, -1, 1); - - constexpr uint8_t maxB = 28, maxR = 28, maxG = 38; - uint8_t R, G, B; - if (n <= -0.5f) { R = 0; G = maxG * (1.0f + n); B = maxB; } - else if (n <= 0.0f) { R = 0; G = maxG; B = maxB * (-n) * 2; } - else if (n < 0.5f) { R = maxR * n * 2; G = maxG; B = 0; } - else { R = maxR; G = maxG * (1.0f - 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::drawCheckbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked=false) { - dwinDrawRectangle(0, color, x + 2, y + 2, x + 17, y + 17); - dwinDrawRectangle(1, checked ? color : bcolor, x + 6, y + 6, x + 13, y + 13); -} - -// Clear Menu by filling the menu area with background color -void DWINUI::clearMainArea() { - dwinDrawRectangle(1, backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); -} - -/* Title Class ==============================================================*/ - -Title title; - -void Title::draw() { - if (DWINUI::onTitleDraw != nullptr) (*DWINUI::onTitleDraw)(this); -} - -void Title::setCaption(const char * const titleStr) { - frameid = 0; - if ( caption == titleStr ) return; - const uint8_t len = _MIN(sizeof(caption) - 1, strlen(titleStr)); - memcpy(&caption[0], titleStr, len); - caption[len] = '\0'; -} - -void Title::showCaption(const char * const titleStr) { - setCaption(titleStr); - draw(); -} - -void Title::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 Title::setFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - setFrame(1, x, y, x + w - 1, y + h - 1); -} - -void Title::frameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { - setFrame(id, x1, y1, x2, y2); - draw(); -} - -void Title::frameCopy(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - frameCopy(1, x, y, x + w - 1, y + h - 1); -} + #include "dwin_defines.h" + #include "dwinui.h" + + xy_int_t DWINUI::cursor = { 0 }; + uint16_t DWINUI::penColor = COLOR_WHITE; + uint16_t DWINUI::textColor = defColorText; + uint16_t DWINUI::backColor = defColorBackground; + uint16_t DWINUI::buttonColor = defColorButton; + uint8_t DWINUI::fontID = font8x16; + FSTR_P const DWINUI::author = F(STRING_CONFIG_H_AUTHOR); + + void (*DWINUI::onTitleDraw)(Title* t) = nullptr; + + void DWINUI::init() { + cursor.reset(); + penColor = COLOR_WHITE; + textColor = defColorText; + backColor = defColorBackground; + buttonColor = defColorButton; + 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) { + #if DISABLED(TJC_DISPLAY) + case font6x12 : return 6; + case font20x40: return 20; + case font24x48: return 24; + case font28x56: return 28; + case font32x64: return 32; + #endif + case font8x16 : return 8; + case font10x20: return 10; + case font12x24: return 12; + case font14x28: return 14; + case font16x32: return 16; + default: return 0; + } + } + + // Get font character height + uint8_t DWINUI::fontHeight(fontid_t fid) { + switch (fid) { + #if DISABLED(TJC_DISPLAY) + case font6x12 : return 12; + case font20x40: return 40; + case font24x48: return 48; + case font28x56: return 56; + case font32x64: return 64; + #endif + case font8x16 : return 16; + case font10x20: return 20; + case font12x24: return 24; + case font14x28: return 28; + case font16x32: return 32; + 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::drawCenteredString(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; + dwinDrawString(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::drawChar(uint16_t color, uint16_t x, uint16_t y, const char c) { + const char string[2] = { c, 0}; + dwinDrawString(false, fontID, color, backColor, x, y, string, 1); + } + + // Draw a char at cursor position and increment cursor + void DWINUI::drawChar(uint16_t color, const char c) { + drawChar(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::drawString(const char * const string, uint16_t rlimit) { + dwinDrawString(false, fontID, textColor, backColor, cursor.x, cursor.y, string, rlimit); + moveBy(strlen(string) * fontWidth(fontID), 0); + } + void DWINUI::drawString(uint16_t color, const char * const string, uint16_t rlimit) { + dwinDrawString(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::drawInt(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); + dwinDrawString(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::drawFloat(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]; + dwinDrawString(bShow, fid, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr)); + } + + // ------------------------- Icons -------------------------------// + + // Draw an Icon and select library automatically + // BG: The icon background display: false=Background filtering is not displayed, true=Background display + // libID: Icon library ID + // picID: Icon ID + // x/y: Upper-left point + void DWINUI::ICON_Show(bool BG, uint8_t icon, uint16_t x, uint16_t y) { + const uint8_t libID = ICON TERN_(HAS_CUSTOMICONS, + (icon / 100)); + const uint8_t picID = icon TERN_(HAS_CUSTOMICONS, % 100); + dwinIconShow(BG, false, !BG, libID, picID, x, y); + } + + // ------------------------- Buttons ------------------------------// + + void DWINUI::drawButton(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) { + dwinDrawRectangle(1, bcolor, x1, y1, x2, y2); + drawCenteredString(0, fontID, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption); + } + + void DWINUI::drawButton(uint8_t id, uint16_t x, uint16_t y) { + switch (id) { + case BTN_Cancel : drawButton(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break; + case BTN_Confirm : drawButton(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break; + case BTN_Continue: drawButton(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break; + case BTN_Print : drawButton(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break; + case BTN_Save : drawButton(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break; + case BTN_Purge : drawButton(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::drawCircle(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--; + dwinDrawPoint(color, 1, 1, x + a, y + b); // Draw some sector 1 + dwinDrawPoint(color, 1, 1, x + b, y + a); // Draw some sector 2 + dwinDrawPoint(color, 1, 1, x + b, y - a); // Draw some sector 3 + dwinDrawPoint(color, 1, 1, x + a, y - b); // Draw some sector 4 + dwinDrawPoint(color, 1, 1, x - a, y - b); // Draw some sector 5 + dwinDrawPoint(color, 1, 1, x - b, y - a); // Draw some sector 6 + dwinDrawPoint(color, 1, 1, x - b, y + a); // Draw some sector 7 + dwinDrawPoint(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::drawFillCircle(uint16_t bcolor, uint16_t x, uint16_t y, uint8_t r) { + dwinDrawLine(bcolor, x - r, y, x + r, y); + uint16_t b = 1; + while (b <= r) { + uint16_t a = SQRT(sq(r) - sq(b)); + dwinDrawLine(bcolor, x - a, y + b, x + a, y + b); + dwinDrawLine(bcolor, x - a, y - b, x + a, y - b); + b += TERN(TJC_DISPLAY, 2, 1); + } + } + + // 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 + 1); + R = (1.0f - n) * GetRColor(color1) + n * GetRColor(color2); + G = (1.0f - n) * GetGColor(color1) + n * GetGColor(color2); + B = (1.0f - 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) { + const int16_t limv = _MAX(abs(minv), abs(maxv)); + float n = (minv >= 0) ? float(val - minv) / (maxv - minv + 1) : (float)val / limv; + LIMIT(n, -1, 1); + + constexpr uint8_t maxB = 28, maxR = 28, maxG = 38; + uint8_t R, G, B; + if (n <= -0.5f) { R = 0; G = maxG * (1.0f + n); B = maxB; } + else if (n <= 0.0f) { R = 0; G = maxG; B = maxB * (-n) * 2; } + else if (n < 0.5f) { R = maxR * n * 2; G = maxG; B = 0; } + else { R = maxR; G = maxG * (1.0f - 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::drawCheckbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked=false) { + dwinDrawRectangle(0, color, x + 2, y + 2, x + 17, y + 17); + dwinDrawRectangle(1, checked ? color : bcolor, x + 6, y + 6, x + 13, y + 13); + } + + // Clear Menu by filling the menu area with background color + void DWINUI::clearMainArea() { + dwinDrawRectangle(1, backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); + } + + /* Title Class ==============================================================*/ + + Title title; + + void Title::draw() { + if (DWINUI::onTitleDraw != nullptr) (*DWINUI::onTitleDraw)(this); + } + + void Title::setCaption(const char * const titleStr) { + frameid = 0; + if ( caption == titleStr ) return; + const uint8_t len = _MIN(sizeof(caption) - 1, strlen(titleStr)); + memcpy(&caption[0], titleStr, len); + caption[len] = '\0'; + } + + void Title::showCaption(const char * const titleStr) { + setCaption(titleStr); + draw(); + } + + void Title::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 Title::setFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + setFrame(1, x, y, x + w - 1, y + h - 1); + } + + void Title::frameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + setFrame(id, x1, y1, x2, y2); + draw(); + } + + void Title::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/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp index 21c83dc8faa0..902038630647 100644 --- a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp +++ b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp @@ -31,63 +31,63 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" + #include "dwin_defines.h" -#if HAS_ESDIAG + #if HAS_ESDIAG -#include "endstop_diag.h" -#include "../../marlinui.h" -#include "dwin.h" -#include "dwin_popup.h" + #include "endstop_diag.h" + #include "../../marlinui.h" + #include "dwin.h" + #include "dwin_popup.h" -#if HAS_FILAMENT_SENSOR - #include "../../../feature/runout.h" -#endif + #if HAS_FILAMENT_SENSOR + #include "../../../feature/runout.h" + #endif -#if HAS_BED_PROBE - #include "../../../module/probe.h" -#endif + #if HAS_BED_PROBE + #include "../../../module/probe.h" + #endif -ESDiag esDiag; + ESDiag esDiag; -void draw_es_label(FSTR_P const flabel=nullptr) { - DWINUI::cursor.x = 40; - if (flabel) DWINUI::drawString(F(flabel)); - DWINUI::drawString(F(": ")); - DWINUI::moveBy(0, 25); -} + void draw_es_label(FSTR_P const flabel=nullptr) { + DWINUI::cursor.x = 40; + if (flabel) DWINUI::drawString(F(flabel)); + DWINUI::drawString(F(": ")); + DWINUI::moveBy(0, 25); + } -void draw_es_state(const bool is_hit) { - const uint8_t LM = 130; - DWINUI::cursor.x = LM; - dwinDrawRectangle(1, hmiData.colorPopupBg, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20); - is_hit ? DWINUI::drawString(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::drawString(RGB(16,63,16), F(STR_ENDSTOP_OPEN)); - DWINUI::moveBy(0, 25); -} + void draw_es_state(const bool is_hit) { + const uint8_t LM = 130; + DWINUI::cursor.x = LM; + dwinDrawRectangle(1, hmiData.colorPopupBg, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20); + is_hit ? DWINUI::drawString(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::drawString(RGB(16,63,16), F(STR_ENDSTOP_OPEN)); + DWINUI::moveBy(0, 25); + } -void ESDiag::draw() { - title.showCaption(GET_TEXT_F(MSG_ENDSTOP_TEST)); - DWINUI::clearMainArea(); - drawPopupBkgd(); - DWINUI::drawButton(BTN_Continue, 86, 250); - DWINUI::cursor.y = 80; - #define ES_LABEL(S) draw_es_label(F(STR_##S)) - TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX)); - TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX)); - TERN_(USE_Z_MIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX)); - TERN_(HAS_FILAMENT_SENSOR, draw_es_label(F(STR_FILAMENT))); - update(); -} + void ESDiag::draw() { + title.showCaption(GET_TEXT_F(MSG_ENDSTOP_TEST)); + DWINUI::clearMainArea(); + drawPopupBkgd(); + DWINUI::drawButton(BTN_Continue, 86, 250); + DWINUI::cursor.y = 80; + #define ES_LABEL(S) draw_es_label(F(STR_##S)) + TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX)); + TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX)); + TERN_(USE_Z_MIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX)); + TERN_(HAS_FILAMENT_SENSOR, draw_es_label(F(STR_FILAMENT))); + update(); + } -void ESDiag::update() { - DWINUI::cursor.y = 80; - #define ES_REPORT(S) draw_es_state(READ(S##_PIN) == S##_ENDSTOP_HIT_STATE) - TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX)); - TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX)); - TERN_(USE_Z_MIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX)); - TERN_(HAS_FILAMENT_SENSOR, draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE)); - dwinUpdateLCD(); -} + void ESDiag::update() { + DWINUI::cursor.y = 80; + #define ES_REPORT(S) draw_es_state(READ(S##_PIN) == S##_ENDSTOP_HIT_STATE) + TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX)); + TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX)); + TERN_(USE_Z_MIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX)); + TERN_(HAS_FILAMENT_SENSOR, draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE)); + dwinUpdateLCD(); + } -#endif // HAS_ESDIAG + #endif // HAS_ESDIAG #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp b/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp index 045615f3c2ae..12e3808d192b 100644 --- a/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp +++ b/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp @@ -31,203 +31,203 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" - -#if HAS_GCODE_PREVIEW - -#include "gcode_preview.h" - -#include "../../marlinui.h" -#include "../../../sd/cardreader.h" -#include "../../../MarlinCore.h" // for wait_for_user -#include "dwin.h" -#include "dwin_popup.h" -#include "base64.h" - -#define THUMBWIDTH 230 -#define THUMBHEIGHT 180 - -Preview preview; - -typedef struct { - char name[13] = ""; // 8.3 + null - uint32_t thumbstart = 0; - int thumbsize = 0; - int thumbheight = 0, thumbwidth = 0; - float time = 0; - float filament = 0; - float layer = 0; - float width = 0, height = 0, length = 0; - - void setname(const char * const fn) { - const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); - memcpy(name, fn, len); - name[len] = '\0'; - } - - void clear() { - name[0] = '\0'; - thumbstart = 0; - thumbsize = 0; - thumbheight = thumbwidth = 0; - time = 0; - filament = 0; - layer = 0; - height = width = length = 0; - } - -} fileprop_t; - -fileprop_t fileprop; - -void getValue(const char * const buf, PGM_P const key, float &value) { - if (value != 0.0f) return; - - char *posptr = strstr_P(buf, key); - if (posptr == nullptr) return; - - char num[10] = ""; - for (uint8_t i = 0; i < sizeof(num);) { - const char c = *posptr; - if (ISEOL(c) || c == '\0') { - num[i] = '\0'; - value = atof(num); - break; + #include "dwin_defines.h" + + #if HAS_GCODE_PREVIEW + + #include "gcode_preview.h" + + #include "../../marlinui.h" + #include "../../../sd/cardreader.h" + #include "../../../MarlinCore.h" // for wait_for_user + #include "dwin.h" + #include "dwin_popup.h" + #include "base64.h" + + #define THUMBWIDTH 230 + #define THUMBHEIGHT 180 + + Preview preview; + + typedef struct { + char name[13] = ""; // 8.3 + null + uint32_t thumbstart = 0; + int thumbsize = 0; + int thumbheight = 0, thumbwidth = 0; + float time = 0; + float filament = 0; + float layer = 0; + float width = 0, height = 0, length = 0; + + void setname(const char * const fn) { + const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); + memcpy(name, fn, len); + name[len] = '\0'; + } + + void clear() { + name[0] = '\0'; + thumbstart = 0; + thumbsize = 0; + thumbheight = thumbwidth = 0; + time = 0; + filament = 0; + layer = 0; + height = width = length = 0; + } + + } fileprop_t; + + fileprop_t fileprop; + + void getValue(const char * const buf, PGM_P const key, float &value) { + if (value != 0.0f) return; + + char *posptr = strstr_P(buf, key); + if (posptr == nullptr) return; + + char num[10] = ""; + for (uint8_t i = 0; i < sizeof(num);) { + const char c = *posptr; + if (ISEOL(c) || c == '\0') { + num[i] = '\0'; + value = atof(num); + break; + } + if (WITHIN(c, '0', '9') || c == '.') num[i++] = c; + posptr++; + } } - if (WITHIN(c, '0', '9') || c == '.') num[i++] = c; - posptr++; - } -} - -bool Preview::hasPreview() { - const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT)); - char *posptr = nullptr; - uint32_t indx = 0; - float tmp = 0; - - fileprop.clear(); - fileprop.setname(card.filename); - - card.openFileRead(fileprop.name); - - char buf[256]; - uint8_t nbyte = 1; - while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) { - nbyte = card.read(buf, sizeof(buf) - 1); - if (nbyte > 0) { - buf[nbyte] = '\0'; - getValue(buf, PSTR(";TIME:"), fileprop.time); - getValue(buf, PSTR(";Filament used:"), fileprop.filament); - getValue(buf, PSTR(";Layer height:"), fileprop.layer); - getValue(buf, PSTR(";MINX:"), tmp); - getValue(buf, PSTR(";MAXX:"), fileprop.width); - fileprop.width -= tmp; - tmp = 0; - getValue(buf, PSTR(";MINY:"), tmp); - getValue(buf, PSTR(";MAXY:"), fileprop.length); - fileprop.length -= tmp; - tmp = 0; - getValue(buf, PSTR(";MINZ:"), tmp); - getValue(buf, PSTR(";MAXZ:"), fileprop.height); - fileprop.height -= tmp; - posptr = strstr_P(buf, tbstart); - if (posptr != nullptr) { - fileprop.thumbstart = indx + (posptr - &buf[0]); + + bool Preview::hasPreview() { + const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT)); + char *posptr = nullptr; + uint32_t indx = 0; + float tmp = 0; + + fileprop.clear(); + fileprop.setname(card.filename); + + card.openFileRead(fileprop.name); + + char buf[256]; + uint8_t nbyte = 1; + while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) { + nbyte = card.read(buf, sizeof(buf) - 1); + if (nbyte > 0) { + buf[nbyte] = '\0'; + getValue(buf, PSTR(";TIME:"), fileprop.time); + getValue(buf, PSTR(";Filament used:"), fileprop.filament); + getValue(buf, PSTR(";Layer height:"), fileprop.layer); + getValue(buf, PSTR(";MINX:"), tmp); + getValue(buf, PSTR(";MAXX:"), fileprop.width); + fileprop.width -= tmp; + tmp = 0; + getValue(buf, PSTR(";MINY:"), tmp); + getValue(buf, PSTR(";MAXY:"), fileprop.length); + fileprop.length -= tmp; + tmp = 0; + getValue(buf, PSTR(";MINZ:"), tmp); + getValue(buf, PSTR(";MAXZ:"), fileprop.height); + fileprop.height -= tmp; + posptr = strstr_P(buf, tbstart); + if (posptr != nullptr) { + fileprop.thumbstart = indx + (posptr - &buf[0]); + } + else { + indx += _MAX(10, nbyte - (signed)strlen_P(tbstart)); + card.setIndex(indx); + } + } } - else { - indx += _MAX(10, nbyte - (signed)strlen_P(tbstart)); - card.setIndex(indx); + + if (!fileprop.thumbstart) { + card.closefile(); + LCD_MESSAGE_F("Thumbnail not found"); + return false; } + + // Get the size of the thumbnail + card.setIndex(fileprop.thumbstart + strlen_P(tbstart)); + for (uint8_t i = 0; i < 16; i++) { + const char c = card.get(); + if (ISEOL(c)) { buf[i] = '\0'; break; } + buf[i] = c; + } + fileprop.thumbsize = atoi(buf); + + // Exit if there isn't a thumbnail + if (!fileprop.thumbsize) { + card.closefile(); + LCD_MESSAGE_F("Invalid Thumbnail Size"); + return false; + } + + uint8_t buf64[fileprop.thumbsize + 1]; + uint16_t nread = 0; + while (nread < fileprop.thumbsize) { + const uint8_t c = card.get(); + if (!ISEOL(c) && c != ';' && c != ' ') + buf64[nread++] = c; + } + card.closefile(); + buf64[nread] = '\0'; + + uint8_t thumbdata[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail + fileprop.thumbsize = decode_base64(buf64, thumbdata); + DWINUI::writeToSRAM(0x00, fileprop.thumbsize, thumbdata); + + fileprop.thumbwidth = THUMBWIDTH; + fileprop.thumbheight = THUMBHEIGHT; + + return true; } - } - - if (!fileprop.thumbstart) { - card.closefile(); - LCD_MESSAGE_F("Thumbnail not found"); - return false; - } - - // Get the size of the thumbnail - card.setIndex(fileprop.thumbstart + strlen_P(tbstart)); - for (uint8_t i = 0; i < 16; i++) { - const char c = card.get(); - if (ISEOL(c)) { buf[i] = '\0'; break; } - buf[i] = c; - } - fileprop.thumbsize = atoi(buf); - - // Exit if there isn't a thumbnail - if (!fileprop.thumbsize) { - card.closefile(); - LCD_MESSAGE_F("Invalid Thumbnail Size"); - return false; - } - - uint8_t buf64[fileprop.thumbsize + 1]; - uint16_t nread = 0; - while (nread < fileprop.thumbsize) { - const uint8_t c = card.get(); - if (!ISEOL(c) && c != ';' && c != ' ') - buf64[nread++] = c; - } - card.closefile(); - buf64[nread] = '\0'; - - uint8_t thumbdata[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail - fileprop.thumbsize = decode_base64(buf64, thumbdata); - DWINUI::writeToSRAM(0x00, fileprop.thumbsize, thumbdata); - - fileprop.thumbwidth = THUMBWIDTH; - fileprop.thumbheight = THUMBHEIGHT; - - return true; -} - -void Preview::drawFromSD() { - if (!hasPreview()) { - hmiFlag.select_flag = 1; - wait_for_user = false; - return; - } - - MString<45> buf; - dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1); - if (fileprop.time) { - buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60); - DWINUI::drawString(20, 10, &buf); - } - if (fileprop.filament) { - buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m")); - DWINUI::drawString(20, 30, &buf); - } - if (fileprop.layer) { - buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm")); - DWINUI::drawString(20, 50, &buf); - } - if (fileprop.width) { - buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm")); - DWINUI::drawString(20, 70, &buf); - } - DWINUI::drawButton(BTN_Print, 26, 290); - DWINUI::drawButton(BTN_Cancel, 146, 290); - show(); - drawSelectHighlight(true, 290); - dwinUpdateLCD(); -} - -void Preview::invalidate() { - fileprop.thumbsize = 0; -} - -bool Preview::valid() { - return !!fileprop.thumbsize; -} - -void Preview::show() { - const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2, - ypos = (205 - fileprop.thumbheight) / 2 + 87; - dwinIconShow(xpos, ypos, 0x00); -} - -#endif // HAS_GCODE_PREVIEW + + void Preview::drawFromSD() { + if (!hasPreview()) { + hmiFlag.select_flag = 1; + wait_for_user = false; + return; + } + + MString<45> buf; + dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1); + if (fileprop.time) { + buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60); + DWINUI::drawString(20, 10, &buf); + } + if (fileprop.filament) { + buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m")); + DWINUI::drawString(20, 30, &buf); + } + if (fileprop.layer) { + buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm")); + DWINUI::drawString(20, 50, &buf); + } + if (fileprop.width) { + buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm")); + DWINUI::drawString(20, 70, &buf); + } + DWINUI::drawButton(BTN_Print, 26, 290); + DWINUI::drawButton(BTN_Cancel, 146, 290); + show(); + drawSelectHighlight(true, 290); + dwinUpdateLCD(); + } + + void Preview::invalidate() { + fileprop.thumbsize = 0; + } + + bool Preview::valid() { + return !!fileprop.thumbsize; + } + + void Preview::show() { + const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2, + ypos = (205 - fileprop.thumbheight) / 2 + 87; + dwinIconShow(xpos, ypos, 0x00); + } + + #endif // HAS_GCODE_PREVIEW #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp index cc18bdd214d6..6bde818215d3 100644 --- a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp +++ b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp @@ -31,48 +31,48 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" + #include "dwin_defines.h" -#if HAS_LOCKSCREEN + #if HAS_LOCKSCREEN -#include "dwin.h" -#include "lockscreen.h" + #include "dwin.h" + #include "lockscreen.h" -LockScreen lockScreen; + LockScreen lockScreen; -uint8_t LockScreen::lock_pos = 0; -bool LockScreen::unlocked = false; -uint8_t LockScreen::rprocess = 0; + uint8_t LockScreen::lock_pos = 0; + bool LockScreen::unlocked = false; + uint8_t LockScreen::rprocess = 0; -void LockScreen::init() { - lock_pos = 0; - unlocked = false; - draw(); -} + void LockScreen::init() { + lock_pos = 0; + unlocked = false; + draw(); + } -void LockScreen::draw() { - title.setCaption(GET_TEXT_F(MSG_LOCKSCREEN)); - DWINUI::clearMainArea(); - DWINUI::drawIcon(ICON_LOGO, 71, 120); // CREALITY logo - DWINUI::drawCenteredString(COLOR_WHITE, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED)); - DWINUI::drawCenteredString(COLOR_WHITE, 200, GET_TEXT_F(MSG_LOCKSCREEN_UNLOCK)); - DWINUI::drawCenteredString(COLOR_WHITE, 240, F("-> | <-")); - dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); - dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); - dwinUpdateLCD(); -} + void LockScreen::draw() { + title.setCaption(GET_TEXT_F(MSG_LOCKSCREEN)); + DWINUI::clearMainArea(); + DWINUI::drawIcon(ICON_LOGO, 71, 120); // CREALITY logo + DWINUI::drawCenteredString(COLOR_WHITE, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED)); + DWINUI::drawCenteredString(COLOR_WHITE, 200, GET_TEXT_F(MSG_LOCKSCREEN_UNLOCK)); + DWINUI::drawCenteredString(COLOR_WHITE, 240, F("-> | <-")); + dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); + dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); + dwinUpdateLCD(); + } -void LockScreen::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; - } - dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); - dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); - dwinUpdateLCD(); -} + void LockScreen::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; + } + dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); + dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); + dwinUpdateLCD(); + } -#endif // HAS_LOCKSCREEN + #endif // HAS_LOCKSCREEN #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/menus.cpp b/Marlin/src/lcd/e3v2/proui/menus.cpp index d537bc5ae663..9a61fd3ceff4 100644 --- a/Marlin/src/lcd/e3v2/proui/menus.cpp +++ b/Marlin/src/lcd/e3v2/proui/menus.cpp @@ -31,531 +31,531 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "../common/encoder.h" -#include "dwin.h" -#include "menus.h" - -int8_t MenuItemTotal = 0; -int8_t MenuItemCount = 0; -CustomMenuItem** menuItems = nullptr; -Menu *currentMenu = nullptr; -Menu *previousMenu = nullptr; -MenuData_t menuData; - -// Menuitem Drawing functions ================================================= - -void drawTitle(Title* aTitle) { - dwinDrawRectangle(1, hmiData.colorTitleBg, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); - if (aTitle->frameid) - dwinFrameAreaCopy(aTitle->frameid, aTitle->frame.left, aTitle->frame.top, aTitle->frame.right, aTitle->frame.bottom, 14, (TITLE_HEIGHT - (aTitle->frame.bottom - aTitle->frame.top)) / 2 - 1); - else - #if ENABLED(TITLE_CENTERED) - DWINUI::drawCenteredString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); - #else - dwinDrawString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); - #endif -} - -void drawMenuCursor(const int8_t line) { - const uint16_t ypos = MYPOS(line); - DWINUI::drawBox(1, hmiData.colorCursor, {0, ypos, 15, MLINE - 1}); -} - -void eraseMenuCursor(const int8_t line) { - const uint16_t ypos = MYPOS(line); - DWINUI::drawBox(1, hmiData.colorBackground, {0, ypos, 15, MLINE - 1}); -} - -void eraseMenuText(const int8_t line) { - if (line < 0 || line >= TROWS) return; - const uint16_t ypos = MYPOS(line) + 1; - DWINUI::drawBox(1, hmiData.colorBackground, {LBLX, ypos, DWIN_WIDTH - LBLX, MLINE - 2}); -} - -void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, const char * const label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { - if (icon) DWINUI::drawIcon(icon, ICOX, MBASE(line) - 3); - if (label) DWINUI::drawString(LBLX, MBASE(line) - 1, (char*)label); - if (more) DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); - if (selected) drawMenuCursor(line); - dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); -} - -void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, FSTR_P label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { - drawMenuLine(line, icon, FTOP(label), more, selected); -} - -void drawCheckboxLine(const uint8_t line, const bool checked) { - DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); -} - -void showCheckboxLine(const bool checked) { - const uint8_t line = currentMenu->line(); - DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); - dwinUpdateLCD(); -} - -void toggleCheckboxLine(bool &checked) { - checked = !checked; - showCheckboxLine(checked); -} - -void drawMenuIntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value/*=0*/) { - DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(line) - 1, value); -} - -void onDrawMenuItem(MenuItem* menuitem, int8_t line) { - if (menuitem->icon) DWINUI::drawIcon(menuitem->icon, ICOX, MBASE(line) - 3); - if (menuitem->frameid) - dwinFrameAreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); - else if (menuitem->caption) - DWINUI::drawString(LBLX, MBASE(line) - 1, menuitem->caption); - dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); -} - -void onDrawSubMenu(MenuItem* menuitem, int8_t line) { - onDrawMenuItem(menuitem, line); - DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); -} - -void onDrawIntMenu(MenuItem* menuitem, int8_t line, int32_t value) { - onDrawMenuItem(menuitem, line); - drawMenuIntValue(hmiData.colorBackground, line, 4, value); -} - -void onDrawPIntMenu(MenuItem* menuitem, int8_t line) { - const int16_t value = *(int16_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); -} - -void onDrawPInt8Menu(MenuItem* menuitem, int8_t line) { - const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); -} - -void onDrawPInt32Menu(MenuItem* menuitem, int8_t line) { - const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); -} - -void onDrawFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp, const float value) { - onDrawMenuItem(menuitem, line); - DWINUI::drawSignedFloat(hmiData.colorText, hmiData.colorBackground, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); -} - -void onDrawPFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp) { - const float value = *(float*)static_cast(menuitem)->value; - onDrawFloatMenu(menuitem, line, dp, value); -} - -void onDrawChkbMenu(MenuItem* menuitem, int8_t line, bool checked) { - onDrawMenuItem(menuitem, line); - drawCheckboxLine(line, checked); -} - -void onDrawChkbMenu(MenuItem* menuitem, int8_t line) { - const bool val = *(bool*)static_cast(menuitem)->value; - onDrawChkbMenu(menuitem, line, val); -} - -void DrawItemEdit(const bool selected) { - const uint16_t bcolor = selected ? hmiData.colorSelected : hmiData.colorBackground; - const uint8_t iNum = 4 - ((menuData.dp > 0) ? (menuData.dp - 1) : 0); - switch (checkkey) { - case ID_SetIntNoDraw: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case ID_SetInt: - case ID_SetPInt: DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(currentMenu->line()) - 1, menuData.value); break; - case ID_SetFloat: - case ID_SetPFloat: DWINUI::drawSignedFloat(hmiData.colorText, bcolor, iNum, menuData.dp, VALX - 2 * DWINUI::fontWidth(), 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); - DrawItemEdit(true); -} - -// 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); - DrawItemEdit(true); -} - -// 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(ID_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.intPtr = (int16_t*)static_cast(currentMenu->selectedItem())->value; - const int32_t value = *menuData.intPtr; - setValueOnClick(ID_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(ID_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.floatPtr = (float*)static_cast(currentMenu->selectedItem())->value; - setValueOnClick(ID_SetPFloat, lo, hi, dp, *menuData.floatPtr, apply, liveUpdate); -} - -// HMI Control functions ====================================================== - -// Generic menu control using the encoder -void hmiMenu() { - EncoderState encoder_diffState = get_encoder_state(); - if (currentMenu) { - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_ENTER) - currentMenu->onClick(); + #include "../common/encoder.h" + #include "dwin.h" + #include "menus.h" + + int8_t MenuItemTotal = 0; + int8_t MenuItemCount = 0; + CustomMenuItem** menuItems = nullptr; + Menu *currentMenu = nullptr; + Menu *previousMenu = nullptr; + MenuData_t menuData; + + // Menuitem Drawing functions ================================================= + + void drawTitle(Title* aTitle) { + dwinDrawRectangle(1, hmiData.colorTitleBg, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); + if (aTitle->frameid) + dwinFrameAreaCopy(aTitle->frameid, aTitle->frame.left, aTitle->frame.top, aTitle->frame.right, aTitle->frame.bottom, 14, (TITLE_HEIGHT - (aTitle->frame.bottom - aTitle->frame.top)) / 2 - 1); else - currentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); - } -} - -// Get a value using the encoder -// draw : draw the value -// Return value: -// 0 : no change -// 1 : live change -// 2 : apply change -int8_t hmiGet(bool draw) { - const int32_t lo = menuData.minValue; - const int32_t hi = menuData.maxValue; - const int32_t cval = menuData.value; - EncoderState encoder_diffState = TERN(SMOOTH_ENCODER_MENUITEMS, get_encoder_state(), encoderReceiveAnalyze()); - if (encoder_diffState != ENCODER_DIFF_NO) { - if (applyEncoder(encoder_diffState, menuData.value)) { - encoderRate.enabled = false; - if (draw) DrawItemEdit(false); - checkkey = ID_Menu; - return 2; - } - LIMIT(menuData.value, lo, hi); - } - const bool change = cval != menuData.value; - if (change) DrawItemEdit(true); - return int8_t(change); -} - -// Set and draw a value using the encoder -void hmiSetDraw() { - int8_t val = hmiGet(true); - switch (val) { - case 0: return; - case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case 2: if (menuData.apply) menuData.apply(); break; - } -} - -// Set an value without drawing -void hmiSetNoDraw() { - int8_t val = hmiGet(false); - switch (val) { - case 0: return; - 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 hmiSetPInt() { - int8_t val = hmiGet(true); - switch (val) { - case 0: return; - case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case 2: *menuData.intPtr = menuData.value; if (menuData.apply) menuData.apply(); break; - } -} - -// Set a scaled float pointer variable using the encoder -void hmiSetPFloat() { - const int8_t val = hmiGet(true); - switch (val) { - case 0: return; - case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case 2: *menuData.floatPtr = menuData.value / POW(10, menuData.dp); if (menuData.apply) menuData.apply(); break; - } -} - -// Menu Class =============================================================== - -Menu::Menu() { - selected = 0; - topline = 0; -} - -void Menu::draw() { - menuTitle.draw(); - DWINUI::setColors(hmiData.colorText, hmiData.colorBackground, hmiData.colorStatusBg); - dwinDrawRectangle(1, DWINUI::backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); - for (int8_t i = 0; i < MenuItemCount; i++) - menuItems[i]->draw(i - topline); - drawMenuCursor(line()); - dwinUpdateLCD(); -} - -void Menu::onScroll(bool dir) { - int8_t sel = selected; - if (dir) sel++; else sel--; - LIMIT(sel, 0, MenuItemCount - 1); - if (sel != selected) { - eraseMenuCursor(line()); + #if ENABLED(TITLE_CENTERED) + DWINUI::drawCenteredString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); + #else + dwinDrawString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); + #endif + } + + void drawMenuCursor(const int8_t line) { + const uint16_t ypos = MYPOS(line); + DWINUI::drawBox(1, hmiData.colorCursor, {0, ypos, 15, MLINE - 1}); + } + + void eraseMenuCursor(const int8_t line) { + const uint16_t ypos = MYPOS(line); + DWINUI::drawBox(1, hmiData.colorBackground, {0, ypos, 15, MLINE - 1}); + } + + void eraseMenuText(const int8_t line) { + if (line < 0 || line >= TROWS) return; + const uint16_t ypos = MYPOS(line) + 1; + DWINUI::drawBox(1, hmiData.colorBackground, {LBLX, ypos, DWIN_WIDTH - LBLX, MLINE - 2}); + } + + void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, const char * const label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { + if (icon) DWINUI::drawIcon(icon, ICOX, MBASE(line) - 3); + if (label) DWINUI::drawString(LBLX, MBASE(line) - 1, (char*)label); + if (more) DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); + if (selected) drawMenuCursor(line); + dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); + } + + void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, FSTR_P label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { + drawMenuLine(line, icon, FTOP(label), more, selected); + } + + void drawCheckboxLine(const uint8_t line, const bool checked) { + DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); + } + + void showCheckboxLine(const bool checked) { + const uint8_t line = currentMenu->line(); + DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); dwinUpdateLCD(); - if ((sel - topline) == TROWS) { - dwinFrameAreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backColor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); - topline++; - menuItems[sel]->draw(TROWS - 1); + } + + void toggleCheckboxLine(bool &checked) { + checked = !checked; + showCheckboxLine(checked); + } + + void drawMenuIntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value/*=0*/) { + DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(line) - 1, value); + } + + void onDrawMenuItem(MenuItem* menuitem, int8_t line) { + if (menuitem->icon) DWINUI::drawIcon(menuitem->icon, ICOX, MBASE(line) - 3); + if (menuitem->frameid) + dwinFrameAreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); + else if (menuitem->caption) + DWINUI::drawString(LBLX, MBASE(line) - 1, menuitem->caption); + dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); + } + + void onDrawSubMenu(MenuItem* menuitem, int8_t line) { + onDrawMenuItem(menuitem, line); + DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); + } + + void onDrawIntMenu(MenuItem* menuitem, int8_t line, int32_t value) { + onDrawMenuItem(menuitem, line); + drawMenuIntValue(hmiData.colorBackground, line, 4, value); + } + + void onDrawPIntMenu(MenuItem* menuitem, int8_t line) { + const int16_t value = *(int16_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); + } + + void onDrawPInt8Menu(MenuItem* menuitem, int8_t line) { + const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); + } + + void onDrawPInt32Menu(MenuItem* menuitem, int8_t line) { + const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); + } + + void onDrawFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp, const float value) { + onDrawMenuItem(menuitem, line); + DWINUI::drawSignedFloat(hmiData.colorText, hmiData.colorBackground, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); + } + + void onDrawPFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp) { + const float value = *(float*)static_cast(menuitem)->value; + onDrawFloatMenu(menuitem, line, dp, value); + } + + void onDrawChkbMenu(MenuItem* menuitem, int8_t line, bool checked) { + onDrawMenuItem(menuitem, line); + drawCheckboxLine(line, checked); + } + + void onDrawChkbMenu(MenuItem* menuitem, int8_t line) { + const bool val = *(bool*)static_cast(menuitem)->value; + onDrawChkbMenu(menuitem, line, val); + } + + void DrawItemEdit(const bool selected) { + const uint16_t bcolor = selected ? hmiData.colorSelected : hmiData.colorBackground; + const uint8_t iNum = 4 - ((menuData.dp > 0) ? (menuData.dp - 1) : 0); + switch (checkkey) { + case ID_SetIntNoDraw: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case ID_SetInt: + case ID_SetPInt: DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(currentMenu->line()) - 1, menuData.value); break; + case ID_SetFloat: + case ID_SetPFloat: DWINUI::drawSignedFloat(hmiData.colorText, bcolor, iNum, menuData.dp, VALX - 2 * DWINUI::fontWidth(), 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); + DrawItemEdit(true); + } + + // 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); + DrawItemEdit(true); + } + + // 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(ID_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.intPtr = (int16_t*)static_cast(currentMenu->selectedItem())->value; + const int32_t value = *menuData.intPtr; + setValueOnClick(ID_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(ID_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.floatPtr = (float*)static_cast(currentMenu->selectedItem())->value; + setValueOnClick(ID_SetPFloat, lo, hi, dp, *menuData.floatPtr, apply, liveUpdate); + } + + // HMI Control functions ====================================================== + + // Generic menu control using the encoder + void hmiMenu() { + EncoderState encoder_diffState = get_encoder_state(); + if (currentMenu) { + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_ENTER) + currentMenu->onClick(); + else + currentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); + } + } + + // Get a value using the encoder + // draw : draw the value + // Return value: + // 0 : no change + // 1 : live change + // 2 : apply change + int8_t hmiGet(bool draw) { + const int32_t lo = menuData.minValue; + const int32_t hi = menuData.maxValue; + const int32_t cval = menuData.value; + EncoderState encoder_diffState = TERN(SMOOTH_ENCODER_MENUITEMS, get_encoder_state(), encoderReceiveAnalyze()); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (applyEncoder(encoder_diffState, menuData.value)) { + encoderRate.enabled = false; + if (draw) DrawItemEdit(false); + checkkey = ID_Menu; + return 2; + } + LIMIT(menuData.value, lo, hi); + } + const bool change = cval != menuData.value; + if (change) DrawItemEdit(true); + return int8_t(change); + } + + // Set and draw a value using the encoder + void hmiSetDraw() { + int8_t val = hmiGet(true); + switch (val) { + case 0: return; + case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case 2: if (menuData.apply) menuData.apply(); break; + } + } + + // Set an value without drawing + void hmiSetNoDraw() { + int8_t val = hmiGet(false); + switch (val) { + case 0: return; + 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 hmiSetPInt() { + int8_t val = hmiGet(true); + switch (val) { + case 0: return; + case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case 2: *menuData.intPtr = menuData.value; if (menuData.apply) menuData.apply(); break; } - if ((sel < topline)) { - dwinFrameAreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backColor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); - topline--; - menuItems[sel]->draw(0); + } + + // Set a scaled float pointer variable using the encoder + void hmiSetPFloat() { + const int8_t val = hmiGet(true); + switch (val) { + case 0: return; + case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case 2: *menuData.floatPtr = menuData.value / POW(10, menuData.dp); if (menuData.apply) menuData.apply(); break; } - selected = sel; + } + + // Menu Class =============================================================== + + Menu::Menu() { + selected = 0; + topline = 0; + } + + void Menu::draw() { + menuTitle.draw(); + DWINUI::setColors(hmiData.colorText, hmiData.colorBackground, hmiData.colorStatusBg); + dwinDrawRectangle(1, DWINUI::backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); + for (int8_t i = 0; i < MenuItemCount; i++) + menuItems[i]->draw(i - topline); drawMenuCursor(line()); dwinUpdateLCD(); } -} - -void Menu::onClick() { - if (menuItems[selected]->onClick != nullptr) (*menuItems[selected]->onClick)(); -} - -CustomMenuItem *Menu::selectedItem() { - return menuItems[selected]; -} - -CustomMenuItem** Menu::items() { - return menuItems; -} - -int8_t Menu::count() { - return MenuItemCount; -}; - -/* MenuItem Class ===========================================================*/ - -void CustomMenuItem::draw(int8_t line) { - if (line < 0 || line >= TROWS) return; - if (onDraw != nullptr) (*onDraw)(static_cast(this), line); -}; - -void CustomMenuItem::redraw(bool erase/*=false*/) { - const int8_t line = currentMenu->line(this->pos); - if (erase) eraseMenuText(line); - draw(line); -} - -CustomMenuItem::CustomMenuItem(OnDrawItem ondraw, OnClickItem onclick) { - onClick = onclick; - onDraw = ondraw; -} - -MenuItem::MenuItem(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { - icon = cicon; - setCaption(text); -} - -MenuItem::MenuItem(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { - icon = cicon; - caption[0] = '\0'; - frameid = id; - frame = { x1, y1, x2, y2 }; -} - -void MenuItem::setCaption(const char * const text) { - const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text)); - memcpy(&caption[0], text, len); - caption[len] = '\0'; -} - -void MenuItem::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 }; -} - -MenuItemPtr::MenuItemPtr(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) : MenuItem(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 = _MIN(totalitems, MENU_MAX_ITEMS); - menuItems = new CustomMenuItem*[totalitems]; -} - -bool isMenu(Menu* _menu) { - return ((checkkey == ID_Menu) && !!currentMenu && (currentMenu == _menu)); -} - -template -T* menuItemAdd(T* menuitem) { - menuItems[MenuItemCount] = menuitem; - menuitem->pos = MenuItemCount++; - return menuitem; -} - -CustomMenuItem* menuItemAdd(OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { - if (MenuItemCount < MenuItemTotal) { - CustomMenuItem* menuitem = new CustomMenuItem(ondraw, onclick); - return menuItemAdd(menuitem); - } - else return nullptr; -} - -MenuItem* menuItemAdd(uint8_t cicon, const char * const text/*=nullptr*/, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { - if (MenuItemCount < MenuItemTotal) { - MenuItem* menuitem = new MenuItem(cicon, text, ondraw, onclick); - return menuItemAdd(menuitem); - } - else return nullptr; -} - -MenuItem* menuItemAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { - if (MenuItemCount < MenuItemTotal) { - MenuItem* menuitem = new MenuItem(cicon, id, x1, y1, x2, y2, ondraw, onclick); - return menuItemAdd(menuitem); - } - else return nullptr; -} - -MenuItem* editItemAdd(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) { - if (MenuItemCount < MenuItemTotal) { - MenuItem* menuitem = new MenuItemPtr(cicon, text, ondraw, onclick, val); - return menuItemAdd(menuitem); - } - else return nullptr; -} - -void initMenu() { - currentMenu = nullptr; - previousMenu = nullptr; -} - -bool setMenu(Menu* &menu, FSTR_P fTitle, int8_t totalitems) { - if (!menu) menu = new Menu(); - const bool notCurrent = (currentMenu != menu); - if (notCurrent) { - menu->menuTitle.setCaption(fTitle); - menuItemsPrepare(totalitems); - } - return notCurrent; -} - -bool setMenu(Menu* &menu, frame_rect_t cn, FSTR_P fTitle, int8_t totalitems) { - if (!menu) menu = new Menu(); - const bool notCurrent = (currentMenu != menu); - if (notCurrent) { - if (cn.w != 0) - menu->menuTitle.setFrame(cn.x, cn.y, cn.w, cn.h); - else + + void Menu::onScroll(bool dir) { + int8_t sel = selected; + if (dir) sel++; else sel--; + LIMIT(sel, 0, MenuItemCount - 1); + if (sel != selected) { + eraseMenuCursor(line()); + dwinUpdateLCD(); + if ((sel - topline) == TROWS) { + dwinFrameAreaMove(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)) { + dwinFrameAreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backColor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); + topline--; + menuItems[sel]->draw(0); + } + selected = sel; + drawMenuCursor(line()); + dwinUpdateLCD(); + } + } + + void Menu::onClick() { + if (menuItems[selected]->onClick != nullptr) (*menuItems[selected]->onClick)(); + } + + CustomMenuItem *Menu::selectedItem() { + return menuItems[selected]; + } + + CustomMenuItem** Menu::items() { + return menuItems; + } + + int8_t Menu::count() { + return MenuItemCount; + }; + + /* MenuItem Class ===========================================================*/ + + void CustomMenuItem::draw(int8_t line) { + if (line < 0 || line >= TROWS) return; + if (onDraw != nullptr) (*onDraw)(static_cast(this), line); + }; + + void CustomMenuItem::redraw(bool erase/*=false*/) { + const int8_t line = currentMenu->line(this->pos); + if (erase) eraseMenuText(line); + draw(line); + } + + CustomMenuItem::CustomMenuItem(OnDrawItem ondraw, OnClickItem onclick) { + onClick = onclick; + onDraw = ondraw; + } + + MenuItem::MenuItem(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { + icon = cicon; + setCaption(text); + } + + MenuItem::MenuItem(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { + icon = cicon; + caption[0] = '\0'; + frameid = id; + frame = { x1, y1, x2, y2 }; + } + + void MenuItem::setCaption(const char * const text) { + const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text)); + memcpy(&caption[0], text, len); + caption[len] = '\0'; + } + + void MenuItem::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 }; + } + + MenuItemPtr::MenuItemPtr(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) : MenuItem(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 = _MIN(totalitems, MENU_MAX_ITEMS); + menuItems = new CustomMenuItem*[totalitems]; + } + + bool isMenu(Menu* _menu) { + return ((checkkey == ID_Menu) && !!currentMenu && (currentMenu == _menu)); + } + + template + T* menuItemAdd(T* menuitem) { + menuItems[MenuItemCount] = menuitem; + menuitem->pos = MenuItemCount++; + return menuitem; + } + + CustomMenuItem* menuItemAdd(OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + CustomMenuItem* menuitem = new CustomMenuItem(ondraw, onclick); + return menuItemAdd(menuitem); + } + else return nullptr; + } + + MenuItem* menuItemAdd(uint8_t cicon, const char * const text/*=nullptr*/, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + MenuItem* menuitem = new MenuItem(cicon, text, ondraw, onclick); + return menuItemAdd(menuitem); + } + else return nullptr; + } + + MenuItem* menuItemAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + MenuItem* menuitem = new MenuItem(cicon, id, x1, y1, x2, y2, ondraw, onclick); + return menuItemAdd(menuitem); + } + else return nullptr; + } + + MenuItem* editItemAdd(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) { + if (MenuItemCount < MenuItemTotal) { + MenuItem* menuitem = new MenuItemPtr(cicon, text, ondraw, onclick, val); + return menuItemAdd(menuitem); + } + else return nullptr; + } + + void initMenu() { + currentMenu = nullptr; + previousMenu = nullptr; + } + + bool setMenu(Menu* &menu, FSTR_P fTitle, int8_t totalitems) { + if (!menu) menu = new Menu(); + const bool notCurrent = (currentMenu != menu); + if (notCurrent) { menu->menuTitle.setCaption(fTitle); - menuItemsPrepare(totalitems); + menuItemsPrepare(totalitems); + } + return notCurrent; } - return notCurrent; -} -void resetMenu(Menu* &menu) { - if (menu) { - menu->topline = 0; - menu->selected = 0; + bool setMenu(Menu* &menu, frame_rect_t cn, FSTR_P fTitle, int8_t totalitems) { + if (!menu) menu = new Menu(); + const bool notCurrent = (currentMenu != menu); + if (notCurrent) { + if (cn.w != 0) + menu->menuTitle.setFrame(cn.x, cn.y, cn.w, cn.h); + else + menu->menuTitle.setCaption(fTitle); + menuItemsPrepare(totalitems); + } + return notCurrent; + } + + void resetMenu(Menu* &menu) { + if (menu) { + menu->topline = 0; + menu->selected = 0; + } } -} -void invalidateMenu() { - resetMenu(currentMenu); - currentMenu = nullptr; -} + void invalidateMenu() { + resetMenu(currentMenu); + currentMenu = nullptr; + } -void updateMenu(Menu* &menu) { - if (!menu) return; - if (currentMenu != menu) { - previousMenu = currentMenu; - currentMenu = menu; + void updateMenu(Menu* &menu) { + if (!menu) return; + if (currentMenu != menu) { + previousMenu = currentMenu; + currentMenu = menu; + } + menu->draw(); } - menu->draw(); -} -void ReDrawMenu(bool force/*=false*/) { - if (currentMenu && (force || checkkey == ID_Menu)) currentMenu->draw(); - if (force) DrawItemEdit(true); -} + void ReDrawMenu(bool force/*=false*/) { + if (currentMenu && (force || checkkey == ID_Menu)) currentMenu->draw(); + if (force) DrawItemEdit(true); + } -void ReDrawItem() { - static_cast(currentMenu->selectedItem())->redraw(false); -} + void ReDrawItem() { + static_cast(currentMenu->selectedItem())->redraw(false); + } #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/meshviewer.cpp b/Marlin/src/lcd/e3v2/proui/meshviewer.cpp index 1c5f08bb4dfa..4803d2f92e8e 100644 --- a/Marlin/src/lcd/e3v2/proui/meshviewer.cpp +++ b/Marlin/src/lcd/e3v2/proui/meshviewer.cpp @@ -31,118 +31,118 @@ #if ALL(DWIN_LCD_PROUI, HAS_MESH) -#include "../../../core/types.h" -#include "../../marlinui.h" -#include "dwin.h" -#include "dwin_popup.h" -#include "../../../feature/bedlevel/bedlevel.h" -#include "meshviewer.h" - -#if ENABLED(USE_GRID_MESHVIEWER) - #include "bedlevel_tools.h" -#endif - -bool meshredraw; // Redraw mesh points -uint8_t sizex, sizey; // Mesh XY size -uint8_t rmax; // Maximum radius -#define margin 25 // XY Margins -#define rmin 5 // Minimum radius -#define zmin -20 // rmin at z=-0.20 -#define zmax 20 // rmax at z= 0.20 -#define width DWIN_WIDTH - 2 * margin -#define r(z) ((z - zmin) * (rmax - rmin) / (zmax - zmin) + rmin) -#define px(xp) (margin + (xp) * (width) / (sizex - 1)) -#define py(yp) (30 + DWIN_WIDTH - margin - (yp) * (width) / (sizey - 1)) - -constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - -MeshViewer meshViewer; - -float MeshViewer::max, MeshViewer::min; - -void MeshViewer::drawMeshGrid(const uint8_t csizex, const uint8_t csizey) { - sizex = csizex; - sizey = csizey; - rmax = _MIN(margin - 2, 0.5 * (width) / (sizex - 1)); - min = 100; - max = -100; - DWINUI::clearMainArea(); - dwinDrawRectangle(0, hmiData.colorSplitLine, px(0), py(0), px(sizex - 1), py(sizey - 1)); - for (uint8_t x = 1; x < sizex - 1; ++x) dwinDrawVLine(hmiData.colorSplitLine, px(x), py(sizey - 1), width); - for (uint8_t y = 1; y < sizey - 1; ++y) dwinDrawHLine(hmiData.colorSplitLine, px(0), py(y), width); -} - -void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) { - const uint8_t fs = DWINUI::fontWidth(meshfont); - const int16_t v = isnan(z) ? 0 : round(z * 100); - NOLESS(max, z); NOMORE(min, z); - - const uint16_t color = DWINUI::rainbowInt(v, zmin, zmax); - DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v, zmax), zmin))); - TERN_(TJC_DISPLAY, delay(100)); - - const uint16_t fy = py(y) - fs; - if (sizex < TERN(TJC_DISPLAY, 8, 9)) { - if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2 * fs, fy, 0); - else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3 * fs, fy, z); + #include "../../../core/types.h" + #include "../../marlinui.h" + #include "dwin.h" + #include "dwin_popup.h" + #include "../../../feature/bedlevel/bedlevel.h" + #include "meshviewer.h" + + #if ENABLED(USE_GRID_MESHVIEWER) + #include "bedlevel_tools.h" + #endif + + bool meshredraw; // Redraw mesh points + uint8_t sizex, sizey; // Mesh XY size + uint8_t rmax; // Maximum radius + #define margin 25 // XY Margins + #define rmin 5 // Minimum radius + #define zmin -20 // rmin at z=-0.20 + #define zmax 20 // rmax at z= 0.20 + #define width DWIN_WIDTH - 2 * margin + #define r(z) ((z - zmin) * (rmax - rmin) / (zmax - zmin) + rmin) + #define px(xp) (margin + (xp) * (width) / (sizex - 1)) + #define py(yp) (30 + DWIN_WIDTH - margin - (yp) * (width) / (sizey - 1)) + + constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); + + MeshViewer meshViewer; + + float MeshViewer::max, MeshViewer::min; + + void MeshViewer::drawMeshGrid(const uint8_t csizex, const uint8_t csizey) { + sizex = csizex; + sizey = csizey; + rmax = _MIN(margin - 2, 0.5 * (width) / (sizex - 1)); + min = 100; + max = -100; + DWINUI::clearMainArea(); + dwinDrawRectangle(0, hmiData.colorSplitLine, px(0), py(0), px(sizex - 1), py(sizey - 1)); + for (uint8_t x = 1; x < sizex - 1; ++x) dwinDrawVLine(hmiData.colorSplitLine, px(x), py(sizey - 1), width); + for (uint8_t y = 1; y < sizey - 1; ++y) dwinDrawHLine(hmiData.colorSplitLine, px(0), py(y), width); } - else { - char msg[9]; msg[0] = '\0'; - switch (v) { - case -999 ... -100: - case 100 ... 999: DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, fy, z); break; - case -99 ... -1: sprintf_P(msg, PSTR("-.%2i"), -v); break; - case 1 ... 99: sprintf_P(msg, PSTR( ".%2i"), v); break; - default: - dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, fy, "0"); - return; + + void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) { + const uint8_t fs = DWINUI::fontWidth(meshfont); + const int16_t v = isnan(z) ? 0 : round(z * 100); + NOLESS(max, z); NOMORE(min, z); + + const uint16_t color = DWINUI::rainbowInt(v, zmin, zmax); + DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v, zmax), zmin))); + TERN_(TJC_DISPLAY, delay(100)); + + const uint16_t fy = py(y) - fs; + if (sizex < TERN(TJC_DISPLAY, 8, 9)) { + if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2 * fs, fy, 0); + else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3 * fs, fy, z); + } + else { + char msg[9]; msg[0] = '\0'; + switch (v) { + case -999 ... -100: + case 100 ... 999: DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, fy, z); break; + case -99 ... -1: sprintf_P(msg, PSTR("-.%2i"), -v); break; + case 1 ... 99: sprintf_P(msg, PSTR( ".%2i"), v); break; + default: + dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, fy, "0"); + return; + } + dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, fy, msg); } - dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, fy, msg); } -} -void MeshViewer::drawMesh(const bed_mesh_t zval, const uint8_t csizex, const uint8_t csizey) { - drawMeshGrid(csizex, csizey); - for (uint8_t y = 0; y < csizey; ++y) { - hal.watchdog_refresh(); - for (uint8_t x = 0; x < csizex; ++x) drawMeshPoint(x, y, zval[x][y]); + void MeshViewer::drawMesh(const bed_mesh_t zval, const uint8_t csizex, const uint8_t csizey) { + drawMeshGrid(csizex, csizey); + for (uint8_t y = 0; y < csizey; ++y) { + hal.watchdog_refresh(); + for (uint8_t x = 0; x < csizex; ++x) drawMeshPoint(x, y, zval[x][y]); + } } -} -void MeshViewer::draw(const bool withsave/*=false*/, const bool redraw/*=true*/) { - title.showCaption(GET_TEXT_F(MSG_MESH_VIEWER)); - #if ENABLED(USE_GRID_MESHVIEWER) - DWINUI::clearMainArea(); - bedLevelTools.viewer_print_value = true; - bedLevelTools.drawBedMesh(-1, 1, 8, 10 + TITLE_HEIGHT); - #else - if (redraw) drawMesh(bedlevel.z_values, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); - else DWINUI::drawBox(1, hmiData.colorBackground, { 89, 305, 99, 38 }); - #endif - if (withsave) { - DWINUI::drawButton(BTN_Save, 26, 305); - DWINUI::drawButton(BTN_Continue, 146, 305); - drawSelectHighlight(hmiFlag.select_flag, 305); + void MeshViewer::draw(const bool withsave/*=false*/, const bool redraw/*=true*/) { + title.showCaption(GET_TEXT_F(MSG_MESH_VIEWER)); + #if ENABLED(USE_GRID_MESHVIEWER) + DWINUI::clearMainArea(); + bedLevelTools.viewer_print_value = true; + bedLevelTools.drawBedMesh(-1, 1, 8, 10 + TITLE_HEIGHT); + #else + if (redraw) drawMesh(bedlevel.z_values, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); + else DWINUI::drawBox(1, hmiData.colorBackground, { 89, 305, 99, 38 }); + #endif + if (withsave) { + DWINUI::drawButton(BTN_Save, 26, 305); + DWINUI::drawButton(BTN_Continue, 146, 305); + drawSelectHighlight(hmiFlag.select_flag, 305); + } + else + DWINUI::drawButton(BTN_Continue, 86, 305); + + #if ENABLED(USE_GRID_MESHVIEWER) + bedLevelTools.setMeshViewerStatus(); + #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 } - else - DWINUI::drawButton(BTN_Continue, 86, 305); - #if ENABLED(USE_GRID_MESHVIEWER) - bedLevelTools.setMeshViewerStatus(); - #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 drawMeshViewer() { meshViewer.draw(true, meshredraw); } -void drawMeshViewer() { meshViewer.draw(true, meshredraw); } + void onClick_MeshViewer() { if (hmiFlag.select_flag) saveMesh(); hmiReturnScreen(); } -void onClick_MeshViewer() { if (hmiFlag.select_flag) saveMesh(); hmiReturnScreen(); } - -void gotoMeshViewer(const bool redraw) { - meshredraw = redraw; - if (leveling_is_valid()) gotoPopup(drawMeshViewer, onClick_MeshViewer); - else hmiReturnScreen(); -} + void gotoMeshViewer(const bool redraw) { + meshredraw = redraw; + if (leveling_is_valid()) gotoPopup(drawMeshViewer, onClick_MeshViewer); + else hmiReturnScreen(); + } #endif // DWIN_LCD_PROUI && HAS_MESH diff --git a/Marlin/src/lcd/e3v2/proui/plot.cpp b/Marlin/src/lcd/e3v2/proui/plot.cpp index 92c6c947177b..891da1c27970 100644 --- a/Marlin/src/lcd/e3v2/proui/plot.cpp +++ b/Marlin/src/lcd/e3v2/proui/plot.cpp @@ -31,52 +31,52 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" + #include "dwin_defines.h" -#if PROUI_TUNING_GRAPH + #if PROUI_TUNING_GRAPH -#include "dwin.h" -#include "../../marlinui.h" -#include "plot.h" + #include "dwin.h" + #include "../../marlinui.h" + #include "plot.h" -#define Plot_Bg_Color RGB( 1, 12, 8) + #define Plot_Bg_Color RGB( 1, 12, 8) -Plot plot; + Plot plot; -uint16_t graphpoints, r, x2, y2 = 0; -frame_rect_t graphframe = {0}; -float scale = 0; + uint16_t graphpoints, r, x2, y2 = 0; + frame_rect_t graphframe = {0}; + float scale = 0; -void Plot::draw(const frame_rect_t &frame, const_celsius_float_t max, const_float_t ref/*=0*/) { - graphframe = frame; - graphpoints = 0; - scale = frame.h / max; - x2 = frame.x + frame.w - 1; - y2 = frame.y + frame.h - 1; - r = round((y2) - ref * scale); - DWINUI::drawBox(1, Plot_Bg_Color, frame); - for (uint8_t i = 1; i < 4; i++) if (i * 60 < frame.w) dwinDrawVLine(COLOR_LINE, i * 60 + frame.x, frame.y, frame.h); - DWINUI::drawBox(0, COLOR_WHITE, DWINUI::extendFrame(frame, 1)); - dwinDrawHLine(COLOR_RED, frame.x, r, frame.w); -} + void Plot::draw(const frame_rect_t &frame, const_celsius_float_t max, const_float_t ref/*=0*/) { + graphframe = frame; + graphpoints = 0; + scale = frame.h / max; + x2 = frame.x + frame.w - 1; + y2 = frame.y + frame.h - 1; + r = round((y2) - ref * scale); + DWINUI::drawBox(1, Plot_Bg_Color, frame); + for (uint8_t i = 1; i < 4; i++) if (i * 60 < frame.w) dwinDrawVLine(COLOR_LINE, i * 60 + frame.x, frame.y, frame.h); + DWINUI::drawBox(0, COLOR_WHITE, DWINUI::extendFrame(frame, 1)); + dwinDrawHLine(COLOR_RED, frame.x, r, frame.w); + } -void Plot::update(const_float_t value) { - if (!scale) return; - const uint16_t y = round((y2) - value * scale); - if (graphpoints < graphframe.w) { - dwinDrawPoint(COLOR_YELLOW, 1, 1, graphpoints + graphframe.x, y); - } - else { - dwinFrameAreaMove(1, 0, 1, Plot_Bg_Color, graphframe.x, graphframe.y, x2, y2); - if ((graphpoints % 60) == 0) dwinDrawVLine(COLOR_LINE, x2 - 1, graphframe.y + 1, graphframe.h - 2); - dwinDrawPoint(COLOR_RED, 1, 1, x2 - 1, r); - dwinDrawPoint(COLOR_YELLOW, 1, 1, x2 - 1, y); - } - graphpoints++; - #if LCD_BACKLIGHT_TIMEOUT_MINS - ui.refresh_backlight_timeout(); - #endif -} + void Plot::update(const_float_t value) { + if (!scale) return; + const uint16_t y = round((y2) - value * scale); + if (graphpoints < graphframe.w) { + dwinDrawPoint(COLOR_YELLOW, 1, 1, graphpoints + graphframe.x, y); + } + else { + dwinFrameAreaMove(1, 0, 1, Plot_Bg_Color, graphframe.x, graphframe.y, x2, y2); + if ((graphpoints % 60) == 0) dwinDrawVLine(COLOR_LINE, x2 - 1, graphframe.y + 1, graphframe.h - 2); + dwinDrawPoint(COLOR_RED, 1, 1, x2 - 1, r); + dwinDrawPoint(COLOR_YELLOW, 1, 1, x2 - 1, y); + } + graphpoints++; + #if LCD_BACKLIGHT_TIMEOUT_MINS + ui.refresh_backlight_timeout(); + #endif + } -#endif // PROUI_TUNING_GRAPH + #endif // PROUI_TUNING_GRAPH #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/printstats.cpp b/Marlin/src/lcd/e3v2/proui/printstats.cpp index 732e80542d16..399ae034dcc0 100644 --- a/Marlin/src/lcd/e3v2/proui/printstats.cpp +++ b/Marlin/src/lcd/e3v2/proui/printstats.cpp @@ -31,52 +31,52 @@ #if ALL(DWIN_LCD_PROUI, PRINTCOUNTER) -#include "printstats.h" + #include "printstats.h" -#include "../../../core/types.h" -#include "../../../MarlinCore.h" -#include "../../marlinui.h" -#include "../../../module/printcounter.h" -#include "dwin.h" -#include "dwin_popup.h" + #include "../../../core/types.h" + #include "../../../MarlinCore.h" + #include "../../marlinui.h" + #include "../../../module/printcounter.h" + #include "dwin.h" + #include "dwin_popup.h" -PrintStats printStats; + PrintStats printStats; -void PrintStats::draw() { - char str[30] = ""; - constexpr int8_t MRG = 30; + void PrintStats::draw() { + char str[30] = ""; + constexpr int8_t MRG = 30; - title.showCaption(GET_TEXT_F(MSG_INFO_STATS_MENU)); - DWINUI::clearMainArea(); - drawPopupBkgd(); - DWINUI::drawButton(BTN_Continue, 86, 250); - printStatistics ps = print_job_timer.getStats(); + title.showCaption(GET_TEXT_F(MSG_INFO_STATS_MENU)); + DWINUI::clearMainArea(); + drawPopupBkgd(); + DWINUI::drawButton(BTN_Continue, 86, 250); + printStatistics ps = print_job_timer.getStats(); - DWINUI::drawString(MRG, 80, TS(GET_TEXT_F(MSG_INFO_PRINT_COUNT), F(": "), ps.totalPrints)); - DWINUI::drawString(MRG, 100, TS(GET_TEXT_F(MSG_INFO_COMPLETED_PRINTS), F(": "), ps.finishedPrints)); - duration_t(print_job_timer.getStats().printTime).toDigital(str, true); - DWINUI::drawString(MRG, 120, MString<50>(GET_TEXT_F(MSG_INFO_PRINT_TIME), F(": "), str)); - duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true); - DWINUI::drawString(MRG, 140, MString<50>(GET_TEXT(MSG_INFO_PRINT_LONGEST), F(": "), str)); - DWINUI::drawString(MRG, 160, TS(GET_TEXT_F(MSG_INFO_PRINT_FILAMENT), F(": "), p_float_t(ps.filamentUsed / 1000, 2), F(" m"))); -} + DWINUI::drawString(MRG, 80, TS(GET_TEXT_F(MSG_INFO_PRINT_COUNT), F(": "), ps.totalPrints)); + DWINUI::drawString(MRG, 100, TS(GET_TEXT_F(MSG_INFO_COMPLETED_PRINTS), F(": "), ps.finishedPrints)); + duration_t(print_job_timer.getStats().printTime).toDigital(str, true); + DWINUI::drawString(MRG, 120, MString<50>(GET_TEXT_F(MSG_INFO_PRINT_TIME), F(": "), str)); + duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true); + DWINUI::drawString(MRG, 140, MString<50>(GET_TEXT(MSG_INFO_PRINT_LONGEST), F(": "), str)); + DWINUI::drawString(MRG, 160, TS(GET_TEXT_F(MSG_INFO_PRINT_FILAMENT), F(": "), p_float_t(ps.filamentUsed / 1000, 2), F(" m"))); + } -void PrintStats::reset() { - print_job_timer.initStats(); - DONE_BUZZ(true); -} + void PrintStats::reset() { + print_job_timer.initStats(); + DONE_BUZZ(true); + } -void gotoPrintStats() { - printStats.draw(); - hmiSaveProcessID(ID_WaitResponse); -} + void gotoPrintStats() { + printStats.draw(); + hmiSaveProcessID(ID_WaitResponse); + } -// Print Stats Reset popup -void popupResetStats() { dwinPopupConfirmCancel(ICON_Info_0, GET_TEXT_F(MSG_RESET_STATS)); } -void onClickResetStats() { - if (hmiFlag.select_flag) printStats.reset(); - hmiReturnScreen(); -} -void printStatsReset() { gotoPopup(popupResetStats, onClickResetStats); } + // Print Stats Reset popup + void popupResetStats() { dwinPopupConfirmCancel(ICON_Info_0, GET_TEXT_F(MSG_RESET_STATS)); } + void onClickResetStats() { + if (hmiFlag.select_flag) printStats.reset(); + hmiReturnScreen(); + } + void printStatsReset() { gotoPopup(popupResetStats, onClickResetStats); } #endif // DWIN_LCD_PROUI && PRINTCOUNTER From 10bea426a356d00aa5a5f6ffe05da2351ea0e887 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 01:15:43 -0500 Subject: [PATCH 13/20] add brief and param to Menu Line Spacing --- Marlin/src/lcd/e3v2/proui/dwinui.h | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwinui.h b/Marlin/src/lcd/e3v2/proui/dwinui.h index 35f07404ff87..816b2259ee72 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.h +++ b/Marlin/src/lcd/e3v2/proui/dwinui.h @@ -195,14 +195,28 @@ #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 +/** + * @brief Menu Line Spacing + * + * @param TITLE_HEIGHT Title bar height + * @param MLINE Menu line height + * @param TROWS Total rows + * @param MROWS Other-than-Back + * @param ICOX Menu item icon X position + * @param LBLX Menu item label X position + * @param VALX Menu item value X position + * @param MENU_CHR_W/MENU_CHR_H Menu font 8x16 + * @param STAT_CHR_W Menu Stats character width + * + */ +constexpr uint8_t TITLE_HEIGHT = 30, + MLINE = 53, + TROWS = (STATUS_Y - TITLE_HEIGHT) / MLINE, + MROWS = TROWS - 1, + ICOX = 26, + LBLX = 55, + VALX = 210, + MENU_CHR_W = 8, MENU_CHR_H = 16, STAT_CHR_W = 10; // Menuitem Y position From ea9c430fc3a290d53c11ca6c2cd26246957fb470 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 01:17:03 -0500 Subject: [PATCH 14/20] update dwin_defines.h remove PROUI_PID_TUNE from Conditionals_post.h --- Marlin/src/inc/Conditionals_post.h | 3 --- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 10 +++++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index b98ca4d371f8..43272f25c7ea 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -2491,9 +2491,6 @@ // PID heating #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) #define HAS_PID_HEATING 1 - #if ENABLED(DWIN_LCD_PROUI) && ANY(PIDTEMP, PIDTEMPBED) - #define PROUI_PID_TUNE 1 - #endif #endif // Thermal protection diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index 30df9ff8c076..941fa25baf00 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -44,6 +44,10 @@ #define HAS_ZOFFSET_ITEM 1 #endif +#if ENABLED(DWIN_LCD_PROUI) && ANY(PIDTEMP, PIDTEMPBED) + #define PROUI_PID_TUNE 1 +#endif + #define defColorBackground RGB( 1, 12, 8) #define defColorCursor RGB(20, 49, 31) #define defColorTitleBg RGB( 0, 23, 16) @@ -82,7 +86,7 @@ * ProUI internal feature flags */ #if ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE) - #define PROUI_MEDIASORT + #define PROUI_MEDIASORT // Enable option to sort G-code files #endif #if ENABLED(POWER_LOSS_RECOVERY) #define PROUI_ITEM_PLR // Tune > Power-loss Recovery @@ -96,10 +100,10 @@ #if HAS_MESH #define PROUI_MESH_EDIT // Add a menu to edit mesh points #endif -#if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) && DISABLED(DISABLE_TUNING_GRAPH) +#if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) #define PROUI_TUNING_GRAPH 1 #endif -#define HAS_GCODE_PREVIEW 1 +#define HAS_GCODE_PREVIEW 1 // Preview G-code model thumbnail #define HAS_CUSTOM_COLORS 1 // Change display colors #define HAS_ESDIAG 1 // View End-stop/Runout switch continuity #define HAS_LOCKSCREEN 1 // Simple lockscreen From e109c3cd53a5d6c871cc9ec5282f9bacd0bb4f20 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 21 Nov 2023 00:34:15 -0600 Subject: [PATCH 15/20] undo extraneous changes --- Marlin/src/inc/Conditionals_post.h | 3 + Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp | 398 +++---- Marlin/src/lcd/e3v2/proui/dwin.cpp | 12 +- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 8 +- Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp | 286 ++--- Marlin/src/lcd/e3v2/proui/dwin_popup.cpp | 100 +- Marlin/src/lcd/e3v2/proui/dwinui.cpp | 660 ++++++------ Marlin/src/lcd/e3v2/proui/dwinui.h | 29 +- Marlin/src/lcd/e3v2/proui/endstop_diag.cpp | 98 +- Marlin/src/lcd/e3v2/proui/gcode_preview.cpp | 390 +++---- Marlin/src/lcd/e3v2/proui/lockscreen.cpp | 72 +- Marlin/src/lcd/e3v2/proui/menus.cpp | 1020 +++++++++--------- Marlin/src/lcd/e3v2/proui/meshviewer.cpp | 206 ++-- Marlin/src/lcd/e3v2/proui/plot.cpp | 80 +- Marlin/src/lcd/e3v2/proui/printstats.cpp | 78 +- 15 files changed, 1715 insertions(+), 1725 deletions(-) diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 43272f25c7ea..b98ca4d371f8 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -2491,6 +2491,9 @@ // PID heating #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) #define HAS_PID_HEATING 1 + #if ENABLED(DWIN_LCD_PROUI) && ANY(PIDTEMP, PIDTEMPBED) + #define PROUI_PID_TUNE 1 + #endif #endif // Thermal protection diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp index d54a458c6d25..a9ee754387a9 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -48,234 +48,234 @@ #if ALL(DWIN_LCD_PROUI, HAS_LEVELING) - #include "../../marlinui.h" - #include "../../../core/types.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" - - #include "dwin.h" - #include "dwinui.h" - #include "dwin_popup.h" - #include "bedlevel_tools.h" - - BedLevelTools bedLevelTools; - - #if ENABLED(USE_GRID_MESHVIEWER) - bool BedLevelTools::viewer_print_value = false; - #endif - bool BedLevelTools::goto_mesh_value = false; - uint8_t BedLevelTools::mesh_x = 0; - uint8_t BedLevelTools::mesh_y = 0; - uint8_t BedLevelTools::tilt_grid = 1; - - bool drawing_mesh = false; - - #if ENABLED(AUTO_BED_LEVELING_UBL) - - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { - MString cmd; - cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); - if (undefined) cmd += F(" N"); - gcode.process_subcommands_now(cmd); - planner.synchronize(); - } - - bool BedLevelTools::createPlaneFromMesh() { - 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]); - } - } +#include "../../marlinui.h" +#include "../../../core/types.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" + +#include "dwin.h" +#include "dwinui.h" +#include "dwin_popup.h" +#include "bedlevel_tools.h" + +BedLevelTools bedLevelTools; + +#if ENABLED(USE_GRID_MESHVIEWER) + bool BedLevelTools::viewer_print_value = false; +#endif +bool BedLevelTools::goto_mesh_value = false; +uint8_t BedLevelTools::mesh_x = 0; +uint8_t BedLevelTools::mesh_y = 0; +uint8_t BedLevelTools::tilt_grid = 1; + +bool drawing_mesh = false; + +#if ENABLED(AUTO_BED_LEVELING_UBL) + + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { + MString cmd; + cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); + if (undefined) cmd += F(" N"); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } - if (finish_incremental_LSF(&lsf_results)) { - SERIAL_ECHOPGM("Could not complete LSF!"); - return true; + bool BedLevelTools::createPlaneFromMesh() { + 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]); } + } - 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_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + if (finish_incremental_LSF(&lsf_results)) { + SERIAL_ECHOPGM("Could not complete LSF!"); + return true; + } - rotation.apply_rotation_xyz(mx, my, mz); + bedlevel.set_all_mesh_points_to_value(0); - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + 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]; - bedlevel.z_values[i][j] = mz - lsf_results.D; + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); } - return false; - } - #else + rotation.apply_rotation_xyz(mx, my, mz); - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { - gcode.process_subcommands_now( - TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) - ); - planner.synchronize(); - } - - #endif + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } - void BedLevelTools::manualMove(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 { - dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); - hmiSaveProcessID(ID_NothingToDo); - gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); - gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); - 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(); - hmiReturnScreen(); + bedlevel.z_values[i][j] = mz - lsf_results.D; } + return false; } - // Move / Probe methods. As examples, not yet used. - void BedLevelTools::moveToXYZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, false); - } - void BedLevelTools::moveToXY() { - goto_mesh_value = false; - manualMove(mesh_x, mesh_y, false); - } - void BedLevelTools::moveToZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, true); - } - void BedLevelTools::probeXY() { +#else + + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { gcode.process_subcommands_now( - MString( - F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), - F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), - F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) - ) + TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) ); + planner.synchronize(); } - void BedLevelTools::meshReset() { - ZERO(bedlevel.z_values); - TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); - } +#endif - // Accessors - float BedLevelTools::getMaxValue() { - float max = -(__FLT_MAX__); - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } - return max; +void BedLevelTools::manualMove(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(); } - - float BedLevelTools::getMinValue() { - float min = __FLT_MAX__; - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } - return min; + else { + dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); + hmiSaveProcessID(ID_NothingToDo); + gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); + gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); + 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(); + hmiReturnScreen(); } - - // Return 'true' if mesh is good and within LCD limits - bool BedLevelTools::meshValidate() { - GRID_LOOP(x, y) { - const float v = bedlevel.z_values[x][y]; - if (isnan(v) || !WITHIN(v, UBL_Z_OFFSET_MIN, UBL_Z_OFFSET_MAX)) return false; - } - return true; +} + +// Move / Probe methods. As examples, not yet used. +void BedLevelTools::moveToXYZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, false); +} +void BedLevelTools::moveToXY() { + goto_mesh_value = false; + manualMove(mesh_x, mesh_y, false); +} +void BedLevelTools::moveToZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, true); +} +void BedLevelTools::probeXY() { + gcode.process_subcommands_now( + MString( + F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), + F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), + F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) + ) + ); +} + +void BedLevelTools::meshReset() { + ZERO(bedlevel.z_values); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); +} + +// Accessors +float BedLevelTools::getMaxValue() { + float max = -(__FLT_MAX__); + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } + return max; +} + +float BedLevelTools::getMinValue() { + float min = __FLT_MAX__; + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } + return min; +} + +// Return 'true' if mesh is good and within LCD limits +bool BedLevelTools::meshValidate() { + GRID_LOOP(x, y) { + const float v = bedlevel.z_values[x][y]; + if (isnan(v) || !WITHIN(v, UBL_Z_OFFSET_MIN, UBL_Z_OFFSET_MAX)) return false; } + return true; +} + +#if ENABLED(USE_GRID_MESHVIEWER) + + constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); + + void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); + + // Clear background from previous selection and select new square + dwinDrawRectangle(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; + dwinDrawRectangle(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); + } - #if ENABLED(USE_GRID_MESHVIEWER) - - constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - - void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); - - // Clear background from previous selection and select new square - dwinDrawRectangle(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; - dwinDrawRectangle(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 + 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; + dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative + (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 + ); - // Draw value square grid - 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; - dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative - (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 + const uint8_t fs = DWINUI::fontWidth(meshfont); + if (viewer_print_value) { + xy_long_t offset { 0, cell_height_px / 2 - fs }; + if (isnan(bedlevel.z_values[x][y])) { // undefined + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); + } + else { // has value + MString<12> msg; + if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) + msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); + else + msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); + offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; + if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); + } safe_delay(10); LCD_SERIAL.flushTX(); - - // Draw value text on - const uint8_t fs = DWINUI::fontWidth(meshfont); - if (viewer_print_value) { - xy_long_t offset { 0, cell_height_px / 2 - fs }; - if (isnan(bedlevel.z_values[x][y])) { // undefined - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); - } - else { // has value - MString<12> msg; - if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) - msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); - else - msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); - offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; - if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); - } - safe_delay(10); - LCD_SERIAL.flushTX(); - } } } + } - void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead - float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); - if (rmax > 3e+10f) rmax = 0.0000001; - if (rmin > 3e+10f) rmin = 0.0000001; - ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); - drawing_mesh = false; - } + void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead + float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); + if (rmax > 3e+10f) rmax = 0.0000001; + if (rmin > 3e+10f) rmin = 0.0000001; + ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); + drawing_mesh = false; + } - #endif // USE_GRID_MESHVIEWER +#endif // USE_GRID_MESHVIEWER #endif // DWIN_LCD_PROUI && HAS_LEVELING diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 6c18af9248fd..8e2b173eafc1 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -72,7 +72,7 @@ #define HAS_ONESTEP_LEVELING 1 #endif -#if HAS_MESH || ALL(HAS_LEVELING, HAS_ZOFFSET_ITEM) +#if HAS_MESH || (HAS_LEVELING && HAS_ZOFFSET_ITEM) #include "../../../feature/bedlevel/bedlevel.h" #include "bedlevel_tools.h" #endif @@ -164,7 +164,7 @@ #define DWIN_VAR_UPDATE_INTERVAL 500 #define DWIN_UPDATE_INTERVAL 1000 -#if ALL(HAS_MESH, HAS_BED_PROBE) +#if HAS_MESH && HAS_BED_PROBE #define BABY_Z_VAR probe.offset.z #else float z_offset = 0; @@ -443,7 +443,7 @@ void popupPauseOrStop() { #endif -#if ANY(HAS_HOTEND, HAS_HEATED_BED) +#if HAS_HOTEND || HAS_HEATED_BED void dwinPopupTemperature(const bool toohigh) { hmiSaveProcessID(ID_WaitResponse); if (hmiIsChinese()) { @@ -2390,7 +2390,7 @@ void setFlow() { setPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW, []{ planner.refr #endif - #if ALL(HAS_BED_PROBE, HAS_MESH) + #if HAS_BED_PROBE && HAS_MESH void trammingwizard() { if (hmiData.fullManualTramming) { @@ -3026,10 +3026,10 @@ void drawPrepareMenu() { checkkey = ID_Menu; if (SET_MENU(trammingMenu, MSG_BED_TRAMMING, 8)) { BACK_ITEM(drawPrepareMenu); - #if ALL(HAS_BED_PROBE, HAS_MESH) + #if HAS_BED_PROBE && HAS_MESH MENU_ITEM(ICON_ProbeSet, MSG_TRAMMING_WIZARD, onDrawMenuItem, trammingwizard); EDIT_ITEM(ICON_ProbeSet, MSG_BED_TRAMMING_MANUAL, onDrawChkbMenu, setManualTramming, &hmiData.fullManualTramming); - #elif ALL(!HAS_BED_PROBE, HAS_ZOFFSET_ITEM) + #elif !HAS_BED_PROBE && HAS_ZOFFSET_ITEM MENU_ITEM_F(ICON_MoveZ0, "Home Z and disable", onDrawMenuItem, homeZAndDisable); #endif MENU_ITEM(ICON_Axis, MSG_TRAM_FL, onDrawMenuItem, []{ (void)tram(0); }); diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index 941fa25baf00..8bf23725c94d 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -28,6 +28,8 @@ * Date: 2022/08/08 */ +#include "../../../inc/MarlinConfigPre.h" + #if defined(__STM32F1__) || defined(STM32F1) #define DASH_REDRAW 1 #endif @@ -44,10 +46,6 @@ #define HAS_ZOFFSET_ITEM 1 #endif -#if ENABLED(DWIN_LCD_PROUI) && ANY(PIDTEMP, PIDTEMPBED) - #define PROUI_PID_TUNE 1 -#endif - #define defColorBackground RGB( 1, 12, 8) #define defColorCursor RGB(20, 49, 31) #define defColorTitleBg RGB( 0, 23, 16) @@ -100,7 +98,7 @@ #if HAS_MESH #define PROUI_MESH_EDIT // Add a menu to edit mesh points #endif -#if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) +#if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) && DISABLED(DISABLE_TUNING_GRAPH) #define PROUI_TUNING_GRAPH 1 #endif #define HAS_GCODE_PREVIEW 1 // Preview G-code model thumbnail diff --git a/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp b/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp index 497c86e81634..853da8532e12 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp @@ -31,150 +31,150 @@ #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 dwinDrawQR(uint8_t QR_Pixel, uint16_t x, uint16_t y, char *string) { - size_t i = 0; - dwinByte(i, 0x21); - dwinWord(i, x); - dwinWord(i, y); - dwinByte(i, QR_Pixel); - dwinText(i, string); - dwinSend(i); - } - - // Draw an Icon with transparent background - // libID: Icon library ID - // picID: Icon ID - // x/y: Upper-left point - void dwinIconShow(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { - dwinIconShow(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 dwinFrameAreaCopy(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { - size_t i = 0; - dwinByte(i, 0x26); - dwinWord(i, xStart); - dwinWord(i, yStart); - dwinWord(i, xEnd); - dwinWord(i, yEnd); - dwinWord(i, x); - dwinWord(i, y); - dwinSend(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 dwinFrameAreaCopy(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; - dwinByte(i, 0x27); - dwinByte(i, (IBD & 1) << 7 | (BIR & 1) << 6 | (BFI & 1) << 5 | cacheID); - dwinWord(i, xStart); - dwinWord(i, yStart); - dwinWord(i, xEnd); - dwinWord(i, yEnd); - dwinWord(i, x); - dwinWord(i, y); - dwinSend(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 dwinFrameAreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { - dwinFrameAreaCopy(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 dwinWriteToMem(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; - dwinByte(i, 0x31); - dwinByte(i, mem); - dwinWord(i, addr + indx); // start address of the data block - ++i; - for (uint8_t j = 0; j < i; ++j) { LCD_SERIAL.write(dwinSendBuf[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 - for (uint8_t j = 0; j < 4; ++j) { LCD_SERIAL.write(dwinBufTail[j]); delayMicroseconds(1); } - block++; - pending -= to_send; - } - } - - // Draw an Icon from SRAM without background transparency for DACAI Screens support - void DACAI_ICON_Show(uint16_t x, uint16_t y, uint16_t addr) { - NOMORE(x, DWIN_WIDTH - 1); - NOMORE(y, DWIN_HEIGHT - 1); +#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 dwinDrawQR(uint8_t QR_Pixel, uint16_t x, uint16_t y, char *string) { + size_t i = 0; + dwinByte(i, 0x21); + dwinWord(i, x); + dwinWord(i, y); + dwinByte(i, QR_Pixel); + dwinText(i, string); + dwinSend(i); +} + +// Draw an Icon with transparent background +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void dwinIconShow(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) { + dwinIconShow(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 dwinFrameAreaCopy(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + size_t i = 0; + dwinByte(i, 0x26); + dwinWord(i, xStart); + dwinWord(i, yStart); + dwinWord(i, xEnd); + dwinWord(i, yEnd); + dwinWord(i, x); + dwinWord(i, y); + dwinSend(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 dwinFrameAreaCopy(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; + dwinByte(i, 0x27); + dwinByte(i, (IBD & 1) << 7 | (BIR & 1) << 6 | (BFI & 1) << 5 | cacheID); + dwinWord(i, xStart); + dwinWord(i, yStart); + dwinWord(i, xEnd); + dwinWord(i, yEnd); + dwinWord(i, x); + dwinWord(i, y); + dwinSend(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 dwinFrameAreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) { + dwinFrameAreaCopy(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 dwinWriteToMem(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; - dwinByte(i, 0x70); - dwinWord(i, x); - dwinWord(i, y); - dwinWord(i, addr); - dwinSend(i); + dwinByte(i, 0x31); + dwinByte(i, mem); + dwinWord(i, addr + indx); // start address of the data block + ++i; + for (uint8_t j = 0; j < i; ++j) { LCD_SERIAL.write(dwinSendBuf[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 + for (uint8_t j = 0; j < 4; ++j) { LCD_SERIAL.write(dwinBufTail[j]); delayMicroseconds(1); } + block++; + pending -= to_send; } - - void dwinIconShow(uint16_t x, uint16_t y, uint16_t addr) { - #if ENABLED(DACAI_DISPLAY) - DACAI_ICON_Show(x, y, addr); - #else - dwinIconShow(0, 0, 1, x, y, addr); - #endif - } - - // 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 dwinSRAMToPic(uint8_t picID) { - size_t i = 0; - dwinByte(i, 0x33); - dwinByte(i, 0x5A); - dwinByte(i, 0xA5); - dwinByte(i, picID); - dwinSend(i); - } - - //--------------------------Test area ------------------------- - - //void dwinReadSRAM(uint16_t addr, const uint8_t length, const char * const data) { - // size_t i = 0; - // dwinByte(i, 0x32); - // dwinByte(i, 0x5A); // 0x5A Read from SRAM - 0xA5 Read from Flash - // dwinWord(i, addr); // 0x0000 to 0x7FFF - // const size_t len = _MIN(0xF0, length); - // dwinByte(i, len); - // dwinSend(i); - //} +} + +// Draw an Icon from SRAM without background transparency for DACAI Screens support +void DACAI_ICON_Show(uint16_t x, uint16_t y, uint16_t addr) { + NOMORE(x, DWIN_WIDTH - 1); + NOMORE(y, DWIN_HEIGHT - 1); + size_t i = 0; + dwinByte(i, 0x70); + dwinWord(i, x); + dwinWord(i, y); + dwinWord(i, addr); + dwinSend(i); +} + +void dwinIconShow(uint16_t x, uint16_t y, uint16_t addr) { + #if ENABLED(DACAI_DISPLAY) + DACAI_ICON_Show(x, y, addr); + #else + dwinIconShow(0, 0, 1, x, y, addr); + #endif +} + +// 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 dwinSRAMToPic(uint8_t picID) { + size_t i = 0; + dwinByte(i, 0x33); + dwinByte(i, 0x5A); + dwinByte(i, 0xA5); + dwinByte(i, picID); + dwinSend(i); +} + +//--------------------------Test area ------------------------- + +//void dwinReadSRAM(uint16_t addr, const uint8_t length, const char * const data) { +// size_t i = 0; +// dwinByte(i, 0x32); +// dwinByte(i, 0x5A); // 0x5A Read from SRAM - 0xA5 Read from Flash +// dwinWord(i, addr); // 0x0000 to 0x7FFF +// const size_t len = _MIN(0xF0, length); +// dwinByte(i, len); +// dwinSend(i); +//} #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp index 71ef7844f7b0..91c3ee98e390 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp @@ -31,65 +31,65 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "dwin.h" - #include "dwinui.h" - #include "dwin_popup.h" +#include "dwin.h" +#include "dwinui.h" +#include "dwin_popup.h" - #include "../../../MarlinCore.h" // for wait_for_user +#include "../../../MarlinCore.h" // for wait_for_user - popupDrawFunc_t popupDraw = nullptr; - popupClickFunc_t popupClick = nullptr; - popupChangeFunc_t popupChange = nullptr; +popupDrawFunc_t popupDraw = nullptr; +popupClickFunc_t popupClick = nullptr; +popupChangeFunc_t popupChange = nullptr; - uint16_t HighlightYPos = 280; +uint16_t HighlightYPos = 280; - void drawSelectHighlight(const bool sel, const uint16_t ypos) { - HighlightYPos = ypos; - hmiFlag.select_flag = sel; - const uint16_t c1 = sel ? hmiData.colorHighlight : hmiData.colorPopupBg, - c2 = sel ? hmiData.colorPopupBg : hmiData.colorHighlight; - dwinDrawRectangle(0, c1, 25, ypos - 1, 126, ypos + 38); - dwinDrawRectangle(0, c1, 24, ypos - 2, 127, ypos + 39); - dwinDrawRectangle(0, c2, 145, ypos - 1, 246, ypos + 38); - dwinDrawRectangle(0, c2, 144, ypos - 2, 247, ypos + 39); - } +void drawSelectHighlight(const bool sel, const uint16_t ypos) { + HighlightYPos = ypos; + hmiFlag.select_flag = sel; + const uint16_t c1 = sel ? hmiData.colorHighlight : hmiData.colorPopupBg, + c2 = sel ? hmiData.colorPopupBg : hmiData.colorHighlight; + dwinDrawRectangle(0, c1, 25, ypos - 1, 126, ypos + 38); + dwinDrawRectangle(0, c1, 24, ypos - 2, 127, ypos + 39); + dwinDrawRectangle(0, c2, 145, ypos - 1, 246, ypos + 38); + dwinDrawRectangle(0, c2, 144, ypos - 2, 247, ypos + 39); +} - void dwinPopupContinue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) { - hmiSaveProcessID(ID_WaitResponse); - dwinDrawPopup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue - dwinUpdateLCD(); - } +void dwinPopupContinue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) { + hmiSaveProcessID(ID_WaitResponse); + dwinDrawPopup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue + dwinUpdateLCD(); +} - void dwinPopupConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) { - dwinDrawPopup(ICON_BLTouch, F("Please confirm"), fmsg2); - DWINUI::drawButton(BTN_Confirm, 26, 280); - DWINUI::drawButton(BTN_Cancel, 146, 280); - drawSelectHighlight(hmiFlag.select_flag); - dwinUpdateLCD(); - } +void dwinPopupConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) { + dwinDrawPopup(ICON_BLTouch, F("Please confirm"), fmsg2); + DWINUI::drawButton(BTN_Confirm, 26, 280); + DWINUI::drawButton(BTN_Cancel, 146, 280); + drawSelectHighlight(hmiFlag.select_flag); + dwinUpdateLCD(); +} - void gotoPopup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) { - popupDraw = fnDraw; - popupClick = fnClick; - popupChange = fnChange; - hmiSaveProcessID(ID_Popup); - hmiFlag.select_flag = false; - popupDraw(); - } +void gotoPopup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) { + popupDraw = fnDraw; + popupClick = fnClick; + popupChange = fnChange; + hmiSaveProcessID(ID_Popup); + hmiFlag.select_flag = false; + popupDraw(); +} - void hmiPopup() { - 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 drawSelectHighlight(change, HighlightYPos); - dwinUpdateLCD(); - } +void hmiPopup() { + 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 drawSelectHighlight(change, HighlightYPos); + dwinUpdateLCD(); } } +} #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwinui.cpp b/Marlin/src/lcd/e3v2/proui/dwinui.cpp index df02508e4781..7e94fc3e5633 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwinui.cpp @@ -31,335 +31,335 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "dwin_defines.h" - #include "dwinui.h" - - xy_int_t DWINUI::cursor = { 0 }; - uint16_t DWINUI::penColor = COLOR_WHITE; - uint16_t DWINUI::textColor = defColorText; - uint16_t DWINUI::backColor = defColorBackground; - uint16_t DWINUI::buttonColor = defColorButton; - uint8_t DWINUI::fontID = font8x16; - FSTR_P const DWINUI::author = F(STRING_CONFIG_H_AUTHOR); - - void (*DWINUI::onTitleDraw)(Title* t) = nullptr; - - void DWINUI::init() { - cursor.reset(); - penColor = COLOR_WHITE; - textColor = defColorText; - backColor = defColorBackground; - buttonColor = defColorButton; - 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) { - #if DISABLED(TJC_DISPLAY) - case font6x12 : return 6; - case font20x40: return 20; - case font24x48: return 24; - case font28x56: return 28; - case font32x64: return 32; - #endif - case font8x16 : return 8; - case font10x20: return 10; - case font12x24: return 12; - case font14x28: return 14; - case font16x32: return 16; - default: return 0; - } - } - - // Get font character height - uint8_t DWINUI::fontHeight(fontid_t fid) { - switch (fid) { - #if DISABLED(TJC_DISPLAY) - case font6x12 : return 12; - case font20x40: return 40; - case font24x48: return 48; - case font28x56: return 56; - case font32x64: return 64; - #endif - case font8x16 : return 16; - case font10x20: return 20; - case font12x24: return 24; - case font14x28: return 28; - case font16x32: return 32; - 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::drawCenteredString(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; - dwinDrawString(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::drawChar(uint16_t color, uint16_t x, uint16_t y, const char c) { - const char string[2] = { c, 0}; - dwinDrawString(false, fontID, color, backColor, x, y, string, 1); - } - - // Draw a char at cursor position and increment cursor - void DWINUI::drawChar(uint16_t color, const char c) { - drawChar(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::drawString(const char * const string, uint16_t rlimit) { - dwinDrawString(false, fontID, textColor, backColor, cursor.x, cursor.y, string, rlimit); - moveBy(strlen(string) * fontWidth(fontID), 0); - } - void DWINUI::drawString(uint16_t color, const char * const string, uint16_t rlimit) { - dwinDrawString(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::drawInt(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); - dwinDrawString(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::drawFloat(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]; - dwinDrawString(bShow, fid, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr)); - } - - // ------------------------- Icons -------------------------------// - - // Draw an Icon and select library automatically - // BG: The icon background display: false=Background filtering is not displayed, true=Background display - // libID: Icon library ID - // picID: Icon ID - // x/y: Upper-left point - void DWINUI::ICON_Show(bool BG, uint8_t icon, uint16_t x, uint16_t y) { - const uint8_t libID = ICON TERN_(HAS_CUSTOMICONS, + (icon / 100)); - const uint8_t picID = icon TERN_(HAS_CUSTOMICONS, % 100); - dwinIconShow(BG, false, !BG, libID, picID, x, y); - } - - // ------------------------- Buttons ------------------------------// - - void DWINUI::drawButton(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) { - dwinDrawRectangle(1, bcolor, x1, y1, x2, y2); - drawCenteredString(0, fontID, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption); - } - - void DWINUI::drawButton(uint8_t id, uint16_t x, uint16_t y) { - switch (id) { - case BTN_Cancel : drawButton(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break; - case BTN_Confirm : drawButton(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break; - case BTN_Continue: drawButton(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break; - case BTN_Print : drawButton(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break; - case BTN_Save : drawButton(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break; - case BTN_Purge : drawButton(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::drawCircle(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--; - dwinDrawPoint(color, 1, 1, x + a, y + b); // Draw some sector 1 - dwinDrawPoint(color, 1, 1, x + b, y + a); // Draw some sector 2 - dwinDrawPoint(color, 1, 1, x + b, y - a); // Draw some sector 3 - dwinDrawPoint(color, 1, 1, x + a, y - b); // Draw some sector 4 - dwinDrawPoint(color, 1, 1, x - a, y - b); // Draw some sector 5 - dwinDrawPoint(color, 1, 1, x - b, y - a); // Draw some sector 6 - dwinDrawPoint(color, 1, 1, x - b, y + a); // Draw some sector 7 - dwinDrawPoint(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::drawFillCircle(uint16_t bcolor, uint16_t x, uint16_t y, uint8_t r) { - dwinDrawLine(bcolor, x - r, y, x + r, y); - uint16_t b = 1; - while (b <= r) { - uint16_t a = SQRT(sq(r) - sq(b)); - dwinDrawLine(bcolor, x - a, y + b, x + a, y + b); - dwinDrawLine(bcolor, x - a, y - b, x + a, y - b); - b += TERN(TJC_DISPLAY, 2, 1); - } - } - - // 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 + 1); - R = (1.0f - n) * GetRColor(color1) + n * GetRColor(color2); - G = (1.0f - n) * GetGColor(color1) + n * GetGColor(color2); - B = (1.0f - 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) { - const int16_t limv = _MAX(abs(minv), abs(maxv)); - float n = (minv >= 0) ? float(val - minv) / (maxv - minv + 1) : (float)val / limv; - LIMIT(n, -1, 1); - - constexpr uint8_t maxB = 28, maxR = 28, maxG = 38; - uint8_t R, G, B; - if (n <= -0.5f) { R = 0; G = maxG * (1.0f + n); B = maxB; } - else if (n <= 0.0f) { R = 0; G = maxG; B = maxB * (-n) * 2; } - else if (n < 0.5f) { R = maxR * n * 2; G = maxG; B = 0; } - else { R = maxR; G = maxG * (1.0f - 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::drawCheckbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked=false) { - dwinDrawRectangle(0, color, x + 2, y + 2, x + 17, y + 17); - dwinDrawRectangle(1, checked ? color : bcolor, x + 6, y + 6, x + 13, y + 13); - } - - // Clear Menu by filling the menu area with background color - void DWINUI::clearMainArea() { - dwinDrawRectangle(1, backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); - } - - /* Title Class ==============================================================*/ - - Title title; - - void Title::draw() { - if (DWINUI::onTitleDraw != nullptr) (*DWINUI::onTitleDraw)(this); - } - - void Title::setCaption(const char * const titleStr) { - frameid = 0; - if ( caption == titleStr ) return; - const uint8_t len = _MIN(sizeof(caption) - 1, strlen(titleStr)); - memcpy(&caption[0], titleStr, len); - caption[len] = '\0'; - } - - void Title::showCaption(const char * const titleStr) { - setCaption(titleStr); - draw(); - } - - void Title::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 Title::setFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - setFrame(1, x, y, x + w - 1, y + h - 1); - } - - void Title::frameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { - setFrame(id, x1, y1, x2, y2); - draw(); - } - - void Title::frameCopy(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - frameCopy(1, x, y, x + w - 1, y + h - 1); - } +#include "dwin_defines.h" +#include "dwinui.h" + +xy_int_t DWINUI::cursor = { 0 }; +uint16_t DWINUI::penColor = COLOR_WHITE; +uint16_t DWINUI::textColor = defColorText; +uint16_t DWINUI::backColor = defColorBackground; +uint16_t DWINUI::buttonColor = defColorButton; +uint8_t DWINUI::fontID = font8x16; +FSTR_P const DWINUI::author = F(STRING_CONFIG_H_AUTHOR); + +void (*DWINUI::onTitleDraw)(Title* t) = nullptr; + +void DWINUI::init() { + cursor.reset(); + penColor = COLOR_WHITE; + textColor = defColorText; + backColor = defColorBackground; + buttonColor = defColorButton; + 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) { + #if DISABLED(TJC_DISPLAY) + case font6x12 : return 6; + case font20x40: return 20; + case font24x48: return 24; + case font28x56: return 28; + case font32x64: return 32; + #endif + case font8x16 : return 8; + case font10x20: return 10; + case font12x24: return 12; + case font14x28: return 14; + case font16x32: return 16; + default: return 0; + } +} + +// Get font character height +uint8_t DWINUI::fontHeight(fontid_t fid) { + switch (fid) { + #if DISABLED(TJC_DISPLAY) + case font6x12 : return 12; + case font20x40: return 40; + case font24x48: return 48; + case font28x56: return 56; + case font32x64: return 64; + #endif + case font8x16 : return 16; + case font10x20: return 20; + case font12x24: return 24; + case font14x28: return 28; + case font16x32: return 32; + 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::drawCenteredString(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; + dwinDrawString(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::drawChar(uint16_t color, uint16_t x, uint16_t y, const char c) { + const char string[2] = { c, 0}; + dwinDrawString(false, fontID, color, backColor, x, y, string, 1); +} + +// Draw a char at cursor position and increment cursor +void DWINUI::drawChar(uint16_t color, const char c) { + drawChar(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::drawString(const char * const string, uint16_t rlimit) { + dwinDrawString(false, fontID, textColor, backColor, cursor.x, cursor.y, string, rlimit); + moveBy(strlen(string) * fontWidth(fontID), 0); +} +void DWINUI::drawString(uint16_t color, const char * const string, uint16_t rlimit) { + dwinDrawString(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::drawInt(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); + dwinDrawString(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::drawFloat(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]; + dwinDrawString(bShow, fid, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr)); +} + +// ------------------------- Icons -------------------------------// + +// Draw an Icon and select library automatically +// BG: The icon background display: false=Background filtering is not displayed, true=Background display +// libID: Icon library ID +// picID: Icon ID +// x/y: Upper-left point +void DWINUI::ICON_Show(bool BG, uint8_t icon, uint16_t x, uint16_t y) { + const uint8_t libID = ICON TERN_(HAS_CUSTOMICONS, + (icon / 100)); + const uint8_t picID = icon TERN_(HAS_CUSTOMICONS, % 100); + dwinIconShow(BG, false, !BG, libID, picID, x, y); +} + +// ------------------------- Buttons ------------------------------// + +void DWINUI::drawButton(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) { + dwinDrawRectangle(1, bcolor, x1, y1, x2, y2); + drawCenteredString(0, fontID, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption); +} + +void DWINUI::drawButton(uint8_t id, uint16_t x, uint16_t y) { + switch (id) { + case BTN_Cancel : drawButton(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break; + case BTN_Confirm : drawButton(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break; + case BTN_Continue: drawButton(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break; + case BTN_Print : drawButton(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break; + case BTN_Save : drawButton(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break; + case BTN_Purge : drawButton(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::drawCircle(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--; + dwinDrawPoint(color, 1, 1, x + a, y + b); // Draw some sector 1 + dwinDrawPoint(color, 1, 1, x + b, y + a); // Draw some sector 2 + dwinDrawPoint(color, 1, 1, x + b, y - a); // Draw some sector 3 + dwinDrawPoint(color, 1, 1, x + a, y - b); // Draw some sector 4 + dwinDrawPoint(color, 1, 1, x - a, y - b); // Draw some sector 5 + dwinDrawPoint(color, 1, 1, x - b, y - a); // Draw some sector 6 + dwinDrawPoint(color, 1, 1, x - b, y + a); // Draw some sector 7 + dwinDrawPoint(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::drawFillCircle(uint16_t bcolor, uint16_t x, uint16_t y, uint8_t r) { + dwinDrawLine(bcolor, x - r, y, x + r, y); + uint16_t b = 1; + while (b <= r) { + uint16_t a = SQRT(sq(r) - sq(b)); + dwinDrawLine(bcolor, x - a, y + b, x + a, y + b); + dwinDrawLine(bcolor, x - a, y - b, x + a, y - b); + b += TERN(TJC_DISPLAY, 2, 1); + } +} + +// 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 + 1); + R = (1.0f - n) * GetRColor(color1) + n * GetRColor(color2); + G = (1.0f - n) * GetGColor(color1) + n * GetGColor(color2); + B = (1.0f - 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) { + const int16_t limv = _MAX(abs(minv), abs(maxv)); + float n = (minv >= 0) ? float(val - minv) / (maxv - minv + 1) : (float)val / limv; + LIMIT(n, -1, 1); + + constexpr uint8_t maxB = 28, maxR = 28, maxG = 38; + uint8_t R, G, B; + if (n <= -0.5f) { R = 0; G = maxG * (1.0f + n); B = maxB; } + else if (n <= 0.0f) { R = 0; G = maxG; B = maxB * (-n) * 2; } + else if (n < 0.5f) { R = maxR * n * 2; G = maxG; B = 0; } + else { R = maxR; G = maxG * (1.0f - 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::drawCheckbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked=false) { + dwinDrawRectangle(0, color, x + 2, y + 2, x + 17, y + 17); + dwinDrawRectangle(1, checked ? color : bcolor, x + 6, y + 6, x + 13, y + 13); +} + +// Clear Menu by filling the menu area with background color +void DWINUI::clearMainArea() { + dwinDrawRectangle(1, backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); +} + +/* Title Class ==============================================================*/ + +Title title; + +void Title::draw() { + if (DWINUI::onTitleDraw != nullptr) (*DWINUI::onTitleDraw)(this); +} + +void Title::setCaption(const char * const titleStr) { + frameid = 0; + if ( caption == titleStr ) return; + const uint8_t len = _MIN(sizeof(caption) - 1, strlen(titleStr)); + memcpy(&caption[0], titleStr, len); + caption[len] = '\0'; +} + +void Title::showCaption(const char * const titleStr) { + setCaption(titleStr); + draw(); +} + +void Title::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 Title::setFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + setFrame(1, x, y, x + w - 1, y + h - 1); +} + +void Title::frameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + setFrame(id, x1, y1, x2, y2); + draw(); +} + +void Title::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/Marlin/src/lcd/e3v2/proui/dwinui.h b/Marlin/src/lcd/e3v2/proui/dwinui.h index 816b2259ee72..015e66c8cb71 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.h +++ b/Marlin/src/lcd/e3v2/proui/dwinui.h @@ -197,27 +197,16 @@ /** * @brief Menu Line Spacing - * - * @param TITLE_HEIGHT Title bar height - * @param MLINE Menu line height - * @param TROWS Total rows - * @param MROWS Other-than-Back - * @param ICOX Menu item icon X position - * @param LBLX Menu item label X position - * @param VALX Menu item value X position - * @param MENU_CHR_W/MENU_CHR_H Menu font 8x16 - * @param STAT_CHR_W Menu Stats character width - * */ -constexpr uint8_t TITLE_HEIGHT = 30, - MLINE = 53, - TROWS = (STATUS_Y - TITLE_HEIGHT) / MLINE, - MROWS = TROWS - 1, - ICOX = 26, - LBLX = 55, - VALX = 210, - MENU_CHR_W = 8, MENU_CHR_H = 16, - STAT_CHR_W = 10; +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; //< Menu Stats character width // Menuitem Y position #define MYPOS(L) (TITLE_HEIGHT + MLINE * (L)) diff --git a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp index 902038630647..21c83dc8faa0 100644 --- a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp +++ b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp @@ -31,63 +31,63 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "dwin_defines.h" +#include "dwin_defines.h" - #if HAS_ESDIAG +#if HAS_ESDIAG - #include "endstop_diag.h" - #include "../../marlinui.h" - #include "dwin.h" - #include "dwin_popup.h" +#include "endstop_diag.h" +#include "../../marlinui.h" +#include "dwin.h" +#include "dwin_popup.h" - #if HAS_FILAMENT_SENSOR - #include "../../../feature/runout.h" - #endif +#if HAS_FILAMENT_SENSOR + #include "../../../feature/runout.h" +#endif - #if HAS_BED_PROBE - #include "../../../module/probe.h" - #endif +#if HAS_BED_PROBE + #include "../../../module/probe.h" +#endif - ESDiag esDiag; +ESDiag esDiag; - void draw_es_label(FSTR_P const flabel=nullptr) { - DWINUI::cursor.x = 40; - if (flabel) DWINUI::drawString(F(flabel)); - DWINUI::drawString(F(": ")); - DWINUI::moveBy(0, 25); - } +void draw_es_label(FSTR_P const flabel=nullptr) { + DWINUI::cursor.x = 40; + if (flabel) DWINUI::drawString(F(flabel)); + DWINUI::drawString(F(": ")); + DWINUI::moveBy(0, 25); +} - void draw_es_state(const bool is_hit) { - const uint8_t LM = 130; - DWINUI::cursor.x = LM; - dwinDrawRectangle(1, hmiData.colorPopupBg, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20); - is_hit ? DWINUI::drawString(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::drawString(RGB(16,63,16), F(STR_ENDSTOP_OPEN)); - DWINUI::moveBy(0, 25); - } +void draw_es_state(const bool is_hit) { + const uint8_t LM = 130; + DWINUI::cursor.x = LM; + dwinDrawRectangle(1, hmiData.colorPopupBg, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20); + is_hit ? DWINUI::drawString(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::drawString(RGB(16,63,16), F(STR_ENDSTOP_OPEN)); + DWINUI::moveBy(0, 25); +} - void ESDiag::draw() { - title.showCaption(GET_TEXT_F(MSG_ENDSTOP_TEST)); - DWINUI::clearMainArea(); - drawPopupBkgd(); - DWINUI::drawButton(BTN_Continue, 86, 250); - DWINUI::cursor.y = 80; - #define ES_LABEL(S) draw_es_label(F(STR_##S)) - TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX)); - TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX)); - TERN_(USE_Z_MIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX)); - TERN_(HAS_FILAMENT_SENSOR, draw_es_label(F(STR_FILAMENT))); - update(); - } +void ESDiag::draw() { + title.showCaption(GET_TEXT_F(MSG_ENDSTOP_TEST)); + DWINUI::clearMainArea(); + drawPopupBkgd(); + DWINUI::drawButton(BTN_Continue, 86, 250); + DWINUI::cursor.y = 80; + #define ES_LABEL(S) draw_es_label(F(STR_##S)) + TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX)); + TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX)); + TERN_(USE_Z_MIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX)); + TERN_(HAS_FILAMENT_SENSOR, draw_es_label(F(STR_FILAMENT))); + update(); +} - void ESDiag::update() { - DWINUI::cursor.y = 80; - #define ES_REPORT(S) draw_es_state(READ(S##_PIN) == S##_ENDSTOP_HIT_STATE) - TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX)); - TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX)); - TERN_(USE_Z_MIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX)); - TERN_(HAS_FILAMENT_SENSOR, draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE)); - dwinUpdateLCD(); - } +void ESDiag::update() { + DWINUI::cursor.y = 80; + #define ES_REPORT(S) draw_es_state(READ(S##_PIN) == S##_ENDSTOP_HIT_STATE) + TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX)); + TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX)); + TERN_(USE_Z_MIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX)); + TERN_(HAS_FILAMENT_SENSOR, draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE)); + dwinUpdateLCD(); +} - #endif // HAS_ESDIAG +#endif // HAS_ESDIAG #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp b/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp index 12e3808d192b..045615f3c2ae 100644 --- a/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp +++ b/Marlin/src/lcd/e3v2/proui/gcode_preview.cpp @@ -31,203 +31,203 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "dwin_defines.h" - - #if HAS_GCODE_PREVIEW - - #include "gcode_preview.h" - - #include "../../marlinui.h" - #include "../../../sd/cardreader.h" - #include "../../../MarlinCore.h" // for wait_for_user - #include "dwin.h" - #include "dwin_popup.h" - #include "base64.h" - - #define THUMBWIDTH 230 - #define THUMBHEIGHT 180 - - Preview preview; - - typedef struct { - char name[13] = ""; // 8.3 + null - uint32_t thumbstart = 0; - int thumbsize = 0; - int thumbheight = 0, thumbwidth = 0; - float time = 0; - float filament = 0; - float layer = 0; - float width = 0, height = 0, length = 0; - - void setname(const char * const fn) { - const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); - memcpy(name, fn, len); - name[len] = '\0'; - } - - void clear() { - name[0] = '\0'; - thumbstart = 0; - thumbsize = 0; - thumbheight = thumbwidth = 0; - time = 0; - filament = 0; - layer = 0; - height = width = length = 0; - } - - } fileprop_t; - - fileprop_t fileprop; - - void getValue(const char * const buf, PGM_P const key, float &value) { - if (value != 0.0f) return; - - char *posptr = strstr_P(buf, key); - if (posptr == nullptr) return; - - char num[10] = ""; - for (uint8_t i = 0; i < sizeof(num);) { - const char c = *posptr; - if (ISEOL(c) || c == '\0') { - num[i] = '\0'; - value = atof(num); - break; - } - if (WITHIN(c, '0', '9') || c == '.') num[i++] = c; - posptr++; - } +#include "dwin_defines.h" + +#if HAS_GCODE_PREVIEW + +#include "gcode_preview.h" + +#include "../../marlinui.h" +#include "../../../sd/cardreader.h" +#include "../../../MarlinCore.h" // for wait_for_user +#include "dwin.h" +#include "dwin_popup.h" +#include "base64.h" + +#define THUMBWIDTH 230 +#define THUMBHEIGHT 180 + +Preview preview; + +typedef struct { + char name[13] = ""; // 8.3 + null + uint32_t thumbstart = 0; + int thumbsize = 0; + int thumbheight = 0, thumbwidth = 0; + float time = 0; + float filament = 0; + float layer = 0; + float width = 0, height = 0, length = 0; + + void setname(const char * const fn) { + const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); + memcpy(name, fn, len); + name[len] = '\0'; + } + + void clear() { + name[0] = '\0'; + thumbstart = 0; + thumbsize = 0; + thumbheight = thumbwidth = 0; + time = 0; + filament = 0; + layer = 0; + height = width = length = 0; + } + +} fileprop_t; + +fileprop_t fileprop; + +void getValue(const char * const buf, PGM_P const key, float &value) { + if (value != 0.0f) return; + + char *posptr = strstr_P(buf, key); + if (posptr == nullptr) return; + + char num[10] = ""; + for (uint8_t i = 0; i < sizeof(num);) { + const char c = *posptr; + if (ISEOL(c) || c == '\0') { + num[i] = '\0'; + value = atof(num); + break; } - - bool Preview::hasPreview() { - const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT)); - char *posptr = nullptr; - uint32_t indx = 0; - float tmp = 0; - - fileprop.clear(); - fileprop.setname(card.filename); - - card.openFileRead(fileprop.name); - - char buf[256]; - uint8_t nbyte = 1; - while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) { - nbyte = card.read(buf, sizeof(buf) - 1); - if (nbyte > 0) { - buf[nbyte] = '\0'; - getValue(buf, PSTR(";TIME:"), fileprop.time); - getValue(buf, PSTR(";Filament used:"), fileprop.filament); - getValue(buf, PSTR(";Layer height:"), fileprop.layer); - getValue(buf, PSTR(";MINX:"), tmp); - getValue(buf, PSTR(";MAXX:"), fileprop.width); - fileprop.width -= tmp; - tmp = 0; - getValue(buf, PSTR(";MINY:"), tmp); - getValue(buf, PSTR(";MAXY:"), fileprop.length); - fileprop.length -= tmp; - tmp = 0; - getValue(buf, PSTR(";MINZ:"), tmp); - getValue(buf, PSTR(";MAXZ:"), fileprop.height); - fileprop.height -= tmp; - posptr = strstr_P(buf, tbstart); - if (posptr != nullptr) { - fileprop.thumbstart = indx + (posptr - &buf[0]); - } - else { - indx += _MAX(10, nbyte - (signed)strlen_P(tbstart)); - card.setIndex(indx); - } - } + if (WITHIN(c, '0', '9') || c == '.') num[i++] = c; + posptr++; + } +} + +bool Preview::hasPreview() { + const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT)); + char *posptr = nullptr; + uint32_t indx = 0; + float tmp = 0; + + fileprop.clear(); + fileprop.setname(card.filename); + + card.openFileRead(fileprop.name); + + char buf[256]; + uint8_t nbyte = 1; + while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) { + nbyte = card.read(buf, sizeof(buf) - 1); + if (nbyte > 0) { + buf[nbyte] = '\0'; + getValue(buf, PSTR(";TIME:"), fileprop.time); + getValue(buf, PSTR(";Filament used:"), fileprop.filament); + getValue(buf, PSTR(";Layer height:"), fileprop.layer); + getValue(buf, PSTR(";MINX:"), tmp); + getValue(buf, PSTR(";MAXX:"), fileprop.width); + fileprop.width -= tmp; + tmp = 0; + getValue(buf, PSTR(";MINY:"), tmp); + getValue(buf, PSTR(";MAXY:"), fileprop.length); + fileprop.length -= tmp; + tmp = 0; + getValue(buf, PSTR(";MINZ:"), tmp); + getValue(buf, PSTR(";MAXZ:"), fileprop.height); + fileprop.height -= tmp; + posptr = strstr_P(buf, tbstart); + if (posptr != nullptr) { + fileprop.thumbstart = indx + (posptr - &buf[0]); } - - if (!fileprop.thumbstart) { - card.closefile(); - LCD_MESSAGE_F("Thumbnail not found"); - return false; + else { + indx += _MAX(10, nbyte - (signed)strlen_P(tbstart)); + card.setIndex(indx); } - - // Get the size of the thumbnail - card.setIndex(fileprop.thumbstart + strlen_P(tbstart)); - for (uint8_t i = 0; i < 16; i++) { - const char c = card.get(); - if (ISEOL(c)) { buf[i] = '\0'; break; } - buf[i] = c; - } - fileprop.thumbsize = atoi(buf); - - // Exit if there isn't a thumbnail - if (!fileprop.thumbsize) { - card.closefile(); - LCD_MESSAGE_F("Invalid Thumbnail Size"); - return false; - } - - uint8_t buf64[fileprop.thumbsize + 1]; - uint16_t nread = 0; - while (nread < fileprop.thumbsize) { - const uint8_t c = card.get(); - if (!ISEOL(c) && c != ';' && c != ' ') - buf64[nread++] = c; - } - card.closefile(); - buf64[nread] = '\0'; - - uint8_t thumbdata[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail - fileprop.thumbsize = decode_base64(buf64, thumbdata); - DWINUI::writeToSRAM(0x00, fileprop.thumbsize, thumbdata); - - fileprop.thumbwidth = THUMBWIDTH; - fileprop.thumbheight = THUMBHEIGHT; - - return true; } - - void Preview::drawFromSD() { - if (!hasPreview()) { - hmiFlag.select_flag = 1; - wait_for_user = false; - return; - } - - MString<45> buf; - dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1); - if (fileprop.time) { - buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60); - DWINUI::drawString(20, 10, &buf); - } - if (fileprop.filament) { - buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m")); - DWINUI::drawString(20, 30, &buf); - } - if (fileprop.layer) { - buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm")); - DWINUI::drawString(20, 50, &buf); - } - if (fileprop.width) { - buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm")); - DWINUI::drawString(20, 70, &buf); - } - DWINUI::drawButton(BTN_Print, 26, 290); - DWINUI::drawButton(BTN_Cancel, 146, 290); - show(); - drawSelectHighlight(true, 290); - dwinUpdateLCD(); - } - - void Preview::invalidate() { - fileprop.thumbsize = 0; - } - - bool Preview::valid() { - return !!fileprop.thumbsize; - } - - void Preview::show() { - const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2, - ypos = (205 - fileprop.thumbheight) / 2 + 87; - dwinIconShow(xpos, ypos, 0x00); - } - - #endif // HAS_GCODE_PREVIEW + } + + if (!fileprop.thumbstart) { + card.closefile(); + LCD_MESSAGE_F("Thumbnail not found"); + return false; + } + + // Get the size of the thumbnail + card.setIndex(fileprop.thumbstart + strlen_P(tbstart)); + for (uint8_t i = 0; i < 16; i++) { + const char c = card.get(); + if (ISEOL(c)) { buf[i] = '\0'; break; } + buf[i] = c; + } + fileprop.thumbsize = atoi(buf); + + // Exit if there isn't a thumbnail + if (!fileprop.thumbsize) { + card.closefile(); + LCD_MESSAGE_F("Invalid Thumbnail Size"); + return false; + } + + uint8_t buf64[fileprop.thumbsize + 1]; + uint16_t nread = 0; + while (nread < fileprop.thumbsize) { + const uint8_t c = card.get(); + if (!ISEOL(c) && c != ';' && c != ' ') + buf64[nread++] = c; + } + card.closefile(); + buf64[nread] = '\0'; + + uint8_t thumbdata[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail + fileprop.thumbsize = decode_base64(buf64, thumbdata); + DWINUI::writeToSRAM(0x00, fileprop.thumbsize, thumbdata); + + fileprop.thumbwidth = THUMBWIDTH; + fileprop.thumbheight = THUMBHEIGHT; + + return true; +} + +void Preview::drawFromSD() { + if (!hasPreview()) { + hmiFlag.select_flag = 1; + wait_for_user = false; + return; + } + + MString<45> buf; + dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1); + if (fileprop.time) { + buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60); + DWINUI::drawString(20, 10, &buf); + } + if (fileprop.filament) { + buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m")); + DWINUI::drawString(20, 30, &buf); + } + if (fileprop.layer) { + buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm")); + DWINUI::drawString(20, 50, &buf); + } + if (fileprop.width) { + buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm")); + DWINUI::drawString(20, 70, &buf); + } + DWINUI::drawButton(BTN_Print, 26, 290); + DWINUI::drawButton(BTN_Cancel, 146, 290); + show(); + drawSelectHighlight(true, 290); + dwinUpdateLCD(); +} + +void Preview::invalidate() { + fileprop.thumbsize = 0; +} + +bool Preview::valid() { + return !!fileprop.thumbsize; +} + +void Preview::show() { + const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2, + ypos = (205 - fileprop.thumbheight) / 2 + 87; + dwinIconShow(xpos, ypos, 0x00); +} + +#endif // HAS_GCODE_PREVIEW #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp index 6bde818215d3..cc18bdd214d6 100644 --- a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp +++ b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp @@ -31,48 +31,48 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "dwin_defines.h" +#include "dwin_defines.h" - #if HAS_LOCKSCREEN +#if HAS_LOCKSCREEN - #include "dwin.h" - #include "lockscreen.h" +#include "dwin.h" +#include "lockscreen.h" - LockScreen lockScreen; +LockScreen lockScreen; - uint8_t LockScreen::lock_pos = 0; - bool LockScreen::unlocked = false; - uint8_t LockScreen::rprocess = 0; +uint8_t LockScreen::lock_pos = 0; +bool LockScreen::unlocked = false; +uint8_t LockScreen::rprocess = 0; - void LockScreen::init() { - lock_pos = 0; - unlocked = false; - draw(); - } +void LockScreen::init() { + lock_pos = 0; + unlocked = false; + draw(); +} - void LockScreen::draw() { - title.setCaption(GET_TEXT_F(MSG_LOCKSCREEN)); - DWINUI::clearMainArea(); - DWINUI::drawIcon(ICON_LOGO, 71, 120); // CREALITY logo - DWINUI::drawCenteredString(COLOR_WHITE, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED)); - DWINUI::drawCenteredString(COLOR_WHITE, 200, GET_TEXT_F(MSG_LOCKSCREEN_UNLOCK)); - DWINUI::drawCenteredString(COLOR_WHITE, 240, F("-> | <-")); - dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); - dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); - dwinUpdateLCD(); - } +void LockScreen::draw() { + title.setCaption(GET_TEXT_F(MSG_LOCKSCREEN)); + DWINUI::clearMainArea(); + DWINUI::drawIcon(ICON_LOGO, 71, 120); // CREALITY logo + DWINUI::drawCenteredString(COLOR_WHITE, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED)); + DWINUI::drawCenteredString(COLOR_WHITE, 200, GET_TEXT_F(MSG_LOCKSCREEN_UNLOCK)); + DWINUI::drawCenteredString(COLOR_WHITE, 240, F("-> | <-")); + dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); + dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); + dwinUpdateLCD(); +} - void LockScreen::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; - } - dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); - dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); - dwinUpdateLCD(); - } +void LockScreen::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; + } + dwinDrawBox(1, hmiData.colorBarfill, 0, 260, DWIN_WIDTH, 20); + dwinDrawVLine(COLOR_YELLOW, lock_pos * DWIN_WIDTH / 255, 260, 20); + dwinUpdateLCD(); +} - #endif // HAS_LOCKSCREEN +#endif // HAS_LOCKSCREEN #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/menus.cpp b/Marlin/src/lcd/e3v2/proui/menus.cpp index 9a61fd3ceff4..d537bc5ae663 100644 --- a/Marlin/src/lcd/e3v2/proui/menus.cpp +++ b/Marlin/src/lcd/e3v2/proui/menus.cpp @@ -31,531 +31,531 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "../common/encoder.h" - #include "dwin.h" - #include "menus.h" - - int8_t MenuItemTotal = 0; - int8_t MenuItemCount = 0; - CustomMenuItem** menuItems = nullptr; - Menu *currentMenu = nullptr; - Menu *previousMenu = nullptr; - MenuData_t menuData; - - // Menuitem Drawing functions ================================================= - - void drawTitle(Title* aTitle) { - dwinDrawRectangle(1, hmiData.colorTitleBg, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); - if (aTitle->frameid) - dwinFrameAreaCopy(aTitle->frameid, aTitle->frame.left, aTitle->frame.top, aTitle->frame.right, aTitle->frame.bottom, 14, (TITLE_HEIGHT - (aTitle->frame.bottom - aTitle->frame.top)) / 2 - 1); +#include "../common/encoder.h" +#include "dwin.h" +#include "menus.h" + +int8_t MenuItemTotal = 0; +int8_t MenuItemCount = 0; +CustomMenuItem** menuItems = nullptr; +Menu *currentMenu = nullptr; +Menu *previousMenu = nullptr; +MenuData_t menuData; + +// Menuitem Drawing functions ================================================= + +void drawTitle(Title* aTitle) { + dwinDrawRectangle(1, hmiData.colorTitleBg, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); + if (aTitle->frameid) + dwinFrameAreaCopy(aTitle->frameid, aTitle->frame.left, aTitle->frame.top, aTitle->frame.right, aTitle->frame.bottom, 14, (TITLE_HEIGHT - (aTitle->frame.bottom - aTitle->frame.top)) / 2 - 1); + else + #if ENABLED(TITLE_CENTERED) + DWINUI::drawCenteredString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); + #else + dwinDrawString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); + #endif +} + +void drawMenuCursor(const int8_t line) { + const uint16_t ypos = MYPOS(line); + DWINUI::drawBox(1, hmiData.colorCursor, {0, ypos, 15, MLINE - 1}); +} + +void eraseMenuCursor(const int8_t line) { + const uint16_t ypos = MYPOS(line); + DWINUI::drawBox(1, hmiData.colorBackground, {0, ypos, 15, MLINE - 1}); +} + +void eraseMenuText(const int8_t line) { + if (line < 0 || line >= TROWS) return; + const uint16_t ypos = MYPOS(line) + 1; + DWINUI::drawBox(1, hmiData.colorBackground, {LBLX, ypos, DWIN_WIDTH - LBLX, MLINE - 2}); +} + +void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, const char * const label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { + if (icon) DWINUI::drawIcon(icon, ICOX, MBASE(line) - 3); + if (label) DWINUI::drawString(LBLX, MBASE(line) - 1, (char*)label); + if (more) DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); + if (selected) drawMenuCursor(line); + dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); +} + +void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, FSTR_P label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { + drawMenuLine(line, icon, FTOP(label), more, selected); +} + +void drawCheckboxLine(const uint8_t line, const bool checked) { + DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); +} + +void showCheckboxLine(const bool checked) { + const uint8_t line = currentMenu->line(); + DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); + dwinUpdateLCD(); +} + +void toggleCheckboxLine(bool &checked) { + checked = !checked; + showCheckboxLine(checked); +} + +void drawMenuIntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value/*=0*/) { + DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(line) - 1, value); +} + +void onDrawMenuItem(MenuItem* menuitem, int8_t line) { + if (menuitem->icon) DWINUI::drawIcon(menuitem->icon, ICOX, MBASE(line) - 3); + if (menuitem->frameid) + dwinFrameAreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); + else if (menuitem->caption) + DWINUI::drawString(LBLX, MBASE(line) - 1, menuitem->caption); + dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); +} + +void onDrawSubMenu(MenuItem* menuitem, int8_t line) { + onDrawMenuItem(menuitem, line); + DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); +} + +void onDrawIntMenu(MenuItem* menuitem, int8_t line, int32_t value) { + onDrawMenuItem(menuitem, line); + drawMenuIntValue(hmiData.colorBackground, line, 4, value); +} + +void onDrawPIntMenu(MenuItem* menuitem, int8_t line) { + const int16_t value = *(int16_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawPInt8Menu(MenuItem* menuitem, int8_t line) { + const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawPInt32Menu(MenuItem* menuitem, int8_t line) { + const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp, const float value) { + onDrawMenuItem(menuitem, line); + DWINUI::drawSignedFloat(hmiData.colorText, hmiData.colorBackground, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); +} + +void onDrawPFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp) { + const float value = *(float*)static_cast(menuitem)->value; + onDrawFloatMenu(menuitem, line, dp, value); +} + +void onDrawChkbMenu(MenuItem* menuitem, int8_t line, bool checked) { + onDrawMenuItem(menuitem, line); + drawCheckboxLine(line, checked); +} + +void onDrawChkbMenu(MenuItem* menuitem, int8_t line) { + const bool val = *(bool*)static_cast(menuitem)->value; + onDrawChkbMenu(menuitem, line, val); +} + +void DrawItemEdit(const bool selected) { + const uint16_t bcolor = selected ? hmiData.colorSelected : hmiData.colorBackground; + const uint8_t iNum = 4 - ((menuData.dp > 0) ? (menuData.dp - 1) : 0); + switch (checkkey) { + case ID_SetIntNoDraw: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case ID_SetInt: + case ID_SetPInt: DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(currentMenu->line()) - 1, menuData.value); break; + case ID_SetFloat: + case ID_SetPFloat: DWINUI::drawSignedFloat(hmiData.colorText, bcolor, iNum, menuData.dp, VALX - 2 * DWINUI::fontWidth(), 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); + DrawItemEdit(true); +} + +// 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); + DrawItemEdit(true); +} + +// 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(ID_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.intPtr = (int16_t*)static_cast(currentMenu->selectedItem())->value; + const int32_t value = *menuData.intPtr; + setValueOnClick(ID_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(ID_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.floatPtr = (float*)static_cast(currentMenu->selectedItem())->value; + setValueOnClick(ID_SetPFloat, lo, hi, dp, *menuData.floatPtr, apply, liveUpdate); +} + +// HMI Control functions ====================================================== + +// Generic menu control using the encoder +void hmiMenu() { + EncoderState encoder_diffState = get_encoder_state(); + if (currentMenu) { + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (encoder_diffState == ENCODER_DIFF_ENTER) + currentMenu->onClick(); else - #if ENABLED(TITLE_CENTERED) - DWINUI::drawCenteredString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); - #else - dwinDrawString(false, DWIN_FONT_HEAD, hmiData.colorTitleTxt, hmiData.colorTitleBg, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, aTitle->caption); - #endif - } - - void drawMenuCursor(const int8_t line) { - const uint16_t ypos = MYPOS(line); - DWINUI::drawBox(1, hmiData.colorCursor, {0, ypos, 15, MLINE - 1}); - } - - void eraseMenuCursor(const int8_t line) { - const uint16_t ypos = MYPOS(line); - DWINUI::drawBox(1, hmiData.colorBackground, {0, ypos, 15, MLINE - 1}); - } - - void eraseMenuText(const int8_t line) { - if (line < 0 || line >= TROWS) return; - const uint16_t ypos = MYPOS(line) + 1; - DWINUI::drawBox(1, hmiData.colorBackground, {LBLX, ypos, DWIN_WIDTH - LBLX, MLINE - 2}); - } - - void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, const char * const label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { - if (icon) DWINUI::drawIcon(icon, ICOX, MBASE(line) - 3); - if (label) DWINUI::drawString(LBLX, MBASE(line) - 1, (char*)label); - if (more) DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); - if (selected) drawMenuCursor(line); - dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); - } - - void drawMenuLine(const uint8_t line, const uint8_t icon/*=0*/, FSTR_P label/*=nullptr*/, bool more/*=false*/, bool selected/*=false*/) { - drawMenuLine(line, icon, FTOP(label), more, selected); - } - - void drawCheckboxLine(const uint8_t line, const bool checked) { - DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); - } - - void showCheckboxLine(const bool checked) { - const uint8_t line = currentMenu->line(); - DWINUI::drawCheckbox(hmiData.colorText, hmiData.colorBackground, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked); - dwinUpdateLCD(); - } - - void toggleCheckboxLine(bool &checked) { - checked = !checked; - showCheckboxLine(checked); - } - - void drawMenuIntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value/*=0*/) { - DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(line) - 1, value); - } - - void onDrawMenuItem(MenuItem* menuitem, int8_t line) { - if (menuitem->icon) DWINUI::drawIcon(menuitem->icon, ICOX, MBASE(line) - 3); - if (menuitem->frameid) - dwinFrameAreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); - else if (menuitem->caption) - DWINUI::drawString(LBLX, MBASE(line) - 1, menuitem->caption); - dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); - } - - void onDrawSubMenu(MenuItem* menuitem, int8_t line) { - onDrawMenuItem(menuitem, line); - DWINUI::drawIcon(ICON_More, VALX + 16, MBASE(line) - 3); - } - - void onDrawIntMenu(MenuItem* menuitem, int8_t line, int32_t value) { - onDrawMenuItem(menuitem, line); - drawMenuIntValue(hmiData.colorBackground, line, 4, value); - } - - void onDrawPIntMenu(MenuItem* menuitem, int8_t line) { - const int16_t value = *(int16_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); - } - - void onDrawPInt8Menu(MenuItem* menuitem, int8_t line) { - const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); - } - - void onDrawPInt32Menu(MenuItem* menuitem, int8_t line) { - const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); - } - - void onDrawFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp, const float value) { - onDrawMenuItem(menuitem, line); - DWINUI::drawSignedFloat(hmiData.colorText, hmiData.colorBackground, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); - } - - void onDrawPFloatMenu(MenuItem* menuitem, int8_t line, uint8_t dp) { - const float value = *(float*)static_cast(menuitem)->value; - onDrawFloatMenu(menuitem, line, dp, value); - } - - void onDrawChkbMenu(MenuItem* menuitem, int8_t line, bool checked) { - onDrawMenuItem(menuitem, line); - drawCheckboxLine(line, checked); - } - - void onDrawChkbMenu(MenuItem* menuitem, int8_t line) { - const bool val = *(bool*)static_cast(menuitem)->value; - onDrawChkbMenu(menuitem, line, val); - } - - void DrawItemEdit(const bool selected) { - const uint16_t bcolor = selected ? hmiData.colorSelected : hmiData.colorBackground; - const uint8_t iNum = 4 - ((menuData.dp > 0) ? (menuData.dp - 1) : 0); - switch (checkkey) { - case ID_SetIntNoDraw: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case ID_SetInt: - case ID_SetPInt: DWINUI::drawSignedInt(hmiData.colorText, bcolor, iNum , VALX, MBASE(currentMenu->line()) - 1, menuData.value); break; - case ID_SetFloat: - case ID_SetPFloat: DWINUI::drawSignedFloat(hmiData.colorText, bcolor, iNum, menuData.dp, VALX - 2 * DWINUI::fontWidth(), 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); - DrawItemEdit(true); - } - - // 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); - DrawItemEdit(true); - } - - // 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(ID_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.intPtr = (int16_t*)static_cast(currentMenu->selectedItem())->value; - const int32_t value = *menuData.intPtr; - setValueOnClick(ID_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(ID_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.floatPtr = (float*)static_cast(currentMenu->selectedItem())->value; - setValueOnClick(ID_SetPFloat, lo, hi, dp, *menuData.floatPtr, apply, liveUpdate); - } - - // HMI Control functions ====================================================== - - // Generic menu control using the encoder - void hmiMenu() { - EncoderState encoder_diffState = get_encoder_state(); - if (currentMenu) { - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_ENTER) - currentMenu->onClick(); - else - currentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); + currentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); + } +} + +// Get a value using the encoder +// draw : draw the value +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t hmiGet(bool draw) { + const int32_t lo = menuData.minValue; + const int32_t hi = menuData.maxValue; + const int32_t cval = menuData.value; + EncoderState encoder_diffState = TERN(SMOOTH_ENCODER_MENUITEMS, get_encoder_state(), encoderReceiveAnalyze()); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (applyEncoder(encoder_diffState, menuData.value)) { + encoderRate.enabled = false; + if (draw) DrawItemEdit(false); + checkkey = ID_Menu; + return 2; } - } - - // Get a value using the encoder - // draw : draw the value - // Return value: - // 0 : no change - // 1 : live change - // 2 : apply change - int8_t hmiGet(bool draw) { - const int32_t lo = menuData.minValue; - const int32_t hi = menuData.maxValue; - const int32_t cval = menuData.value; - EncoderState encoder_diffState = TERN(SMOOTH_ENCODER_MENUITEMS, get_encoder_state(), encoderReceiveAnalyze()); - if (encoder_diffState != ENCODER_DIFF_NO) { - if (applyEncoder(encoder_diffState, menuData.value)) { - encoderRate.enabled = false; - if (draw) DrawItemEdit(false); - checkkey = ID_Menu; - return 2; - } - LIMIT(menuData.value, lo, hi); - } - const bool change = cval != menuData.value; - if (change) DrawItemEdit(true); - return int8_t(change); - } - - // Set and draw a value using the encoder - void hmiSetDraw() { - int8_t val = hmiGet(true); - switch (val) { - case 0: return; - case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case 2: if (menuData.apply) menuData.apply(); break; - } - } - - // Set an value without drawing - void hmiSetNoDraw() { - int8_t val = hmiGet(false); - switch (val) { - case 0: return; - 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 hmiSetPInt() { - int8_t val = hmiGet(true); - switch (val) { - case 0: return; - case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case 2: *menuData.intPtr = menuData.value; if (menuData.apply) menuData.apply(); break; + LIMIT(menuData.value, lo, hi); + } + const bool change = cval != menuData.value; + if (change) DrawItemEdit(true); + return int8_t(change); +} + +// Set and draw a value using the encoder +void hmiSetDraw() { + int8_t val = hmiGet(true); + switch (val) { + case 0: return; + case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case 2: if (menuData.apply) menuData.apply(); break; + } +} + +// Set an value without drawing +void hmiSetNoDraw() { + int8_t val = hmiGet(false); + switch (val) { + case 0: return; + 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 hmiSetPInt() { + int8_t val = hmiGet(true); + switch (val) { + case 0: return; + case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case 2: *menuData.intPtr = menuData.value; if (menuData.apply) menuData.apply(); break; + } +} + +// Set a scaled float pointer variable using the encoder +void hmiSetPFloat() { + const int8_t val = hmiGet(true); + switch (val) { + case 0: return; + case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; + case 2: *menuData.floatPtr = menuData.value / POW(10, menuData.dp); if (menuData.apply) menuData.apply(); break; + } +} + +// Menu Class =============================================================== + +Menu::Menu() { + selected = 0; + topline = 0; +} + +void Menu::draw() { + menuTitle.draw(); + DWINUI::setColors(hmiData.colorText, hmiData.colorBackground, hmiData.colorStatusBg); + dwinDrawRectangle(1, DWINUI::backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); + for (int8_t i = 0; i < MenuItemCount; i++) + menuItems[i]->draw(i - topline); + drawMenuCursor(line()); + dwinUpdateLCD(); +} + +void Menu::onScroll(bool dir) { + int8_t sel = selected; + if (dir) sel++; else sel--; + LIMIT(sel, 0, MenuItemCount - 1); + if (sel != selected) { + eraseMenuCursor(line()); + dwinUpdateLCD(); + if ((sel - topline) == TROWS) { + dwinFrameAreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backColor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); + topline++; + menuItems[sel]->draw(TROWS - 1); } - } - - // Set a scaled float pointer variable using the encoder - void hmiSetPFloat() { - const int8_t val = hmiGet(true); - switch (val) { - case 0: return; - case 1: if (menuData.liveUpdate) menuData.liveUpdate(); break; - case 2: *menuData.floatPtr = menuData.value / POW(10, menuData.dp); if (menuData.apply) menuData.apply(); break; + if ((sel < topline)) { + dwinFrameAreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backColor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); + topline--; + menuItems[sel]->draw(0); } - } - - // Menu Class =============================================================== - - Menu::Menu() { - selected = 0; - topline = 0; - } - - void Menu::draw() { - menuTitle.draw(); - DWINUI::setColors(hmiData.colorText, hmiData.colorBackground, hmiData.colorStatusBg); - dwinDrawRectangle(1, DWINUI::backColor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); - for (int8_t i = 0; i < MenuItemCount; i++) - menuItems[i]->draw(i - topline); + selected = sel; drawMenuCursor(line()); dwinUpdateLCD(); } - - void Menu::onScroll(bool dir) { - int8_t sel = selected; - if (dir) sel++; else sel--; - LIMIT(sel, 0, MenuItemCount - 1); - if (sel != selected) { - eraseMenuCursor(line()); - dwinUpdateLCD(); - if ((sel - topline) == TROWS) { - dwinFrameAreaMove(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)) { - dwinFrameAreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backColor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1); - topline--; - menuItems[sel]->draw(0); - } - selected = sel; - drawMenuCursor(line()); - dwinUpdateLCD(); - } - } - - void Menu::onClick() { - if (menuItems[selected]->onClick != nullptr) (*menuItems[selected]->onClick)(); - } - - CustomMenuItem *Menu::selectedItem() { - return menuItems[selected]; - } - - CustomMenuItem** Menu::items() { - return menuItems; - } - - int8_t Menu::count() { - return MenuItemCount; - }; - - /* MenuItem Class ===========================================================*/ - - void CustomMenuItem::draw(int8_t line) { - if (line < 0 || line >= TROWS) return; - if (onDraw != nullptr) (*onDraw)(static_cast(this), line); - }; - - void CustomMenuItem::redraw(bool erase/*=false*/) { - const int8_t line = currentMenu->line(this->pos); - if (erase) eraseMenuText(line); - draw(line); - } - - CustomMenuItem::CustomMenuItem(OnDrawItem ondraw, OnClickItem onclick) { - onClick = onclick; - onDraw = ondraw; - } - - MenuItem::MenuItem(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { - icon = cicon; - setCaption(text); - } - - MenuItem::MenuItem(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { - icon = cicon; - caption[0] = '\0'; - frameid = id; - frame = { x1, y1, x2, y2 }; - } - - void MenuItem::setCaption(const char * const text) { - const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text)); - memcpy(&caption[0], text, len); - caption[len] = '\0'; - } - - void MenuItem::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 }; - } - - MenuItemPtr::MenuItemPtr(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) : MenuItem(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 = _MIN(totalitems, MENU_MAX_ITEMS); - menuItems = new CustomMenuItem*[totalitems]; - } - - bool isMenu(Menu* _menu) { - return ((checkkey == ID_Menu) && !!currentMenu && (currentMenu == _menu)); - } - - template - T* menuItemAdd(T* menuitem) { - menuItems[MenuItemCount] = menuitem; - menuitem->pos = MenuItemCount++; - return menuitem; - } - - CustomMenuItem* menuItemAdd(OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { - if (MenuItemCount < MenuItemTotal) { - CustomMenuItem* menuitem = new CustomMenuItem(ondraw, onclick); - return menuItemAdd(menuitem); - } - else return nullptr; - } - - MenuItem* menuItemAdd(uint8_t cicon, const char * const text/*=nullptr*/, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { - if (MenuItemCount < MenuItemTotal) { - MenuItem* menuitem = new MenuItem(cicon, text, ondraw, onclick); - return menuItemAdd(menuitem); - } - else return nullptr; - } - - MenuItem* menuItemAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { - if (MenuItemCount < MenuItemTotal) { - MenuItem* menuitem = new MenuItem(cicon, id, x1, y1, x2, y2, ondraw, onclick); - return menuItemAdd(menuitem); - } - else return nullptr; - } - - MenuItem* editItemAdd(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) { - if (MenuItemCount < MenuItemTotal) { - MenuItem* menuitem = new MenuItemPtr(cicon, text, ondraw, onclick, val); - return menuItemAdd(menuitem); - } - else return nullptr; - } - - void initMenu() { - currentMenu = nullptr; - previousMenu = nullptr; - } - - bool setMenu(Menu* &menu, FSTR_P fTitle, int8_t totalitems) { - if (!menu) menu = new Menu(); - const bool notCurrent = (currentMenu != menu); - if (notCurrent) { +} + +void Menu::onClick() { + if (menuItems[selected]->onClick != nullptr) (*menuItems[selected]->onClick)(); +} + +CustomMenuItem *Menu::selectedItem() { + return menuItems[selected]; +} + +CustomMenuItem** Menu::items() { + return menuItems; +} + +int8_t Menu::count() { + return MenuItemCount; +}; + +/* MenuItem Class ===========================================================*/ + +void CustomMenuItem::draw(int8_t line) { + if (line < 0 || line >= TROWS) return; + if (onDraw != nullptr) (*onDraw)(static_cast(this), line); +}; + +void CustomMenuItem::redraw(bool erase/*=false*/) { + const int8_t line = currentMenu->line(this->pos); + if (erase) eraseMenuText(line); + draw(line); +} + +CustomMenuItem::CustomMenuItem(OnDrawItem ondraw, OnClickItem onclick) { + onClick = onclick; + onDraw = ondraw; +} + +MenuItem::MenuItem(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { + icon = cicon; + setCaption(text); +} + +MenuItem::MenuItem(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw, OnClickItem onclick) : CustomMenuItem(ondraw, onclick) { + icon = cicon; + caption[0] = '\0'; + frameid = id; + frame = { x1, y1, x2, y2 }; +} + +void MenuItem::setCaption(const char * const text) { + const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text)); + memcpy(&caption[0], text, len); + caption[len] = '\0'; +} + +void MenuItem::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 }; +} + +MenuItemPtr::MenuItemPtr(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) : MenuItem(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 = _MIN(totalitems, MENU_MAX_ITEMS); + menuItems = new CustomMenuItem*[totalitems]; +} + +bool isMenu(Menu* _menu) { + return ((checkkey == ID_Menu) && !!currentMenu && (currentMenu == _menu)); +} + +template +T* menuItemAdd(T* menuitem) { + menuItems[MenuItemCount] = menuitem; + menuitem->pos = MenuItemCount++; + return menuitem; +} + +CustomMenuItem* menuItemAdd(OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + CustomMenuItem* menuitem = new CustomMenuItem(ondraw, onclick); + return menuItemAdd(menuitem); + } + else return nullptr; +} + +MenuItem* menuItemAdd(uint8_t cicon, const char * const text/*=nullptr*/, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + MenuItem* menuitem = new MenuItem(cicon, text, ondraw, onclick); + return menuItemAdd(menuitem); + } + else return nullptr; +} + +MenuItem* menuItemAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, OnDrawItem ondraw/*=nullptr*/, OnClickItem onclick/*=nullptr*/) { + if (MenuItemCount < MenuItemTotal) { + MenuItem* menuitem = new MenuItem(cicon, id, x1, y1, x2, y2, ondraw, onclick); + return menuItemAdd(menuitem); + } + else return nullptr; +} + +MenuItem* editItemAdd(uint8_t cicon, const char * const text, OnDrawItem ondraw, OnClickItem onclick, void* val) { + if (MenuItemCount < MenuItemTotal) { + MenuItem* menuitem = new MenuItemPtr(cicon, text, ondraw, onclick, val); + return menuItemAdd(menuitem); + } + else return nullptr; +} + +void initMenu() { + currentMenu = nullptr; + previousMenu = nullptr; +} + +bool setMenu(Menu* &menu, FSTR_P fTitle, int8_t totalitems) { + if (!menu) menu = new Menu(); + const bool notCurrent = (currentMenu != menu); + if (notCurrent) { + menu->menuTitle.setCaption(fTitle); + menuItemsPrepare(totalitems); + } + return notCurrent; +} + +bool setMenu(Menu* &menu, frame_rect_t cn, FSTR_P fTitle, int8_t totalitems) { + if (!menu) menu = new Menu(); + const bool notCurrent = (currentMenu != menu); + if (notCurrent) { + if (cn.w != 0) + menu->menuTitle.setFrame(cn.x, cn.y, cn.w, cn.h); + else menu->menuTitle.setCaption(fTitle); - menuItemsPrepare(totalitems); - } - return notCurrent; + menuItemsPrepare(totalitems); } + return notCurrent; +} - bool setMenu(Menu* &menu, frame_rect_t cn, FSTR_P fTitle, int8_t totalitems) { - if (!menu) menu = new Menu(); - const bool notCurrent = (currentMenu != menu); - if (notCurrent) { - if (cn.w != 0) - menu->menuTitle.setFrame(cn.x, cn.y, cn.w, cn.h); - else - menu->menuTitle.setCaption(fTitle); - menuItemsPrepare(totalitems); - } - return notCurrent; - } - - void resetMenu(Menu* &menu) { - if (menu) { - menu->topline = 0; - menu->selected = 0; - } +void resetMenu(Menu* &menu) { + if (menu) { + menu->topline = 0; + menu->selected = 0; } +} - void invalidateMenu() { - resetMenu(currentMenu); - currentMenu = nullptr; - } +void invalidateMenu() { + resetMenu(currentMenu); + currentMenu = nullptr; +} - void updateMenu(Menu* &menu) { - if (!menu) return; - if (currentMenu != menu) { - previousMenu = currentMenu; - currentMenu = menu; - } - menu->draw(); +void updateMenu(Menu* &menu) { + if (!menu) return; + if (currentMenu != menu) { + previousMenu = currentMenu; + currentMenu = menu; } + menu->draw(); +} - void ReDrawMenu(bool force/*=false*/) { - if (currentMenu && (force || checkkey == ID_Menu)) currentMenu->draw(); - if (force) DrawItemEdit(true); - } +void ReDrawMenu(bool force/*=false*/) { + if (currentMenu && (force || checkkey == ID_Menu)) currentMenu->draw(); + if (force) DrawItemEdit(true); +} - void ReDrawItem() { - static_cast(currentMenu->selectedItem())->redraw(false); - } +void ReDrawItem() { + static_cast(currentMenu->selectedItem())->redraw(false); +} #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/meshviewer.cpp b/Marlin/src/lcd/e3v2/proui/meshviewer.cpp index 4803d2f92e8e..1c5f08bb4dfa 100644 --- a/Marlin/src/lcd/e3v2/proui/meshviewer.cpp +++ b/Marlin/src/lcd/e3v2/proui/meshviewer.cpp @@ -31,118 +31,118 @@ #if ALL(DWIN_LCD_PROUI, HAS_MESH) - #include "../../../core/types.h" - #include "../../marlinui.h" - #include "dwin.h" - #include "dwin_popup.h" - #include "../../../feature/bedlevel/bedlevel.h" - #include "meshviewer.h" - - #if ENABLED(USE_GRID_MESHVIEWER) - #include "bedlevel_tools.h" - #endif - - bool meshredraw; // Redraw mesh points - uint8_t sizex, sizey; // Mesh XY size - uint8_t rmax; // Maximum radius - #define margin 25 // XY Margins - #define rmin 5 // Minimum radius - #define zmin -20 // rmin at z=-0.20 - #define zmax 20 // rmax at z= 0.20 - #define width DWIN_WIDTH - 2 * margin - #define r(z) ((z - zmin) * (rmax - rmin) / (zmax - zmin) + rmin) - #define px(xp) (margin + (xp) * (width) / (sizex - 1)) - #define py(yp) (30 + DWIN_WIDTH - margin - (yp) * (width) / (sizey - 1)) - - constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - - MeshViewer meshViewer; - - float MeshViewer::max, MeshViewer::min; - - void MeshViewer::drawMeshGrid(const uint8_t csizex, const uint8_t csizey) { - sizex = csizex; - sizey = csizey; - rmax = _MIN(margin - 2, 0.5 * (width) / (sizex - 1)); - min = 100; - max = -100; - DWINUI::clearMainArea(); - dwinDrawRectangle(0, hmiData.colorSplitLine, px(0), py(0), px(sizex - 1), py(sizey - 1)); - for (uint8_t x = 1; x < sizex - 1; ++x) dwinDrawVLine(hmiData.colorSplitLine, px(x), py(sizey - 1), width); - for (uint8_t y = 1; y < sizey - 1; ++y) dwinDrawHLine(hmiData.colorSplitLine, px(0), py(y), width); +#include "../../../core/types.h" +#include "../../marlinui.h" +#include "dwin.h" +#include "dwin_popup.h" +#include "../../../feature/bedlevel/bedlevel.h" +#include "meshviewer.h" + +#if ENABLED(USE_GRID_MESHVIEWER) + #include "bedlevel_tools.h" +#endif + +bool meshredraw; // Redraw mesh points +uint8_t sizex, sizey; // Mesh XY size +uint8_t rmax; // Maximum radius +#define margin 25 // XY Margins +#define rmin 5 // Minimum radius +#define zmin -20 // rmin at z=-0.20 +#define zmax 20 // rmax at z= 0.20 +#define width DWIN_WIDTH - 2 * margin +#define r(z) ((z - zmin) * (rmax - rmin) / (zmax - zmin) + rmin) +#define px(xp) (margin + (xp) * (width) / (sizex - 1)) +#define py(yp) (30 + DWIN_WIDTH - margin - (yp) * (width) / (sizey - 1)) + +constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); + +MeshViewer meshViewer; + +float MeshViewer::max, MeshViewer::min; + +void MeshViewer::drawMeshGrid(const uint8_t csizex, const uint8_t csizey) { + sizex = csizex; + sizey = csizey; + rmax = _MIN(margin - 2, 0.5 * (width) / (sizex - 1)); + min = 100; + max = -100; + DWINUI::clearMainArea(); + dwinDrawRectangle(0, hmiData.colorSplitLine, px(0), py(0), px(sizex - 1), py(sizey - 1)); + for (uint8_t x = 1; x < sizex - 1; ++x) dwinDrawVLine(hmiData.colorSplitLine, px(x), py(sizey - 1), width); + for (uint8_t y = 1; y < sizey - 1; ++y) dwinDrawHLine(hmiData.colorSplitLine, px(0), py(y), width); +} + +void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) { + const uint8_t fs = DWINUI::fontWidth(meshfont); + const int16_t v = isnan(z) ? 0 : round(z * 100); + NOLESS(max, z); NOMORE(min, z); + + const uint16_t color = DWINUI::rainbowInt(v, zmin, zmax); + DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v, zmax), zmin))); + TERN_(TJC_DISPLAY, delay(100)); + + const uint16_t fy = py(y) - fs; + if (sizex < TERN(TJC_DISPLAY, 8, 9)) { + if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2 * fs, fy, 0); + else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3 * fs, fy, z); } - - void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) { - const uint8_t fs = DWINUI::fontWidth(meshfont); - const int16_t v = isnan(z) ? 0 : round(z * 100); - NOLESS(max, z); NOMORE(min, z); - - const uint16_t color = DWINUI::rainbowInt(v, zmin, zmax); - DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v, zmax), zmin))); - TERN_(TJC_DISPLAY, delay(100)); - - const uint16_t fy = py(y) - fs; - if (sizex < TERN(TJC_DISPLAY, 8, 9)) { - if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2 * fs, fy, 0); - else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3 * fs, fy, z); - } - else { - char msg[9]; msg[0] = '\0'; - switch (v) { - case -999 ... -100: - case 100 ... 999: DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, fy, z); break; - case -99 ... -1: sprintf_P(msg, PSTR("-.%2i"), -v); break; - case 1 ... 99: sprintf_P(msg, PSTR( ".%2i"), v); break; - default: - dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, fy, "0"); - return; - } - dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, fy, msg); + else { + char msg[9]; msg[0] = '\0'; + switch (v) { + case -999 ... -100: + case 100 ... 999: DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, fy, z); break; + case -99 ... -1: sprintf_P(msg, PSTR("-.%2i"), -v); break; + case 1 ... 99: sprintf_P(msg, PSTR( ".%2i"), v); break; + default: + dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, fy, "0"); + return; } + dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, fy, msg); } +} - void MeshViewer::drawMesh(const bed_mesh_t zval, const uint8_t csizex, const uint8_t csizey) { - drawMeshGrid(csizex, csizey); - for (uint8_t y = 0; y < csizey; ++y) { - hal.watchdog_refresh(); - for (uint8_t x = 0; x < csizex; ++x) drawMeshPoint(x, y, zval[x][y]); - } +void MeshViewer::drawMesh(const bed_mesh_t zval, const uint8_t csizex, const uint8_t csizey) { + drawMeshGrid(csizex, csizey); + for (uint8_t y = 0; y < csizey; ++y) { + hal.watchdog_refresh(); + for (uint8_t x = 0; x < csizex; ++x) drawMeshPoint(x, y, zval[x][y]); } +} - void MeshViewer::draw(const bool withsave/*=false*/, const bool redraw/*=true*/) { - title.showCaption(GET_TEXT_F(MSG_MESH_VIEWER)); - #if ENABLED(USE_GRID_MESHVIEWER) - DWINUI::clearMainArea(); - bedLevelTools.viewer_print_value = true; - bedLevelTools.drawBedMesh(-1, 1, 8, 10 + TITLE_HEIGHT); - #else - if (redraw) drawMesh(bedlevel.z_values, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); - else DWINUI::drawBox(1, hmiData.colorBackground, { 89, 305, 99, 38 }); - #endif - if (withsave) { - DWINUI::drawButton(BTN_Save, 26, 305); - DWINUI::drawButton(BTN_Continue, 146, 305); - drawSelectHighlight(hmiFlag.select_flag, 305); - } - else - DWINUI::drawButton(BTN_Continue, 86, 305); - - #if ENABLED(USE_GRID_MESHVIEWER) - bedLevelTools.setMeshViewerStatus(); - #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 MeshViewer::draw(const bool withsave/*=false*/, const bool redraw/*=true*/) { + title.showCaption(GET_TEXT_F(MSG_MESH_VIEWER)); + #if ENABLED(USE_GRID_MESHVIEWER) + DWINUI::clearMainArea(); + bedLevelTools.viewer_print_value = true; + bedLevelTools.drawBedMesh(-1, 1, 8, 10 + TITLE_HEIGHT); + #else + if (redraw) drawMesh(bedlevel.z_values, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); + else DWINUI::drawBox(1, hmiData.colorBackground, { 89, 305, 99, 38 }); + #endif + if (withsave) { + DWINUI::drawButton(BTN_Save, 26, 305); + DWINUI::drawButton(BTN_Continue, 146, 305); + drawSelectHighlight(hmiFlag.select_flag, 305); } + else + DWINUI::drawButton(BTN_Continue, 86, 305); - void drawMeshViewer() { meshViewer.draw(true, meshredraw); } + #if ENABLED(USE_GRID_MESHVIEWER) + bedLevelTools.setMeshViewerStatus(); + #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 onClick_MeshViewer() { if (hmiFlag.select_flag) saveMesh(); hmiReturnScreen(); } +void drawMeshViewer() { meshViewer.draw(true, meshredraw); } - void gotoMeshViewer(const bool redraw) { - meshredraw = redraw; - if (leveling_is_valid()) gotoPopup(drawMeshViewer, onClick_MeshViewer); - else hmiReturnScreen(); - } +void onClick_MeshViewer() { if (hmiFlag.select_flag) saveMesh(); hmiReturnScreen(); } + +void gotoMeshViewer(const bool redraw) { + meshredraw = redraw; + if (leveling_is_valid()) gotoPopup(drawMeshViewer, onClick_MeshViewer); + else hmiReturnScreen(); +} #endif // DWIN_LCD_PROUI && HAS_MESH diff --git a/Marlin/src/lcd/e3v2/proui/plot.cpp b/Marlin/src/lcd/e3v2/proui/plot.cpp index 891da1c27970..92c6c947177b 100644 --- a/Marlin/src/lcd/e3v2/proui/plot.cpp +++ b/Marlin/src/lcd/e3v2/proui/plot.cpp @@ -31,52 +31,52 @@ #if ENABLED(DWIN_LCD_PROUI) - #include "dwin_defines.h" +#include "dwin_defines.h" - #if PROUI_TUNING_GRAPH +#if PROUI_TUNING_GRAPH - #include "dwin.h" - #include "../../marlinui.h" - #include "plot.h" +#include "dwin.h" +#include "../../marlinui.h" +#include "plot.h" - #define Plot_Bg_Color RGB( 1, 12, 8) +#define Plot_Bg_Color RGB( 1, 12, 8) - Plot plot; +Plot plot; - uint16_t graphpoints, r, x2, y2 = 0; - frame_rect_t graphframe = {0}; - float scale = 0; +uint16_t graphpoints, r, x2, y2 = 0; +frame_rect_t graphframe = {0}; +float scale = 0; - void Plot::draw(const frame_rect_t &frame, const_celsius_float_t max, const_float_t ref/*=0*/) { - graphframe = frame; - graphpoints = 0; - scale = frame.h / max; - x2 = frame.x + frame.w - 1; - y2 = frame.y + frame.h - 1; - r = round((y2) - ref * scale); - DWINUI::drawBox(1, Plot_Bg_Color, frame); - for (uint8_t i = 1; i < 4; i++) if (i * 60 < frame.w) dwinDrawVLine(COLOR_LINE, i * 60 + frame.x, frame.y, frame.h); - DWINUI::drawBox(0, COLOR_WHITE, DWINUI::extendFrame(frame, 1)); - dwinDrawHLine(COLOR_RED, frame.x, r, frame.w); - } +void Plot::draw(const frame_rect_t &frame, const_celsius_float_t max, const_float_t ref/*=0*/) { + graphframe = frame; + graphpoints = 0; + scale = frame.h / max; + x2 = frame.x + frame.w - 1; + y2 = frame.y + frame.h - 1; + r = round((y2) - ref * scale); + DWINUI::drawBox(1, Plot_Bg_Color, frame); + for (uint8_t i = 1; i < 4; i++) if (i * 60 < frame.w) dwinDrawVLine(COLOR_LINE, i * 60 + frame.x, frame.y, frame.h); + DWINUI::drawBox(0, COLOR_WHITE, DWINUI::extendFrame(frame, 1)); + dwinDrawHLine(COLOR_RED, frame.x, r, frame.w); +} - void Plot::update(const_float_t value) { - if (!scale) return; - const uint16_t y = round((y2) - value * scale); - if (graphpoints < graphframe.w) { - dwinDrawPoint(COLOR_YELLOW, 1, 1, graphpoints + graphframe.x, y); - } - else { - dwinFrameAreaMove(1, 0, 1, Plot_Bg_Color, graphframe.x, graphframe.y, x2, y2); - if ((graphpoints % 60) == 0) dwinDrawVLine(COLOR_LINE, x2 - 1, graphframe.y + 1, graphframe.h - 2); - dwinDrawPoint(COLOR_RED, 1, 1, x2 - 1, r); - dwinDrawPoint(COLOR_YELLOW, 1, 1, x2 - 1, y); - } - graphpoints++; - #if LCD_BACKLIGHT_TIMEOUT_MINS - ui.refresh_backlight_timeout(); - #endif - } +void Plot::update(const_float_t value) { + if (!scale) return; + const uint16_t y = round((y2) - value * scale); + if (graphpoints < graphframe.w) { + dwinDrawPoint(COLOR_YELLOW, 1, 1, graphpoints + graphframe.x, y); + } + else { + dwinFrameAreaMove(1, 0, 1, Plot_Bg_Color, graphframe.x, graphframe.y, x2, y2); + if ((graphpoints % 60) == 0) dwinDrawVLine(COLOR_LINE, x2 - 1, graphframe.y + 1, graphframe.h - 2); + dwinDrawPoint(COLOR_RED, 1, 1, x2 - 1, r); + dwinDrawPoint(COLOR_YELLOW, 1, 1, x2 - 1, y); + } + graphpoints++; + #if LCD_BACKLIGHT_TIMEOUT_MINS + ui.refresh_backlight_timeout(); + #endif +} - #endif // PROUI_TUNING_GRAPH +#endif // PROUI_TUNING_GRAPH #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/printstats.cpp b/Marlin/src/lcd/e3v2/proui/printstats.cpp index 399ae034dcc0..732e80542d16 100644 --- a/Marlin/src/lcd/e3v2/proui/printstats.cpp +++ b/Marlin/src/lcd/e3v2/proui/printstats.cpp @@ -31,52 +31,52 @@ #if ALL(DWIN_LCD_PROUI, PRINTCOUNTER) - #include "printstats.h" +#include "printstats.h" - #include "../../../core/types.h" - #include "../../../MarlinCore.h" - #include "../../marlinui.h" - #include "../../../module/printcounter.h" - #include "dwin.h" - #include "dwin_popup.h" +#include "../../../core/types.h" +#include "../../../MarlinCore.h" +#include "../../marlinui.h" +#include "../../../module/printcounter.h" +#include "dwin.h" +#include "dwin_popup.h" - PrintStats printStats; +PrintStats printStats; - void PrintStats::draw() { - char str[30] = ""; - constexpr int8_t MRG = 30; +void PrintStats::draw() { + char str[30] = ""; + constexpr int8_t MRG = 30; - title.showCaption(GET_TEXT_F(MSG_INFO_STATS_MENU)); - DWINUI::clearMainArea(); - drawPopupBkgd(); - DWINUI::drawButton(BTN_Continue, 86, 250); - printStatistics ps = print_job_timer.getStats(); + title.showCaption(GET_TEXT_F(MSG_INFO_STATS_MENU)); + DWINUI::clearMainArea(); + drawPopupBkgd(); + DWINUI::drawButton(BTN_Continue, 86, 250); + printStatistics ps = print_job_timer.getStats(); - DWINUI::drawString(MRG, 80, TS(GET_TEXT_F(MSG_INFO_PRINT_COUNT), F(": "), ps.totalPrints)); - DWINUI::drawString(MRG, 100, TS(GET_TEXT_F(MSG_INFO_COMPLETED_PRINTS), F(": "), ps.finishedPrints)); - duration_t(print_job_timer.getStats().printTime).toDigital(str, true); - DWINUI::drawString(MRG, 120, MString<50>(GET_TEXT_F(MSG_INFO_PRINT_TIME), F(": "), str)); - duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true); - DWINUI::drawString(MRG, 140, MString<50>(GET_TEXT(MSG_INFO_PRINT_LONGEST), F(": "), str)); - DWINUI::drawString(MRG, 160, TS(GET_TEXT_F(MSG_INFO_PRINT_FILAMENT), F(": "), p_float_t(ps.filamentUsed / 1000, 2), F(" m"))); - } + DWINUI::drawString(MRG, 80, TS(GET_TEXT_F(MSG_INFO_PRINT_COUNT), F(": "), ps.totalPrints)); + DWINUI::drawString(MRG, 100, TS(GET_TEXT_F(MSG_INFO_COMPLETED_PRINTS), F(": "), ps.finishedPrints)); + duration_t(print_job_timer.getStats().printTime).toDigital(str, true); + DWINUI::drawString(MRG, 120, MString<50>(GET_TEXT_F(MSG_INFO_PRINT_TIME), F(": "), str)); + duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true); + DWINUI::drawString(MRG, 140, MString<50>(GET_TEXT(MSG_INFO_PRINT_LONGEST), F(": "), str)); + DWINUI::drawString(MRG, 160, TS(GET_TEXT_F(MSG_INFO_PRINT_FILAMENT), F(": "), p_float_t(ps.filamentUsed / 1000, 2), F(" m"))); +} - void PrintStats::reset() { - print_job_timer.initStats(); - DONE_BUZZ(true); - } +void PrintStats::reset() { + print_job_timer.initStats(); + DONE_BUZZ(true); +} - void gotoPrintStats() { - printStats.draw(); - hmiSaveProcessID(ID_WaitResponse); - } +void gotoPrintStats() { + printStats.draw(); + hmiSaveProcessID(ID_WaitResponse); +} - // Print Stats Reset popup - void popupResetStats() { dwinPopupConfirmCancel(ICON_Info_0, GET_TEXT_F(MSG_RESET_STATS)); } - void onClickResetStats() { - if (hmiFlag.select_flag) printStats.reset(); - hmiReturnScreen(); - } - void printStatsReset() { gotoPopup(popupResetStats, onClickResetStats); } +// Print Stats Reset popup +void popupResetStats() { dwinPopupConfirmCancel(ICON_Info_0, GET_TEXT_F(MSG_RESET_STATS)); } +void onClickResetStats() { + if (hmiFlag.select_flag) printStats.reset(); + hmiReturnScreen(); +} +void printStatsReset() { gotoPopup(popupResetStats, onClickResetStats); } #endif // DWIN_LCD_PROUI && PRINTCOUNTER From 758ebab5f34c06d039526b5f37d62ce66598ad19 Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 01:40:43 -0500 Subject: [PATCH 16/20] rename UBL_Z_OFFSET_MIN/MAX to Z_OFFSET_MIN/MAX --- Marlin/src/lcd/e3v2/proui/bedlevel_tools.h | 4 ++-- Marlin/src/lcd/e3v2/proui/dwin.cpp | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h index 7bd236760ae9..4838eb40d9a4 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h @@ -47,8 +47,8 @@ #include "../../../inc/MarlinConfigPre.h" -#define UBL_Z_OFFSET_MIN -3.0 -#define UBL_Z_OFFSET_MAX 3.0 +#define Z_OFFSET_MIN -3.0 +#define Z_OFFSET_MAX 3.0 class BedLevelTools { public: diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 6c18af9248fd..d5883ad348ca 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -3949,9 +3949,6 @@ void drawStepsMenu() { #endif #if ENABLED(PROUI_MESH_EDIT) - #define Z_OFFSET_MIN -3 - #define Z_OFFSET_MAX 3 - void LiveEditMesh() { ((MenuItemPtr*)editZValueItem)->value = &bedlevel.z_values[hmiValue.select ? bedLevelTools.mesh_x : menuData.value][hmiValue.select ? menuData.value : bedLevelTools.mesh_y]; editZValueItem->redraw(); } void applyEditMeshX() { bedLevelTools.mesh_x = menuData.value; } void applyEditMeshY() { bedLevelTools.mesh_y = menuData.value; } From 1b41c4b8c655f944f6f7a6da37b92e618047655b Mon Sep 17 00:00:00 2001 From: classicrocker883 Date: Tue, 21 Nov 2023 01:52:51 -0500 Subject: [PATCH 17/20] forgot indent bedlevel_tools.cpp --- Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp | 398 +++++++++---------- 1 file changed, 199 insertions(+), 199 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp index a9ee754387a9..42aa597dc164 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -48,234 +48,234 @@ #if ALL(DWIN_LCD_PROUI, HAS_LEVELING) -#include "../../marlinui.h" -#include "../../../core/types.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" - -#include "dwin.h" -#include "dwinui.h" -#include "dwin_popup.h" -#include "bedlevel_tools.h" - -BedLevelTools bedLevelTools; - -#if ENABLED(USE_GRID_MESHVIEWER) - bool BedLevelTools::viewer_print_value = false; -#endif -bool BedLevelTools::goto_mesh_value = false; -uint8_t BedLevelTools::mesh_x = 0; -uint8_t BedLevelTools::mesh_y = 0; -uint8_t BedLevelTools::tilt_grid = 1; - -bool drawing_mesh = false; - -#if ENABLED(AUTO_BED_LEVELING_UBL) - - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { - MString cmd; - cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); - if (undefined) cmd += F(" N"); - gcode.process_subcommands_now(cmd); - planner.synchronize(); - } + #include "../../marlinui.h" + #include "../../../core/types.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" + + #include "dwin.h" + #include "dwinui.h" + #include "dwin_popup.h" + #include "bedlevel_tools.h" + + BedLevelTools bedLevelTools; + + #if ENABLED(USE_GRID_MESHVIEWER) + bool BedLevelTools::viewer_print_value = false; + #endif + bool BedLevelTools::goto_mesh_value = false; + uint8_t BedLevelTools::mesh_x = 0; + uint8_t BedLevelTools::mesh_y = 0; + uint8_t BedLevelTools::tilt_grid = 1; + + bool drawing_mesh = false; + + #if ENABLED(AUTO_BED_LEVELING_UBL) + + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { + MString cmd; + cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); + if (undefined) cmd += F(" N"); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } - bool BedLevelTools::createPlaneFromMesh() { - 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]); + bool BedLevelTools::createPlaneFromMesh() { + 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; - } + if (finish_incremental_LSF(&lsf_results)) { + SERIAL_ECHOPGM("Could not complete LSF!"); + return true; + } - bedlevel.set_all_mesh_points_to_value(0); + 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]; + 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_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } - rotation.apply_rotation_xyz(mx, my, mz); + rotation.apply_rotation_xyz(mx, my, mz); - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } + + bedlevel.z_values[i][j] = mz - lsf_results.D; } + return false; + } + + #else - bedlevel.z_values[i][j] = mz - lsf_results.D; + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { + gcode.process_subcommands_now( + TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) + ); + planner.synchronize(); } - return false; - } -#else + #endif + + void BedLevelTools::manualMove(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 { + dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); + hmiSaveProcessID(ID_NothingToDo); + gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); + gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); + 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(); + hmiReturnScreen(); + } + } - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { + // Move / Probe methods. As examples, not yet used. + void BedLevelTools::moveToXYZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, false); + } + void BedLevelTools::moveToXY() { + goto_mesh_value = false; + manualMove(mesh_x, mesh_y, false); + } + void BedLevelTools::moveToZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, true); + } + void BedLevelTools::probeXY() { gcode.process_subcommands_now( - TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) + MString( + F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), + F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), + F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) + ) ); - planner.synchronize(); } -#endif - -void BedLevelTools::manualMove(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(); + void BedLevelTools::meshReset() { + ZERO(bedlevel.z_values); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); } - else { - dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); - hmiSaveProcessID(ID_NothingToDo); - gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); - gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); - 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(); - hmiReturnScreen(); + + // Accessors + float BedLevelTools::getMaxValue() { + float max = -(__FLT_MAX__); + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } + return max; } -} - -// Move / Probe methods. As examples, not yet used. -void BedLevelTools::moveToXYZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, false); -} -void BedLevelTools::moveToXY() { - goto_mesh_value = false; - manualMove(mesh_x, mesh_y, false); -} -void BedLevelTools::moveToZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, true); -} -void BedLevelTools::probeXY() { - gcode.process_subcommands_now( - MString( - F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), - F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), - F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) - ) - ); -} - -void BedLevelTools::meshReset() { - ZERO(bedlevel.z_values); - TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); -} - -// Accessors -float BedLevelTools::getMaxValue() { - float max = -(__FLT_MAX__); - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } - return max; -} - -float BedLevelTools::getMinValue() { - float min = __FLT_MAX__; - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } - return min; -} - -// Return 'true' if mesh is good and within LCD limits -bool BedLevelTools::meshValidate() { - GRID_LOOP(x, y) { - const float v = bedlevel.z_values[x][y]; - if (isnan(v) || !WITHIN(v, UBL_Z_OFFSET_MIN, UBL_Z_OFFSET_MAX)) return false; + + float BedLevelTools::getMinValue() { + float min = __FLT_MAX__; + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } + return min; } - return true; -} - -#if ENABLED(USE_GRID_MESHVIEWER) - - constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - - void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); - - // Clear background from previous selection and select new square - dwinDrawRectangle(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; - dwinDrawRectangle(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 + // Return 'true' if mesh is good and within LCD limits + bool BedLevelTools::meshValidate() { 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; - dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative - (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 - ); + const float v = bedlevel.z_values[x][y]; + if (isnan(v) || !WITHIN(v, Z_OFFSET_MIN, Z_OFFSET_MAX)) return false; + } + return true; + } - safe_delay(10); - LCD_SERIAL.flushTX(); + #if ENABLED(USE_GRID_MESHVIEWER) + + constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); + + void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); + + // Clear background from previous selection and select new square + dwinDrawRectangle(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; + dwinDrawRectangle(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 + 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; + dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative + (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 + ); - // Draw value text on - const uint8_t fs = DWINUI::fontWidth(meshfont); - if (viewer_print_value) { - xy_long_t offset { 0, cell_height_px / 2 - fs }; - if (isnan(bedlevel.z_values[x][y])) { // undefined - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); - } - else { // has value - MString<12> msg; - if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) - msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); - else - msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); - offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; - if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); - } safe_delay(10); LCD_SERIAL.flushTX(); + + // Draw value text on + const uint8_t fs = DWINUI::fontWidth(meshfont); + if (viewer_print_value) { + xy_long_t offset { 0, cell_height_px / 2 - fs }; + if (isnan(bedlevel.z_values[x][y])) { // undefined + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); + } + else { // has value + MString<12> msg; + if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) + msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); + else + msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); + offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; + if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); + } + safe_delay(10); + LCD_SERIAL.flushTX(); + } } } - } - void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead - float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); - if (rmax > 3e+10f) rmax = 0.0000001; - if (rmin > 3e+10f) rmin = 0.0000001; - ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); - drawing_mesh = false; - } + void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead + float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); + if (rmax > 3e+10f) rmax = 0.0000001; + if (rmin > 3e+10f) rmin = 0.0000001; + ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); + drawing_mesh = false; + } -#endif // USE_GRID_MESHVIEWER + #endif // USE_GRID_MESHVIEWER #endif // DWIN_LCD_PROUI && HAS_LEVELING From 41081cc75708e71394bcae53b923bb0e99684016 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 21 Nov 2023 00:58:45 -0600 Subject: [PATCH 18/20] unindent --- Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp | 398 +++++++++---------- 1 file changed, 199 insertions(+), 199 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp index 42aa597dc164..e5e95b9f12d4 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -48,234 +48,234 @@ #if ALL(DWIN_LCD_PROUI, HAS_LEVELING) - #include "../../marlinui.h" - #include "../../../core/types.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" - - #include "dwin.h" - #include "dwinui.h" - #include "dwin_popup.h" - #include "bedlevel_tools.h" - - BedLevelTools bedLevelTools; - - #if ENABLED(USE_GRID_MESHVIEWER) - bool BedLevelTools::viewer_print_value = false; - #endif - bool BedLevelTools::goto_mesh_value = false; - uint8_t BedLevelTools::mesh_x = 0; - uint8_t BedLevelTools::mesh_y = 0; - uint8_t BedLevelTools::tilt_grid = 1; - - bool drawing_mesh = false; - - #if ENABLED(AUTO_BED_LEVELING_UBL) - - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { - MString cmd; - cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); - if (undefined) cmd += F(" N"); - gcode.process_subcommands_now(cmd); - planner.synchronize(); - } - - bool BedLevelTools::createPlaneFromMesh() { - 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]); - } - } +#include "../../marlinui.h" +#include "../../../core/types.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" + +#include "dwin.h" +#include "dwinui.h" +#include "dwin_popup.h" +#include "bedlevel_tools.h" + +BedLevelTools bedLevelTools; + +#if ENABLED(USE_GRID_MESHVIEWER) + bool BedLevelTools::viewer_print_value = false; +#endif +bool BedLevelTools::goto_mesh_value = false; +uint8_t BedLevelTools::mesh_x = 0; +uint8_t BedLevelTools::mesh_y = 0; +uint8_t BedLevelTools::tilt_grid = 1; + +bool drawing_mesh = false; + +#if ENABLED(AUTO_BED_LEVELING_UBL) + + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) { + MString cmd; + cmd.set(F("M421 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)); + if (undefined) cmd += F(" N"); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + } - if (finish_incremental_LSF(&lsf_results)) { - SERIAL_ECHOPGM("Could not complete LSF!"); - return true; + bool BedLevelTools::createPlaneFromMesh() { + 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]); } + } - 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_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + if (finish_incremental_LSF(&lsf_results)) { + SERIAL_ECHOPGM("Could not complete LSF!"); + return true; + } - rotation.apply_rotation_xyz(mx, my, mz); + bedlevel.set_all_mesh_points_to_value(0); - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + 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]; - bedlevel.z_values[i][j] = mz - lsf_results.D; + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); } - return false; - } - #else + rotation.apply_rotation_xyz(mx, my, mz); - void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { - gcode.process_subcommands_now( - TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) - ); - planner.synchronize(); - } - - #endif + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), AS_CHAR(','), p_float_t(my, 7), AS_CHAR(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } - void BedLevelTools::manualMove(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 { - dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); - hmiSaveProcessID(ID_NothingToDo); - gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); - gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); - 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(); - hmiReturnScreen(); + bedlevel.z_values[i][j] = mz - lsf_results.D; } + return false; } - // Move / Probe methods. As examples, not yet used. - void BedLevelTools::moveToXYZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, false); - } - void BedLevelTools::moveToXY() { - goto_mesh_value = false; - manualMove(mesh_x, mesh_y, false); - } - void BedLevelTools::moveToZ() { - goto_mesh_value = true; - manualMove(mesh_x, mesh_y, true); - } - void BedLevelTools::probeXY() { +#else + + void BedLevelTools::manualValueUpdate(const uint8_t mesh_x, const uint8_t mesh_y) { gcode.process_subcommands_now( - MString( - F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), - F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), - F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) - ) + TS(F("G29 I"), mesh_x, 'J', mesh_y, 'Z', p_float_t(current_position.z, 3)) ); + planner.synchronize(); } - void BedLevelTools::meshReset() { - ZERO(bedlevel.z_values); - TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); - } +#endif - // Accessors - float BedLevelTools::getMaxValue() { - float max = -(__FLT_MAX__); - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } - return max; +void BedLevelTools::manualMove(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(); } - - float BedLevelTools::getMinValue() { - float min = __FLT_MAX__; - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } - return min; + else { + dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); + hmiSaveProcessID(ID_NothingToDo); + gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); + gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); + 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(); + hmiReturnScreen(); } - - // Return 'true' if mesh is good and within LCD limits - bool BedLevelTools::meshValidate() { - GRID_LOOP(x, y) { - const float v = bedlevel.z_values[x][y]; - if (isnan(v) || !WITHIN(v, Z_OFFSET_MIN, Z_OFFSET_MAX)) return false; - } - return true; +} + +// Move / Probe methods. As examples, not yet used. +void BedLevelTools::moveToXYZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, false); +} +void BedLevelTools::moveToXY() { + goto_mesh_value = false; + manualMove(mesh_x, mesh_y, false); +} +void BedLevelTools::moveToZ() { + goto_mesh_value = true; + manualMove(mesh_x, mesh_y, true); +} +void BedLevelTools::probeXY() { + gcode.process_subcommands_now( + MString( + F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), + F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), + F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) + ) + ); +} + +void BedLevelTools::meshReset() { + ZERO(bedlevel.z_values); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); +} + +// Accessors +float BedLevelTools::getMaxValue() { + float max = -(__FLT_MAX__); + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } + return max; +} + +float BedLevelTools::getMinValue() { + float min = __FLT_MAX__; + GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } + return min; +} + +// Return 'true' if mesh is good and within LCD limits +bool BedLevelTools::meshValidate() { + GRID_LOOP(x, y) { + const float v = bedlevel.z_values[x][y]; + if (isnan(v) || !WITHIN(v, Z_OFFSET_MIN, Z_OFFSET_MAX)) return false; } + return true; +} + +#if ENABLED(USE_GRID_MESHVIEWER) + + constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); + + void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); + + // Clear background from previous selection and select new square + dwinDrawRectangle(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; + dwinDrawRectangle(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); + } - #if ENABLED(USE_GRID_MESHVIEWER) - - constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - - void BedLevelTools::drawBedMesh(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(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max); - - // Clear background from previous selection and select new square - dwinDrawRectangle(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; - dwinDrawRectangle(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 + 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; + dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative + (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 + ); - // Draw value square grid - 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; - dwinDrawRectangle(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] / rmax) << 11 : // red if mesh point value is negative - (uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 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 + const uint8_t fs = DWINUI::fontWidth(meshfont); + if (viewer_print_value) { + xy_long_t offset { 0, cell_height_px / 2 - fs }; + if (isnan(bedlevel.z_values[x][y])) { // undefined + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); + } + else { // has value + MString<12> msg; + if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) + msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); + else + msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); + offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; + if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); + dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); + } safe_delay(10); LCD_SERIAL.flushTX(); - - // Draw value text on - const uint8_t fs = DWINUI::fontWidth(meshfont); - if (viewer_print_value) { - xy_long_t offset { 0, cell_height_px / 2 - fs }; - if (isnan(bedlevel.z_values[x][y])) { // undefined - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); - } - else { // has value - MString<12> msg; - if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10)) - msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2)); - else - msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100)); - offset.x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; - if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10)) - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset.x, start_y_px + offset.y, F(".")); - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset.x, start_y_px + offset.y, msg); - } - safe_delay(10); - LCD_SERIAL.flushTX(); - } } } + } - void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead - float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); - if (rmax > 3e+10f) rmax = 0.0000001; - if (rmin > 3e+10f) rmin = 0.0000001; - ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); - drawing_mesh = false; - } + void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead + float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max); + if (rmax > 3e+10f) rmax = 0.0000001; + if (rmin > 3e+10f) rmin = 0.0000001; + ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green"))); + drawing_mesh = false; + } - #endif // USE_GRID_MESHVIEWER +#endif // USE_GRID_MESHVIEWER #endif // DWIN_LCD_PROUI && HAS_LEVELING From 86819bbc030f00b7c12005d3cf711809931cf073 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 21 Nov 2023 00:59:48 -0600 Subject: [PATCH 19/20] move to dwin_defines --- Marlin/src/lcd/e3v2/jyersui/dwin.cpp | 2 +- Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp | 2 +- Marlin/src/lcd/e3v2/proui/bedlevel_tools.h | 3 --- Marlin/src/lcd/e3v2/proui/dwin_defines.h | 19 ++++++++++++------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp index e1282f8c9877..cf78bdd7c6a5 100644 --- a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp @@ -389,7 +389,7 @@ class TextScroller { // Draw value text on if (viewer_print_value) { - xy_long_t offset { 0, cell_height_px / 2 - 6 }; + xy_int_t offset { 0, cell_height_px / 2 - 6 }; if (isnan(bedlevel.z_values[x][y])) { // undefined dwinDrawString(false, font6x12, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); } diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp index e5e95b9f12d4..eea4ac97f0cc 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.cpp @@ -247,7 +247,7 @@ bool BedLevelTools::meshValidate() { // Draw value text on const uint8_t fs = DWINUI::fontWidth(meshfont); if (viewer_print_value) { - xy_long_t offset { 0, cell_height_px / 2 - fs }; + xy_int_t offset { 0, cell_height_px / 2 - fs }; if (isnan(bedlevel.z_values[x][y])) { // undefined dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset.y, F("X")); } diff --git a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h index 4838eb40d9a4..6e568e32b51e 100644 --- a/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h +++ b/Marlin/src/lcd/e3v2/proui/bedlevel_tools.h @@ -47,9 +47,6 @@ #include "../../../inc/MarlinConfigPre.h" -#define Z_OFFSET_MIN -3.0 -#define Z_OFFSET_MAX 3.0 - class BedLevelTools { public: #if ENABLED(USE_GRID_MESHVIEWER) diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index 8bf23725c94d..1b987906ae87 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -30,6 +30,14 @@ #include "../../../inc/MarlinConfigPre.h" +#if HAS_MESH + #define PROUI_MESH_EDIT // Add a menu to edit mesh points + #if ENABLED(PROUI_MESH_EDIT) + #define Z_OFFSET_MIN -3.0 // (mm) + #define Z_OFFSET_MAX 3.0 // (mm) + #endif +#endif + #if defined(__STM32F1__) || defined(STM32F1) #define DASH_REDRAW 1 #endif @@ -84,19 +92,16 @@ * ProUI internal feature flags */ #if ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE) - #define PROUI_MEDIASORT // Enable option to sort G-code files + #define PROUI_MEDIASORT // Enable option to sort G-code files #endif #if ENABLED(POWER_LOSS_RECOVERY) - #define PROUI_ITEM_PLR // Tune > Power-loss Recovery + #define PROUI_ITEM_PLR // Tune > Power-loss Recovery #endif #if ENABLED(HAS_JUNCTION_DEVIATION) - #define PROUI_ITEM_JD // Tune > Junction Deviation + #define PROUI_ITEM_JD // Tune > Junction Deviation #endif #if ENABLED(LIN_ADVANCE) - #define PROUI_ITEM_ADVK // Tune > Linear Advance -#endif -#if HAS_MESH - #define PROUI_MESH_EDIT // Add a menu to edit mesh points + #define PROUI_ITEM_ADVK // Tune > Linear Advance #endif #if ANY(PROUI_PID_TUNE, MPC_AUTOTUNE) && DISABLED(DISABLE_TUNING_GRAPH) #define PROUI_TUNING_GRAPH 1 From 43ff6594671a9bcf16dddcb64d47ce55f2252240 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 21 Nov 2023 03:25:21 -0600 Subject: [PATCH 20/20] rgb type, some case fix --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 34 +++++++++++------------- Marlin/src/lcd/e3v2/proui/dwin.h | 19 ++++++++++--- Marlin/src/lcd/e3v2/proui/dwin_popup.cpp | 6 ++--- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 9befc892ff92..a6cc1613ef09 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -985,9 +985,8 @@ void drawPrintFileMenu() { if (card.isMounted()) { if (SET_MENU(fileMenu, MSG_MEDIA_MENU, nr_sd_menu_items() + 1)) { BACK_ITEM(gotoMainMenu); - for (uint8_t i = 0; i < nr_sd_menu_items(); ++i) { + for (uint8_t i = 0; i < nr_sd_menu_items(); ++i) menuItemAdd(onDrawFileName, onClickSDItem); - } } updateMenu(fileMenu); TERN_(DASH_REDRAW, dwinRedrawDash()); @@ -1022,7 +1021,6 @@ void hmiSDCardUpdate() { */ void dwinDrawDashboard() { - dwinDrawRectangle(1, hmiData.colorBackground, 0, STATUS_Y + 21, DWIN_WIDTH, DWIN_HEIGHT - 1); dwinDrawRectangle(1, hmiData.colorSplitLine, 0, 449, DWIN_WIDTH, 451); @@ -1067,7 +1065,7 @@ void dwinDrawDashboard() { void drawInfoMenu() { DWINUI::clearMainArea(); if (hmiIsChinese()) - title.frameCopy(30, 17, 28, 13); // "Info" + title.frameCopy(30, 17, 28, 13); // "Info" else title.showCaption(GET_TEXT_F(MSG_INFO_SCREEN)); drawMenuLine(0, ICON_Back, GET_TEXT_F(MSG_BACK), false, true); @@ -1124,7 +1122,7 @@ void hmiMainMenu() { if (hmiData.mediaAutoMount) { card.mount(); safe_delay(800); - }; + } drawPrintFileMenu(); break; case PAGE_PREPARE: drawPrepareMenu(); break; @@ -2710,7 +2708,7 @@ void onDrawGetColorItem(MenuItem* menuitem, int8_t line) { dwinDrawRectangle(0, hmiData.colorHighlight, ICOX + 1, MBASE(line) - 1 + 1, ICOX + 18, MBASE(line) - 1 + 18); dwinDrawRectangle(1, color, ICOX + 2, MBASE(line) - 1 + 2, ICOX + 17, MBASE(line) - 1 + 17); DWINUI::drawString(LBLX, MBASE(line) - 1, menuitem->caption); - drawMenuIntValue(hmiData.colorBackground, line, 4, hmiValue.Color[i]); + drawMenuIntValue(hmiData.colorBackground, line, 4, hmiValue.color[i]); dwinDrawHLine(hmiData.colorSplitLine, 16, MYPOS(line + 1), 240); } @@ -3665,24 +3663,24 @@ void drawStepsMenu() { void selColor() { menuData.intPtr = (int16_t*)static_cast(currentMenu->selectedItem())->value; - hmiValue.Color[0] = GetRColor(*menuData.intPtr); // Red - hmiValue.Color[1] = GetGColor(*menuData.intPtr); // Green - hmiValue.Color[2] = GetBColor(*menuData.intPtr); // Blue + hmiValue.color.r = GetRColor(*menuData.intPtr); // Red + hmiValue.color.g = GetGColor(*menuData.intPtr); // Green + hmiValue.color.b = GetBColor(*menuData.intPtr); // Blue drawGetColorMenu(); } void liveRGBColor() { - hmiValue.Color[currentMenu->line() - 2] = menuData.value; - uint16_t color = RGB(hmiValue.Color[0], hmiValue.Color[1], hmiValue.Color[2]); + hmiValue.color[currentMenu->line() - 2] = menuData.value; + const uint16_t color = RGB(hmiValue.color.r, hmiValue.color.g, hmiValue.color.b); dwinDrawRectangle(1, color, 20, 315, DWIN_WIDTH - 20, 335); } void setRGBColor() { const uint8_t color = static_cast(currentMenu->selectedItem())->icon; - setIntOnClick(0, (color == 1) ? 63 : 31, hmiValue.Color[color], nullptr, liveRGBColor); + setIntOnClick(0, (color == 1) ? 63 : 31, hmiValue.color[color], nullptr, liveRGBColor); } void dwinApplyColor() { - *menuData.intPtr = RGB(hmiValue.Color[0], hmiValue.Color[1], hmiValue.Color[2]); + *menuData.intPtr = RGB(hmiValue.color.r, hmiValue.color.g, hmiValue.color.b); DWINUI::setColors(hmiData.colorText, hmiData.colorBackground, hmiData.colorStatusBg); drawSelectColorsMenu(); hash_changed = true; @@ -3949,12 +3947,12 @@ void drawStepsMenu() { #endif #if ENABLED(PROUI_MESH_EDIT) - void LiveEditMesh() { ((MenuItemPtr*)editZValueItem)->value = &bedlevel.z_values[hmiValue.select ? bedLevelTools.mesh_x : menuData.value][hmiValue.select ? menuData.value : bedLevelTools.mesh_y]; editZValueItem->redraw(); } + void liveEditMesh() { ((MenuItemPtr*)editZValueItem)->value = &bedlevel.z_values[hmiValue.select ? bedLevelTools.mesh_x : menuData.value][hmiValue.select ? menuData.value : bedLevelTools.mesh_y]; editZValueItem->redraw(); } void applyEditMeshX() { bedLevelTools.mesh_x = menuData.value; } void applyEditMeshY() { bedLevelTools.mesh_y = menuData.value; } - void ResetMesh() { bedLevelTools.meshReset(); LCD_MESSAGE(MSG_MESH_RESET); } - void setEditMeshX() { hmiValue.select = 0; setIntOnClick(0, GRID_MAX_POINTS_X - 1, bedLevelTools.mesh_x, applyEditMeshX, LiveEditMesh); } - void setEditMeshY() { hmiValue.select = 1; setIntOnClick(0, GRID_MAX_POINTS_Y - 1, bedLevelTools.mesh_y, applyEditMeshY, LiveEditMesh); } + void resetMesh() { bedLevelTools.meshReset(); LCD_MESSAGE(MSG_MESH_RESET); } + void setEditMeshX() { hmiValue.select = 0; setIntOnClick(0, GRID_MAX_POINTS_X - 1, bedLevelTools.mesh_x, applyEditMeshX, liveEditMesh); } + void setEditMeshY() { hmiValue.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 @@ -4023,7 +4021,7 @@ void drawStepsMenu() { MENU_ITEM(ICON_UBLSmartFill, MSG_UBL_SMART_FILLIN, onDrawMenuItem, ublSmartFillMesh); #endif #if ENABLED(PROUI_MESH_EDIT) - MENU_ITEM(ICON_MeshReset, MSG_MESH_RESET, onDrawMenuItem, ResetMesh); + MENU_ITEM(ICON_MeshReset, MSG_MESH_RESET, onDrawMenuItem, resetMesh); MENU_ITEM(ICON_MeshEdit, MSG_EDIT_MESH, onDrawSubMenu, drawEditMeshMenu); #endif MENU_ITEM(ICON_MeshViewer, MSG_MESH_VIEW, onDrawSubMenu, dwinMeshViewer); diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index 26b7fec5fda8..cf4f9e264353 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -159,12 +159,25 @@ extern hmi_data_t hmiData; static constexpr size_t eeprom_data_size = sizeof(hmi_data_t); typedef struct { - int8_t Color[3]; // Color components + int8_t r, g, b; + void set(int8_t _r, int8_t _g, int8_t _b) { r = _r; g = _g; b = _b; } + int8_t& operator[](const int i) { + switch (i) { + default: + case 0: return r; + case 1: return g; + case 2: return b; + } + } +} rgb_t; + +typedef struct { + rgb_t color; // Color #if ANY(PROUI_PID_TUNE, MPCTEMP) tempcontrol_t tempControl = AUTOTUNE_DONE; #endif - uint8_t select = 0; // Auxiliary selector variable - AxisEnum axis = X_AXIS; // Axis Select + uint8_t select = 0; // Auxiliary selector variable + AxisEnum axis = X_AXIS; // Axis Select } hmi_value_t; typedef struct { diff --git a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp index 91c3ee98e390..5756b770afbe 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp @@ -41,10 +41,10 @@ popupDrawFunc_t popupDraw = nullptr; popupClickFunc_t popupClick = nullptr; popupChangeFunc_t popupChange = nullptr; -uint16_t HighlightYPos = 280; +uint16_t highlightY = 280; void drawSelectHighlight(const bool sel, const uint16_t ypos) { - HighlightYPos = ypos; + highlightY = ypos; hmiFlag.select_flag = sel; const uint16_t c1 = sel ? hmiData.colorHighlight : hmiData.colorPopupBg, c2 = sel ? hmiData.colorPopupBg : hmiData.colorHighlight; @@ -86,7 +86,7 @@ void hmiPopup() { 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 drawSelectHighlight(change, HighlightYPos); + if (popupChange) popupChange(change); else drawSelectHighlight(change, highlightY); dwinUpdateLCD(); } }