From 325e8323ae855cf02a4dbc5bbbd38698c0799617 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 13 Aug 2025 05:33:23 -0400 Subject: [PATCH 1/8] Add Custom GCODE_MACROS --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 118 +++++++++++++++++++++++++++++ Marlin/src/lcd/e3v2/proui/dwin.h | 15 ++++ 2 files changed, 133 insertions(+) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index cf99a13529ca..0ac65fb43540 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -175,6 +175,10 @@ hmi_value_t hmiValue; hmi_flag_t hmiFlag{0}; hmi_data_t hmiData; +#if ENABLED(GCODE_MACROS) + hmi_macro_t hmiMacro; + const char macroChars[] PROGMEM = " GMABCDEFHIJKLNOPRSTUVWXYZ0123456789.|"; +#endif enum SelectItem : uint8_t { PAGE_PRINT = 0, @@ -286,6 +290,9 @@ Menu *stepsMenu = nullptr; #if HAS_TRINAMIC_CONFIG Menu *trinamicConfigMenu = nullptr; #endif +#if ENABLED(GCODE_MACROS) + Menu *macroMenu = nullptr; +#endif // Updatable menuitems pointers MenuItem *hotendTargetItem = nullptr; @@ -1475,6 +1482,10 @@ void dwinHandleScreen() { #if HAS_LOCKSCREEN case ID_Locked: hmiLockScreen(); break; #endif + #if ENABLED(GCODE_MACROS) + case ID_Macros: hmiMacroEditor(); break; + #endif + TERN_(HAS_ESDIAG, case ID_ESDiagProcess:) TERN_(PROUI_ITEM_PLOT, case ID_PlotProcess:) case ID_PrintDone: @@ -3131,6 +3142,109 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { #endif +#if ENABLED(GCODE_MACROS) + + void drawMacroEditor() { + DWINUI::drawString(10, 100, hmiMacro.edit_buffer); + // Calculate cursor position once + const uint16_t cursor_pos = 10 + hmiMacro.cursor_pos * 8; + DWINUI::drawChar(hmiData.colorCursor, cursor_pos, 120, macroChars[hmiMacro.char_index]); + DWINUI::drawBox(1, hmiData.colorCursor, {cursor_pos, 120, 18, 16}); + TERN_(DASH_REDRAW, dwinRedrawDash();) + } + + void hmiMacroEditor() { + static millis_t last_enter_press_ms = 0; + static bool awaiting_second_press = false; + const millis_t DOUBLE_PRESS_WINDOW_MS = 500; // 500ms window for a double press + + EncoderState state = get_encoder_state(); + if (state == ENCODER_DIFF_CW) { + hmiMacro.char_index = (hmiMacro.char_index + 1) % (sizeof(macroChars) - 1); + } + else if (state == ENCODER_DIFF_CCW) { + hmiMacro.char_index = (hmiMacro.char_index == 0 ? sizeof(macroChars) - 2 : hmiMacro.char_index - 1); + } + else if (state == ENCODER_DIFF_ENTER) { + millis_t current_ms = millis(); + // Check if a second press occurred within the time window + if (awaiting_second_press && (current_ms - last_enter_press_ms < DOUBLE_PRESS_WINDOW_MS)) { + // This is a double press: finish early + hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; + char cmd[80]; + sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); + gcode.process_subcommands_now(cmd); + #if ENABLED(EEPROM_SETTINGS) + gcode.process_subcommands_now(F("M500")); + #endif + awaiting_second_press = false; + hmiReturnScreen(); + return; + } + else { + awaiting_second_press = true; + last_enter_press_ms = current_ms; + // Proceed with the single-press action + hmiMacro.edit_buffer[hmiMacro.cursor_pos] = macroChars[hmiMacro.char_index]; + hmiMacro.cursor_pos++; + hmiMacro.char_index = 0; // Reset character index after insertion + } + } + // Timeout logic: if a second press is awaited and the time window has passed, + // we treat the first press as a single press and reset the state. + if (awaiting_second_press && (millis() - last_enter_press_ms >= DOUBLE_PRESS_WINDOW_MS)) { + awaiting_second_press = false; + } + + if (hmiMacro.cursor_pos >= GCODE_MACROS_SLOT_SIZE) { + hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; + char cmd[80]; + sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); + gcode.process_subcommands_now(cmd); + #if ENABLED(EEPROM_SETTINGS) + gcode.process_subcommands_now(F("M500")); + #endif + hmiReturnScreen(); + return; + } + drawMacroEditor(); + } + + void runMacro(uint8_t slot) { + char cmd[8]; + sprintf(cmd, "M81%u", slot); + gcode.process_subcommands_now(cmd); + } + + void editMacro(uint8_t slot) { + DWINUI::clearMainArea(); + char macro_title[20]; + sprintf(macro_title, "Edit M81%u", hmiMacro.slot_edit); + title.showCaption(macro_title); + DWINUI::drawString(10, 80, F("Macro:")); + hmiMacro.slot_edit = slot; + hmiMacro.cursor_pos = 0; + hmiMacro.char_index = 0; + memset(hmiMacro.edit_buffer, 0, sizeof(hmiMacro.edit_buffer)); + // HMI_SaveProcessID(ID_Macros); + checkkey = ID_Macros; + drawMacroEditor(); + } + + void drawMacroMenu() { + checkkey = ID_Menu; + if (SET_MENU_F(macroMenu, "Custom Macros", (GCODE_MACROS_SLOTS * 2) + 1)) { + BACK_ITEM(drawControlMenu); + #define _ITEM_MACRO(N) \ + MENU_ITEM_F(ICON_File, "Run M81"#N, onDrawMenuItem, []{ (void)runMacro(N); }); \ + MENU_ITEM_F(ICON_Info, "Edit M81"#N, onDrawMenuItem, []{ (void)editMacro(N); }); + REPEAT(GCODE_MACROS_SLOTS, _ITEM_MACRO); + } + updateMenu(macroMenu); + } + +#endif + // Menu Creation and Drawing functions ====================================================== frame_rect_t selrect(frame_rect_t) { @@ -3224,11 +3338,15 @@ void drawControlMenu() { constexpr uint8_t items = (3 + COUNT_ENABLED(CASE_LIGHT_MENU, LED_CONTROL_MENU) + TERN0(EEPROM_SETTINGS, 3) + + ENABLED(GCODE_MACROS) + 2 ); checkkey = ID_Menu; if (SET_MENU_R(controlMenu, selrect({103, 1, 28, 14}), MSG_CONTROL, items)) { BACK_ITEM(gotoMainMenu); + #if ENABLED(GCODE_MACROS) + MENU_ITEM_F(ICON_WriteEEPROM, "Custom Macros", onDrawSubMenu, drawMacroMenu); + #endif MENU_ITEM(ICON_Temperature, MSG_TEMPERATURE, onDrawTempSubMenu, drawTemperatureMenu); MENU_ITEM(ICON_Motion, MSG_MOTION, onDrawMotionSubMenu, drawMotionMenu); #if ENABLED(CASE_LIGHT_MENU) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index b6534a617b2f..622363b7e419 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -69,6 +69,7 @@ enum processID : uint8_t { ID_PIDProcess, ID_PlotProcess, ID_MPCProcess, + ID_Macros, ID_NothingToDo }; @@ -195,6 +196,17 @@ typedef struct { extern hmi_value_t hmiValue; +#if ENABLED(GCODE_MACROS) + typedef struct { + uint8_t slot_edit = 0; + uint8_t cursor_pos = 0; + uint8_t char_index = 0; + char edit_buffer[GCODE_MACROS_SLOT_SIZE + 1] = { 0 }; + } hmi_macro_t; + + extern hmi_macro_t hmiMacro; +#endif + typedef struct { uint8_t language; bool printing_flag:1; // sd or host printing @@ -387,6 +399,9 @@ void drawMaxAccelMenu(); #if HAS_TRINAMIC_CONFIG void drawTrinamicConfigMenu(); #endif +#if ENABLED(GCODE_MACROS) + void hmiMacroEditor(); +#endif // Custom colors editing #if HAS_CUSTOM_COLORS From f939ca5af5965f4271c4530a97be6634953705b8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 13 Aug 2025 06:00:04 -0400 Subject: [PATCH 2/8] update comments --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 7 ++++--- Marlin/src/lcd/e3v2/proui/dwin.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 0ac65fb43540..091ae54023f6 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -3156,7 +3156,7 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { void hmiMacroEditor() { static millis_t last_enter_press_ms = 0; static bool awaiting_second_press = false; - const millis_t DOUBLE_PRESS_WINDOW_MS = 500; // 500ms window for a double press + const millis_t DOUBLE_PRESS_WINDOW_MS = 500; // 500ms window double press EncoderState state = get_encoder_state(); if (state == ENCODER_DIFF_CW) { @@ -3167,9 +3167,9 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { } else if (state == ENCODER_DIFF_ENTER) { millis_t current_ms = millis(); - // Check if a second press occurred within the time window + // Check if a second press occurred if (awaiting_second_press && (current_ms - last_enter_press_ms < DOUBLE_PRESS_WINDOW_MS)) { - // This is a double press: finish early + // If double press, finish early hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; char cmd[80]; sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); @@ -3190,6 +3190,7 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { hmiMacro.char_index = 0; // Reset character index after insertion } } + // Timeout logic: if a second press is awaited and the time window has passed, // we treat the first press as a single press and reset the state. if (awaiting_second_press && (millis() - last_enter_press_ms >= DOUBLE_PRESS_WINDOW_MS)) { diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index 622363b7e419..84ff26cf2276 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -198,7 +198,7 @@ extern hmi_value_t hmiValue; #if ENABLED(GCODE_MACROS) typedef struct { - uint8_t slot_edit = 0; + uint8_t slot_edit = 0; uint8_t cursor_pos = 0; uint8_t char_index = 0; char edit_buffer[GCODE_MACROS_SLOT_SIZE + 1] = { 0 }; From c0a9c9bbed52851225201879161ca4040bc5fb7e Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 14 Aug 2025 00:29:51 -0400 Subject: [PATCH 3/8] update variables --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 091ae54023f6..ea906c7057d4 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -177,7 +177,7 @@ hmi_flag_t hmiFlag{0}; hmi_data_t hmiData; #if ENABLED(GCODE_MACROS) hmi_macro_t hmiMacro; - const char macroChars[] PROGMEM = " GMABCDEFHIJKLNOPRSTUVWXYZ0123456789.|"; + static const char macroChars[] PROGMEM = " GMABCDEFHIJKLNOPQRSTUVWXYZ0123456789.|"; #endif enum SelectItem : uint8_t { @@ -3156,7 +3156,6 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { void hmiMacroEditor() { static millis_t last_enter_press_ms = 0; static bool awaiting_second_press = false; - const millis_t DOUBLE_PRESS_WINDOW_MS = 500; // 500ms window double press EncoderState state = get_encoder_state(); if (state == ENCODER_DIFF_CW) { @@ -3168,7 +3167,7 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { else if (state == ENCODER_DIFF_ENTER) { millis_t current_ms = millis(); // Check if a second press occurred - if (awaiting_second_press && (current_ms - last_enter_press_ms < DOUBLE_PRESS_WINDOW_MS)) { + if (awaiting_second_press && (current_ms - last_enter_press_ms < DWIN_VAR_UPDATE_INTERVAL)) { // If double press, finish early hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; char cmd[80]; @@ -3193,7 +3192,7 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { // Timeout logic: if a second press is awaited and the time window has passed, // we treat the first press as a single press and reset the state. - if (awaiting_second_press && (millis() - last_enter_press_ms >= DOUBLE_PRESS_WINDOW_MS)) { + if (awaiting_second_press && (millis() - last_enter_press_ms >= DWIN_VAR_UPDATE_INTERVAL)) { awaiting_second_press = false; } From e939d0c60cec3015846b58704e21fe9577172d01 Mon Sep 17 00:00:00 2001 From: Andrew <18502096+classicrocker883@users.noreply.github.com> Date: Mon, 1 Sep 2025 00:09:36 -0400 Subject: [PATCH 4/8] Update dwin.cpp macroChars arrange --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index a2ba11b173fb..bf196bcf8493 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -177,7 +177,7 @@ hmi_flag_t hmiFlag{0}; hmi_data_t hmiData; #if ENABLED(GCODE_MACROS) hmi_macro_t hmiMacro; - static const char macroChars[] PROGMEM = " GMABCDEFHIJKLNOPQRSTUVWXYZ0123456789.|"; + static const char macroChars[] PROGMEM = " GM0123456789.XYZABCDEFHIJKLNOPQRSTUVW|"; #endif enum SelectItem : uint8_t { From 391f73cf9e42e689971014b8a01cbdeee760700b Mon Sep 17 00:00:00 2001 From: Andrew <18502096+classicrocker883@users.noreply.github.com> Date: Mon, 1 Sep 2025 01:56:52 -0400 Subject: [PATCH 5/8] Update dwin.cpp gcode macros --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index bf196bcf8493..e84130acc833 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -3150,12 +3150,14 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { const uint16_t cursor_pos = 10 + hmiMacro.cursor_pos * 8; DWINUI::drawChar(hmiData.colorCursor, cursor_pos, 120, macroChars[hmiMacro.char_index]); DWINUI::drawBox(1, hmiData.colorCursor, {cursor_pos, 120, 18, 16}); + dwinUpdateLCD(); TERN_(DASH_REDRAW, dwinRedrawDash();) } void hmiMacroEditor() { static millis_t last_enter_press_ms = 0; static bool awaiting_second_press = false; + Draw_MacroEditor(); EncoderState state = get_encoder_state(); if (state == ENCODER_DIFF_CW) { @@ -3207,7 +3209,8 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { hmiReturnScreen(); return; } - drawMacroEditor(); + dwinUpdateLCD(); + TERN_(DASH_REDRAW, dwinRedrawDash();) } void runMacro(uint8_t slot) { @@ -3218,16 +3221,16 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { void editMacro(uint8_t slot) { DWINUI::clearMainArea(); - char macro_title[20]; - sprintf(macro_title, "Edit M81%u", hmiMacro.slot_edit); - title.showCaption(macro_title); + char title[20]; + sprintf(title, "Edit M81%u", hmiMacro.slot_edit); + title.showCaption(title); DWINUI::drawString(10, 80, F("Macro:")); hmiMacro.slot_edit = slot; hmiMacro.cursor_pos = 0; hmiMacro.char_index = 0; memset(hmiMacro.edit_buffer, 0, sizeof(hmiMacro.edit_buffer)); - // HMI_SaveProcessID(ID_Macros); - checkkey = ID_Macros; + HMI_SaveProcessID(ID_Macros); + //checkkey = ID_Macros; drawMacroEditor(); } From 853e33116a04077e793e39334b83b3f6e8a82bcb Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 15 Sep 2025 05:32:16 -0400 Subject: [PATCH 6/8] couple typo fixes --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index e84130acc833..ad19ace5fba7 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -3157,7 +3157,7 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { void hmiMacroEditor() { static millis_t last_enter_press_ms = 0; static bool awaiting_second_press = false; - Draw_MacroEditor(); + drawMacroEditor(); EncoderState state = get_encoder_state(); if (state == ENCODER_DIFF_CW) { @@ -3221,15 +3221,15 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { void editMacro(uint8_t slot) { DWINUI::clearMainArea(); - char title[20]; - sprintf(title, "Edit M81%u", hmiMacro.slot_edit); - title.showCaption(title); + char draw_title[20]; + sprintf(draw_title, "Edit M81%u", hmiMacro.slot_edit); + title.showCaption(draw_title); DWINUI::drawString(10, 80, F("Macro:")); hmiMacro.slot_edit = slot; hmiMacro.cursor_pos = 0; hmiMacro.char_index = 0; memset(hmiMacro.edit_buffer, 0, sizeof(hmiMacro.edit_buffer)); - HMI_SaveProcessID(ID_Macros); + hmiSaveProcessID(ID_Macros); //checkkey = ID_Macros; drawMacroEditor(); } From 56cb68b6e2bf88c46081225a75933e12f377e3ad Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 19 Sep 2025 23:54:46 -0400 Subject: [PATCH 7/8] final update - tested and working --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 107 ++++++++++++++--------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index ad19ace5fba7..e38892d6c2ba 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -3147,49 +3147,53 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { void drawMacroEditor() { DWINUI::drawString(10, 100, hmiMacro.edit_buffer); // Calculate cursor position once - const uint16_t cursor_pos = 10 + hmiMacro.cursor_pos * 8; - DWINUI::drawChar(hmiData.colorCursor, cursor_pos, 120, macroChars[hmiMacro.char_index]); - DWINUI::drawBox(1, hmiData.colorCursor, {cursor_pos, 120, 18, 16}); - dwinUpdateLCD(); - TERN_(DASH_REDRAW, dwinRedrawDash();) + const uint16_t cursor_pos = 10 + hmiMacro.cursor_pos * DWINUI::fontWidth(); + DWINUI::drawBox(1, hmiData.colorBackground, {10, 120, uint16_t(1 + cursor_pos), DWINUI::fontHeight()}); + DWINUI::drawChar(hmiData.colorAlertTxt, cursor_pos, 120, macroChars[hmiMacro.char_index]); + DWINUI::drawBox(1, hmiData.colorCursor, {cursor_pos, uint16_t(120 + DWINUI::fontHeight()), uint16_t(1 + DWINUI::fontWidth()), DWINUI::fontHeight()}); } - void hmiMacroEditor() { + void macroEncoder(EncoderState encoder_diffState) { static millis_t last_enter_press_ms = 0; static bool awaiting_second_press = false; - drawMacroEditor(); - EncoderState state = get_encoder_state(); - if (state == ENCODER_DIFF_CW) { - hmiMacro.char_index = (hmiMacro.char_index + 1) % (sizeof(macroChars) - 1); - } - else if (state == ENCODER_DIFF_CCW) { - hmiMacro.char_index = (hmiMacro.char_index == 0 ? sizeof(macroChars) - 2 : hmiMacro.char_index - 1); - } - else if (state == ENCODER_DIFF_ENTER) { - millis_t current_ms = millis(); - // Check if a second press occurred - if (awaiting_second_press && (current_ms - last_enter_press_ms < DWIN_VAR_UPDATE_INTERVAL)) { - // If double press, finish early - hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; - char cmd[80]; - sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); - gcode.process_subcommands_now(cmd); - #if ENABLED(EEPROM_SETTINGS) - gcode.process_subcommands_now(F("M500")); - #endif - awaiting_second_press = false; - hmiReturnScreen(); - return; - } - else { - awaiting_second_press = true; - last_enter_press_ms = current_ms; - // Proceed with the single-press action - hmiMacro.edit_buffer[hmiMacro.cursor_pos] = macroChars[hmiMacro.char_index]; - hmiMacro.cursor_pos++; - hmiMacro.char_index = 0; // Reset character index after insertion + switch (encoder_diffState) { + case ENCODER_DIFF_CW: + hmiMacro.char_index = (hmiMacro.char_index + 1) % (sizeof(macroChars) - 1); + break; + case ENCODER_DIFF_CCW: + hmiMacro.char_index = (hmiMacro.char_index == 0 ? sizeof(macroChars) - 2 : hmiMacro.char_index - 1); + break; + case ENCODER_DIFF_ENTER: { + millis_t current_ms = millis(); + // Check if a second press occurred + if (awaiting_second_press && (current_ms - last_enter_press_ms < DWIN_VAR_UPDATE_INTERVAL)) { + // If double press, finish early + hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; + char cmd[80]; + sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); + gcode.process_subcommands_now(cmd); + #if ENABLED(EEPROM_SETTINGS) + gcode.process_subcommands_now(F("M500")); + #endif + awaiting_second_press = false; + DWINUI::clearMainArea(); + hmiReturnScreen(); + ReDrawMenu(); + return; + } + else { + awaiting_second_press = true; + last_enter_press_ms = current_ms; + // Proceed with the single-press action + hmiMacro.edit_buffer[hmiMacro.cursor_pos] = macroChars[hmiMacro.char_index]; + hmiMacro.cursor_pos++; + hmiMacro.char_index = 0; // Reset character index after insertion + } } + break; + default: + break; } // Timeout logic: if a second press is awaited and the time window has passed, @@ -3198,17 +3202,13 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { awaiting_second_press = false; } - if (hmiMacro.cursor_pos >= GCODE_MACROS_SLOT_SIZE) { - hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; - char cmd[80]; - sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); - gcode.process_subcommands_now(cmd); - #if ENABLED(EEPROM_SETTINGS) - gcode.process_subcommands_now(F("M500")); - #endif - hmiReturnScreen(); - return; - } + drawMacroEditor(); + } + + void hmiMacroEditor() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + macroEncoder(encoder_diffState); dwinUpdateLCD(); TERN_(DASH_REDRAW, dwinRedrawDash();) } @@ -3220,17 +3220,16 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { } void editMacro(uint8_t slot) { - DWINUI::clearMainArea(); - char draw_title[20]; - sprintf(draw_title, "Edit M81%u", hmiMacro.slot_edit); - title.showCaption(draw_title); - DWINUI::drawString(10, 80, F("Macro:")); hmiMacro.slot_edit = slot; hmiMacro.cursor_pos = 0; hmiMacro.char_index = 0; memset(hmiMacro.edit_buffer, 0, sizeof(hmiMacro.edit_buffer)); hmiSaveProcessID(ID_Macros); - //checkkey = ID_Macros; + char draw_title[20]; + sprintf(draw_title, "Edit M81%u", hmiMacro.slot_edit); + title.showCaption(draw_title); + DWINUI::clearMainArea(); + DWINUI::drawString(10, 80, F("Macro:")); drawMacroEditor(); } From bd054277ef1ee51603d3d361d1e21d1be5c20370 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sat, 20 Sep 2025 02:21:26 -0400 Subject: [PATCH 8/8] add M820-sih --- Marlin/src/lcd/e3v2/proui/dwin.cpp | 43 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index e38892d6c2ba..d14e6d3680d6 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -178,6 +178,8 @@ hmi_data_t hmiData; #if ENABLED(GCODE_MACROS) hmi_macro_t hmiMacro; static const char macroChars[] PROGMEM = " GM0123456789.XYZABCDEFHIJKLNOPQRSTUVW|"; + char hmi_macro_data[GCODE_MACROS_SLOTS][GCODE_MACROS_SLOT_SIZE + 1] = {}; + char run_labels[GCODE_MACROS_SLOTS][GCODE_MACROS_SLOT_SIZE + 20] = {}; #endif enum SelectItem : uint8_t { @@ -3154,9 +3156,6 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { } void macroEncoder(EncoderState encoder_diffState) { - static millis_t last_enter_press_ms = 0; - static bool awaiting_second_press = false; - switch (encoder_diffState) { case ENCODER_DIFF_CW: hmiMacro.char_index = (hmiMacro.char_index + 1) % (sizeof(macroChars) - 1); @@ -3165,30 +3164,33 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { hmiMacro.char_index = (hmiMacro.char_index == 0 ? sizeof(macroChars) - 2 : hmiMacro.char_index - 1); break; case ENCODER_DIFF_ENTER: { - millis_t current_ms = millis(); - // Check if a second press occurred - if (awaiting_second_press && (current_ms - last_enter_press_ms < DWIN_VAR_UPDATE_INTERVAL)) { - // If double press, finish early + char selectedChar = macroChars[hmiMacro.char_index]; + + // Check if the selected character is the end-and-save character. + if (selectedChar == '=') { hmiMacro.edit_buffer[hmiMacro.cursor_pos] = '\0'; + + // Build and process the G-code command. char cmd[80]; sprintf(cmd, "M81%u %s", hmiMacro.slot_edit, hmiMacro.edit_buffer); gcode.process_subcommands_now(cmd); #if ENABLED(EEPROM_SETTINGS) gcode.process_subcommands_now(F("M500")); #endif - awaiting_second_press = false; + + // Copy the edited buffer to the permanent storage array. + memcpy(hmi_macro_data[hmiMacro.slot_edit], hmiMacro.edit_buffer, sizeof(hmiMacro.edit_buffer)); + + // UI updates and return. DWINUI::clearMainArea(); hmiReturnScreen(); ReDrawMenu(); return; } else { - awaiting_second_press = true; - last_enter_press_ms = current_ms; - // Proceed with the single-press action - hmiMacro.edit_buffer[hmiMacro.cursor_pos] = macroChars[hmiMacro.char_index]; + hmiMacro.edit_buffer[hmiMacro.cursor_pos] = selectedChar; hmiMacro.cursor_pos++; - hmiMacro.char_index = 0; // Reset character index after insertion + hmiMacro.char_index = 0; // Reset character index for next selection } } break; @@ -3196,12 +3198,6 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { break; } - // Timeout logic: if a second press is awaited and the time window has passed, - // we treat the first press as a single press and reset the state. - if (awaiting_second_press && (millis() - last_enter_press_ms >= DWIN_VAR_UPDATE_INTERVAL)) { - awaiting_second_press = false; - } - drawMacroEditor(); } @@ -3230,6 +3226,7 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { title.showCaption(draw_title); DWINUI::clearMainArea(); DWINUI::drawString(10, 80, F("Macro:")); + DWINUI::drawString(10, 160, F("Select = to save and exit")); drawMacroEditor(); } @@ -3237,6 +3234,14 @@ void onDrawAcc(MenuItem* menuitem, int8_t line) { checkkey = ID_Menu; if (SET_MENU_F(macroMenu, "Custom Macros", (GCODE_MACROS_SLOTS * 2) + 1)) { BACK_ITEM(drawControlMenu); + for (uint8_t i = 0; i < GCODE_MACROS_SLOTS; i++) { + const char* gcode_str = hmi_macro_data[i]; + if (gcode_str[0] != '\0') { + sprintf_P(run_labels[i], PSTR("Run M81%u (%s)"), i, hmi_macro_data[i]); + } else { + sprintf_P(run_labels[i], PSTR("Run M81%u"), i); + } + } #define _ITEM_MACRO(N) \ MENU_ITEM_F(ICON_File, "Run M81"#N, onDrawMenuItem, []{ (void)runMacro(N); }); \ MENU_ITEM_F(ICON_Info, "Edit M81"#N, onDrawMenuItem, []{ (void)editMacro(N); });