diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index bfc39298a210..fea0d51e5f1f 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -2565,10 +2565,15 @@
// - Download https://github.com/makerbase-mks/MKS-H43
// - Copy the downloaded DWIN_SET folder to the SD card.
//
+// RELOADED (T5UID1)
+// - Download https://github.com/Desuuuu/DGUS-reloaded
+// - Copy the downloaded DWIN_SET folder to the SD card.
+//
//#define DGUS_LCD_UI_ORIGIN
//#define DGUS_LCD_UI_FYSETC
//#define DGUS_LCD_UI_HIPRECY
//#define DGUS_LCD_UI_MKS
+//#define DGUS_LCD_UI_RELOADED
#if ENABLED(DGUS_LCD_UI_MKS)
#define USE_MKS_GREEN_UI
#endif
diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 9875422742a8..0715b1f5145c 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -479,6 +479,10 @@
// Aliases for LCD features
#if ANY(DGUS_LCD_UI_ORIGIN, DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY, DGUS_LCD_UI_MKS)
+ #define HAS_DGUS_LCD_CLASSIC 1
+#endif
+
+#if ANY(HAS_DGUS_LCD_CLASSIC, DGUS_LCD_UI_RELOADED)
#define HAS_DGUS_LCD 1
#endif
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 01fdaa3451e2..75df13127ca1 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -2655,7 +2655,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
+ (DISABLED(IS_LEGACY_TFT) && ENABLED(TFT_GENERIC)) \
+ (ENABLED(IS_LEGACY_TFT) && COUNT_ENABLED(TFT_320x240, TFT_320x240_SPI, TFT_480x320, TFT_480x320_SPI)) \
+ COUNT_ENABLED(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, ANYCUBIC_TFT35) \
- + COUNT_ENABLED(DGUS_LCD_UI_ORIGIN, DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY, DGUS_LCD_UI_MKS) \
+ + COUNT_ENABLED(DGUS_LCD_UI_ORIGIN, DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY, DGUS_LCD_UI_MKS, DGUS_LCD_UI_RELOADED) \
+ COUNT_ENABLED(ENDER2_STOCKDISPLAY, CR10_STOCKDISPLAY) \
+ COUNT_ENABLED(DWIN_CREALITY_LCD, DWIN_MARLINUI_PORTRAIT, DWIN_MARLINUI_LANDSCAPE) \
+ COUNT_ENABLED(FYSETC_MINI_12864_X_X, FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0, FYSETC_MINI_12864_2_1, FYSETC_GENERIC_12864_1_1) \
@@ -3798,6 +3798,35 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#endif
#undef _BAD_DRIVER
+/**
+ * Require certain features for DGUS_LCD_UI_RELOADED.
+ */
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+ #if BUFSIZE < 4
+ #error "DGUS_LCD_UI_RELOADED requires a BUFSIZE of at least 4."
+ #elif HOTENDS < 1
+ #error "DGUS_LCD_UI_RELOADED requires at least 1 hotend."
+ #elif EXTRUDERS < 1
+ #error "DGUS_LCD_UI_RELOADED requires at least 1 extruder."
+ #elif !HAS_HEATED_BED
+ #error "DGUS_LCD_UI_RELOADED requires a heated bed."
+ #elif FAN_COUNT < 1
+ #error "DGUS_LCD_UI_RELOADED requires a fan."
+ #elif !HAS_BED_PROBE
+ #error "DGUS_LCD_UI_RELOADED requires a bed probe."
+ #elif !HAS_MESH
+ #error "DGUS_LCD_UI_RELOADED requires mesh leveling."
+ #elif DISABLED(LEVEL_BED_CORNERS)
+ #error "DGUS_LCD_UI_RELOADED requires LEVEL_BED_CORNERS."
+ #elif DISABLED(BABYSTEP_ALWAYS_AVAILABLE)
+ #error "DGUS_LCD_UI_RELOADED requires BABYSTEP_ALWAYS_AVAILABLE."
+ #elif DISABLED(BABYSTEP_ZPROBE_OFFSET)
+ #error "DGUS_LCD_UI_RELOADED requires BABYSTEP_ZPROBE_OFFSET."
+ #elif ENABLED(AUTO_BED_LEVELING_UBL) && DISABLED(UBL_SAVE_ACTIVE_ON_M500)
+ #warning "Without UBL_SAVE_ACTIVE_ON_M500, your mesh will not be saved when using the touchscreen."
+ #endif
+#endif
+
// Misc. Cleanup
#undef _TEST_PWM
#undef _LINEAR_AXES_STR
diff --git a/Marlin/src/lcd/extui/dgus/DGUSDisplay.cpp b/Marlin/src/lcd/extui/dgus/DGUSDisplay.cpp
index c2390d63a661..535bc965912f 100644
--- a/Marlin/src/lcd/extui/dgus/DGUSDisplay.cpp
+++ b/Marlin/src/lcd/extui/dgus/DGUSDisplay.cpp
@@ -22,7 +22,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_DGUS_LCD
+#if HAS_DGUS_LCD_CLASSIC
#if HOTENDS > 2
#warning "More than 2 hotends not implemented on DGUS Display UI."
@@ -268,4 +268,4 @@ bool populate_VPVar(const uint16_t VP, DGUS_VP_Variable * const ramcopy) {
return true;
}
-#endif // HAS_DGUS_LCD
+#endif // HAS_DGUS_LCD_CLASSIC
diff --git a/Marlin/src/lcd/extui/dgus/DGUSScreenHandler.cpp b/Marlin/src/lcd/extui/dgus/DGUSScreenHandler.cpp
index 5c108d07092a..9e44cf13318f 100644
--- a/Marlin/src/lcd/extui/dgus/DGUSScreenHandler.cpp
+++ b/Marlin/src/lcd/extui/dgus/DGUSScreenHandler.cpp
@@ -22,7 +22,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_DGUS_LCD
+#if HAS_DGUS_LCD_CLASSIC
#include "DGUSScreenHandler.h"
@@ -772,4 +772,4 @@ void DGUSDisplay::RequestScreen(DGUSLCD_Screens screen) {
WriteVariable(0x84, gotoscreen, sizeof(gotoscreen));
}
-#endif // HAS_DGUS_LCD
+#endif // HAS_DGUS_LCD_CLASSIC
diff --git a/Marlin/src/lcd/extui/dgus/dgus_extui.cpp b/Marlin/src/lcd/extui/dgus/dgus_extui.cpp
index 4b4521c47f96..4f15827a4938 100644
--- a/Marlin/src/lcd/extui/dgus/dgus_extui.cpp
+++ b/Marlin/src/lcd/extui/dgus/dgus_extui.cpp
@@ -26,7 +26,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_DGUS_LCD
+#if HAS_DGUS_LCD_CLASSIC
#include "../ui_api.h"
#include "DGUSDisplay.h"
@@ -159,4 +159,4 @@ namespace ExtUI {
void onSteppersEnabled() {}
}
-#endif // HAS_DGUS_LCD
+#endif // HAS_DGUS_LCD_CLASSIC
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.cpp
new file mode 100644
index 000000000000..e82f63bce108
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.cpp
@@ -0,0 +1,407 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/* DGUS implementation written by coldtobi in 2019 for Marlin */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUSDisplay.h"
+
+#include "config/DGUS_Addr.h"
+#include "config/DGUS_Constants.h"
+#include "definition/DGUS_VPList.h"
+
+#include "../ui_api.h"
+#include "../../../gcode/gcode.h"
+
+long map_precise(float x, long in_min, long in_max, long out_min, long out_max) {
+ return LROUND((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);
+}
+
+uint8_t DGUSDisplay::gui_version = 0;
+uint8_t DGUSDisplay::os_version = 0;
+
+uint8_t DGUSDisplay::volume = 255;
+uint8_t DGUSDisplay::brightness = 100;
+
+DGUSDisplay::rx_datagram_state_t DGUSDisplay::rx_datagram_state = DGUS_IDLE;
+uint8_t DGUSDisplay::rx_datagram_len = 0;
+
+bool DGUSDisplay::initialized = false;
+
+void DGUSDisplay::Loop() {
+ ProcessRx();
+}
+
+void DGUSDisplay::Init() {
+ LCD_SERIAL.begin(LCD_BAUDRATE);
+
+ Read(DGUS_VERSION, 1);
+}
+
+void DGUSDisplay::Read(uint16_t addr, uint8_t size) {
+ WriteHeader(addr, DGUS_READVAR, size);
+
+ LCD_SERIAL.write(size);
+}
+
+void DGUSDisplay::Write(uint16_t addr, const void* data_ptr, uint8_t size) {
+ if (!data_ptr) return;
+
+ WriteHeader(addr, DGUS_WRITEVAR, size);
+
+ const char* data = static_cast(data_ptr);
+
+ while (size--) {
+ LCD_SERIAL.write(*data++);
+ }
+}
+
+void DGUSDisplay::WriteString(uint16_t addr, const void* data_ptr, uint8_t size, bool left, bool right, bool use_space) {
+ if (!data_ptr) return;
+
+ WriteHeader(addr, DGUS_WRITEVAR, size);
+
+ const char* data = static_cast(data_ptr);
+ size_t len = strlen(data);
+ uint8_t left_spaces = 0;
+ uint8_t right_spaces = 0;
+
+ if (len < size) {
+ if (!len) {
+ right_spaces = size;
+ }
+ else if ((left && right) || (!left && !right)) {
+ left_spaces = (size - len) / 2;
+ right_spaces = size - len - left_spaces;
+ }
+ else if (left) {
+ right_spaces = size - len;
+ }
+ else {
+ left_spaces = size - len;
+ }
+ }
+ else {
+ len = size;
+ }
+
+ while (left_spaces--) {
+ LCD_SERIAL.write(' ');
+ }
+ while (len--) {
+ LCD_SERIAL.write(*data++);
+ }
+ while (right_spaces--) {
+ LCD_SERIAL.write(use_space ? ' ' : '\0');
+ }
+}
+
+void DGUSDisplay::WriteStringPGM(uint16_t addr, const void* data_ptr, uint8_t size, bool left, bool right, bool use_space) {
+ if (!data_ptr) return;
+
+ WriteHeader(addr, DGUS_WRITEVAR, size);
+
+ const char* data = static_cast(data_ptr);
+ size_t len = strlen_P(data);
+ uint8_t left_spaces = 0;
+ uint8_t right_spaces = 0;
+
+ if (len < size) {
+ if (!len) {
+ right_spaces = size;
+ }
+ else if ((left && right) || (!left && !right)) {
+ left_spaces = (size - len) / 2;
+ right_spaces = size - len - left_spaces;
+ }
+ else if (left) {
+ right_spaces = size - len;
+ }
+ else {
+ left_spaces = size - len;
+ }
+ }
+ else {
+ len = size;
+ }
+
+ while (left_spaces--) {
+ LCD_SERIAL.write(' ');
+ }
+ while (len--) {
+ LCD_SERIAL.write(pgm_read_byte(data++));
+ }
+ while (right_spaces--) {
+ LCD_SERIAL.write(use_space ? ' ' : '\0');
+ }
+}
+
+void DGUSDisplay::SwitchScreen(DGUS_Screen screen) {
+ DEBUG_ECHOLNPAIR("SwitchScreen ", (uint8_t)screen);
+ const uint8_t command[] = { 0x5A, 0x01, 0x00, (uint8_t)screen };
+ Write(0x84, command, sizeof(command));
+}
+
+void DGUSDisplay::PlaySound(uint8_t start, uint8_t len, uint8_t volume) {
+ if (volume == 0) volume = DGUSDisplay::volume;
+ if (volume == 0) return;
+ DEBUG_ECHOLNPAIR("PlaySound ", start, ":", len, "\nVolume ", volume);
+ const uint8_t command[] = { start, len, volume, 0x00 };
+ Write(0xA0, command, sizeof(command));
+}
+
+void DGUSDisplay::EnableControl(DGUS_Screen screen, DGUS_ControlType type, DGUS_Control control) {
+ DEBUG_ECHOLNPAIR("EnableControl ", (uint8_t)control, "\nScreen ", (uint8_t)screen, "\nType ", (uint8_t)type);
+
+ const uint8_t command[] = { 0x5A, 0xA5, 0x00, (uint8_t)screen, (uint8_t)control, type, 0x00, 0x01 };
+ Write(0xB0, command, sizeof(command));
+
+ FlushTx();
+ delay(50);
+}
+
+void DGUSDisplay::DisableControl(DGUS_Screen screen, DGUS_ControlType type, DGUS_Control control) {
+ DEBUG_ECHOLNPAIR("DisableControl ", (uint8_t)control, "\nScreen ", (uint8_t)screen, "\nType ", (uint8_t)type);
+
+ const uint8_t command[] = { 0x5A, 0xA5, 0x00, (uint8_t)screen, (uint8_t)control, type, 0x00, 0x00 };
+ Write(0xB0, command, sizeof(command));
+
+ FlushTx();
+ delay(50);
+}
+
+uint8_t DGUSDisplay::GetBrightness() {
+ return brightness;
+}
+
+uint8_t DGUSDisplay::GetVolume() {
+ return map_precise(volume, 0, 255, 0, 100);
+}
+
+void DGUSDisplay::SetBrightness(uint8_t new_brightness) {
+ brightness = constrain(new_brightness, 0, 100);
+ new_brightness = map_precise(brightness, 0, 100, 5, 100);
+ DEBUG_ECHOLNPAIR("SetBrightness ", new_brightness);
+ const uint8_t command[] = { new_brightness, new_brightness };
+ Write(0x82, command, sizeof(command));
+}
+
+void DGUSDisplay::SetVolume(uint8_t new_volume) {
+ volume = map_precise(constrain(new_volume, 0, 100), 0, 100, 0, 255);
+ DEBUG_ECHOLNPAIR("SetVolume ", volume);
+ const uint8_t command[] = { volume, 0x00 };
+ Write(0xA1, command, sizeof(command));
+}
+
+void DGUSDisplay::ProcessRx() {
+
+ #if ENABLED(LCD_SERIAL_STATS_RX_BUFFER_OVERRUNS)
+ if (!LCD_SERIAL.available() && LCD_SERIAL.buffer_overruns()) {
+ // Overrun, but reset the flag only when the buffer is empty
+ // We want to extract as many as valid datagrams possible...
+ DEBUG_ECHOPGM("OVFL");
+ rx_datagram_state = DGUS_IDLE;
+ //LCD_SERIAL.reset_rx_overun();
+ LCD_SERIAL.flush();
+ }
+ #endif
+
+ uint8_t receivedbyte;
+ while (LCD_SERIAL.available()) {
+ switch (rx_datagram_state) {
+
+ case DGUS_IDLE: // Waiting for the first header byte
+ receivedbyte = LCD_SERIAL.read();
+ DEBUG_ECHOPAIR("< ", receivedbyte);
+ if (DGUS_HEADER1 == receivedbyte) rx_datagram_state = DGUS_HEADER1_SEEN;
+ break;
+
+ case DGUS_HEADER1_SEEN: // Waiting for the second header byte
+ receivedbyte = LCD_SERIAL.read();
+ DEBUG_ECHOPAIR(" ", receivedbyte);
+ rx_datagram_state = (DGUS_HEADER2 == receivedbyte) ? DGUS_HEADER2_SEEN : DGUS_IDLE;
+ break;
+
+ case DGUS_HEADER2_SEEN: // Waiting for the length byte
+ rx_datagram_len = LCD_SERIAL.read();
+ DEBUG_ECHOPAIR(" (", rx_datagram_len, ") ");
+
+ // Telegram min len is 3 (command and one word of payload)
+ rx_datagram_state = WITHIN(rx_datagram_len, 3, DGUS_RX_BUFFER_SIZE) ? DGUS_WAIT_TELEGRAM : DGUS_IDLE;
+ break;
+
+ case DGUS_WAIT_TELEGRAM: // wait for complete datagram to arrive.
+ if (LCD_SERIAL.available() < rx_datagram_len) return;
+
+ initialized = true; // We've talked to it, so we defined it as initialized.
+ uint8_t command = LCD_SERIAL.read();
+
+ DEBUG_ECHOPAIR("# ", command);
+
+ uint8_t readlen = rx_datagram_len - 1; // command is part of len.
+ unsigned char tmp[rx_datagram_len - 1];
+ unsigned char *ptmp = tmp;
+
+ while (readlen--) {
+ receivedbyte = LCD_SERIAL.read();
+ DEBUG_ECHOPAIR(" ", receivedbyte);
+ *ptmp++ = receivedbyte;
+ }
+ DEBUG_ECHOPGM(" # ");
+ // mostly we'll get this: 5A A5 03 82 4F 4B -- ACK on 0x82, so discard it.
+ if (command == DGUS_WRITEVAR && 'O' == tmp[0] && 'K' == tmp[1]) {
+ DEBUG_ECHOLNPGM(">");
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ /* AutoUpload, (and answer to) Command 0x83 :
+ | tmp[0 1 2 3 4 ... ]
+ | Example 5A A5 06 83 20 01 01 78 01 ……
+ | / / | | \ / | \ \
+ | Header | | | | \_____\_ DATA (Words!)
+ | DatagramLen / VPAdr |
+ | Command DataLen (in Words) */
+ if (command == DGUS_READVAR) {
+ const uint16_t addr = tmp[0] << 8 | tmp[1];
+ const uint8_t dlen = tmp[2] << 1; // Convert to Bytes. (Display works with words)
+ DEBUG_ECHOPAIR("addr=", addr, " dlen=", dlen, "> ");
+
+ if (addr == DGUS_VERSION && dlen == 2) {
+ DEBUG_ECHOLNPGM("VERSIONS");
+ gui_version = tmp[3];
+ os_version = tmp[4];
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ DGUS_VP vp;
+ if (!DGUS_PopulateVP((DGUS_Addr)addr, &vp)) {
+ DEBUG_ECHOLNPGM("VP not found");
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ if (!vp.rx_handler) {
+ DEBUG_ECHOLNPGM("VP found, no handler.");
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ gcode.reset_stepper_timeout();
+
+ if (!vp.size) {
+ DEBUG_ECHOLN();
+ vp.rx_handler(vp, nullptr);
+
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ if (vp.flags & VPFLAG_RXSTRING) {
+ unsigned char buffer[vp.size];
+ memset(buffer, 0, vp.size);
+
+ for (uint8_t i = 0; i < dlen; i++) {
+ if (i >= vp.size) {
+ break;
+ }
+
+ if (i + 1 < dlen && tmp[i + 3] == 0xFF && tmp[i + 4] == 0xFF) {
+ break;
+ }
+
+ buffer[i] = tmp[i + 3];
+ }
+
+ DEBUG_ECHOLN();
+ vp.rx_handler(vp, buffer);
+
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ if (dlen != vp.size) {
+ DEBUG_ECHOLNPGM("VP found, size mismatch.");
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ DEBUG_ECHOLN();
+ vp.rx_handler(vp, &tmp[3]);
+
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ DEBUG_ECHOLNPGM(">");
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+ }
+}
+
+size_t DGUSDisplay::GetFreeTxBuffer() {
+ #ifdef LCD_SERIAL_GET_TX_BUFFER_FREE
+ return LCD_SERIAL_GET_TX_BUFFER_FREE();
+ #else
+ return SIZE_MAX;
+ #endif
+}
+
+void DGUSDisplay::FlushTx() {
+ #ifdef ARDUINO_ARCH_STM32
+ LCD_SERIAL.flush();
+ #else
+ LCD_SERIAL.flushTX();
+ #endif
+}
+
+void DGUSDisplay::WriteHeader(uint16_t addr, uint8_t command, uint8_t len) {
+ LCD_SERIAL.write(DGUS_HEADER1);
+ LCD_SERIAL.write(DGUS_HEADER2);
+ LCD_SERIAL.write(len + 3);
+ LCD_SERIAL.write(command);
+ LCD_SERIAL.write(addr >> 8);
+ LCD_SERIAL.write(addr & 0xFF);
+}
+
+bool DGUS_PopulateVP(const DGUS_Addr addr, DGUS_VP * const buffer) {
+ const DGUS_VP *ret = vp_list;
+
+ do {
+ const uint16_t *paddr = (uint16_t *)(&ret->addr);
+ const uint16_t addrcheck = pgm_read_word(paddr);
+ if (addrcheck == 0) break;
+ if ((DGUS_Addr)addrcheck == addr) {
+ memcpy_P(buffer, ret, sizeof(*ret));
+ return true;
+ }
+ } while (++ret);
+ DEBUG_ECHOLNPAIR("VP not found: ", (uint16_t)addr);
+ return false;
+}
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.h b/Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.h
new file mode 100644
index 000000000000..2a679648d11e
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.h
@@ -0,0 +1,171 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/* DGUS implementation written by coldtobi in 2019 for Marlin */
+
+#include "config/DGUS_Screen.h"
+#include "config/DGUS_Control.h"
+#include "definition/DGUS_VP.h"
+
+#include "../../../inc/MarlinConfigPre.h"
+#include "../../../MarlinCore.h"
+
+#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
+#include "../../../core/debug_out.h"
+
+#define Swap16(val) ((uint16_t)(((uint16_t)(val) >> 8) |\
+ ((uint16_t)(val) << 8)))
+
+// Low-Level access to the display.
+class DGUSDisplay {
+public:
+
+ enum DGUS_ControlType : uint8_t {
+ VARIABLE_DATA_INPUT = 0x00,
+ POPUP_WINDOW = 0x01,
+ INCREMENTAL_ADJUST = 0x02,
+ SLIDER_ADJUST = 0x03,
+ RTC_SETTINGS = 0x04,
+ RETURN_KEY_CODE = 0x05,
+ TEXT_INPUT = 0x06,
+ FIRMWARE_SETTINGS = 0x07
+ };
+
+ DGUSDisplay() = default;
+
+ static void Init();
+
+ static void Read(uint16_t addr, uint8_t size);
+ static void Write(uint16_t addr, const void* data_ptr, uint8_t size);
+
+ static void WriteString(uint16_t addr, const void* data_ptr, uint8_t size, bool left = true, bool right = false, bool use_space = true);
+ static void WriteStringPGM(uint16_t addr, const void* data_ptr, uint8_t size, bool left = true, bool right = false, bool use_space = true);
+
+ template
+ static void Write(uint16_t addr, T data) {
+ Write(addr, static_cast(&data), sizeof(T));
+ }
+
+ // Until now I did not need to actively read from the display. That's why there is no ReadVariable
+ // (I extensively use the auto upload of the display)
+
+ // Force display into another screen.
+ static void SwitchScreen(DGUS_Screen screen);
+ // Play sounds using the display speaker.
+ // start: position at which the sound was stored on the display.
+ // len: how many sounds to play. Sounds will play consecutively from start to start+len-1.
+ // volume: playback volume. 0 keeps the current volume.
+ static void PlaySound(uint8_t start, uint8_t len = 1, uint8_t volume = 0);
+ // Enable/disable a specific touch control.
+ // type: control type.
+ // control: index of the control on the page (set during screen development).
+ static void EnableControl(DGUS_Screen screen, DGUS_ControlType type, DGUS_Control control);
+ static void DisableControl(DGUS_Screen screen, DGUS_ControlType type, DGUS_Control control);
+
+ static uint8_t GetBrightness();
+ static uint8_t GetVolume();
+
+ // Set the display brightness/volume, ranging 0 - 100
+ static void SetBrightness(uint8_t brightness);
+ static void SetVolume(uint8_t volume);
+
+ // Periodic tasks, eg. Rx-Queue handling.
+ static void Loop();
+
+ // Helper for users of this class to estimate if an interaction would be blocking.
+ static size_t GetFreeTxBuffer();
+ static void FlushTx();
+
+ // Checks two things: Can we confirm the presence of the display and has we initiliazed it.
+ // (both boils down that the display answered to our chatting)
+ static inline bool IsInitialized() {
+ return initialized;
+ }
+
+ static uint8_t gui_version;
+ static uint8_t os_version;
+
+ template
+ static T SwapBytes(const T value) {
+ union {
+ T val;
+ char byte[sizeof(T)];
+ } src, dst;
+
+ src.val = value;
+ LOOP_L_N(i, sizeof(T)) dst.byte[i] = src.byte[sizeof(T) - i - 1];
+ return dst.val;
+ }
+
+ template
+ T_out FromFixedPoint(const T_in value) {
+ return (T_out)((float)value / POW(10, decimals));
+ }
+
+ template
+ T_out ToFixedPoint(const T_in value) {
+ return (T_out)LROUND((float)value * POW(10, decimals));
+ }
+
+private:
+ enum dgus_header : uint8_t {
+ DGUS_HEADER1 = 0x5A,
+ DGUS_HEADER2 = 0xA5
+ };
+
+ enum dgus_command : uint8_t {
+ DGUS_WRITEVAR = 0x82,
+ DGUS_READVAR = 0x83
+ };
+
+ enum rx_datagram_state_t : uint8_t {
+ DGUS_IDLE, //< waiting for DGUS_HEADER1.
+ DGUS_HEADER1_SEEN, //< DGUS_HEADER1 received
+ DGUS_HEADER2_SEEN, //< DGUS_HEADER2 received
+ DGUS_WAIT_TELEGRAM, //< LEN received, Waiting for to receive all bytes.
+ };
+
+ enum dgus_system_addr : uint16_t {
+ DGUS_VERSION = 0x000f // OS/GUI version
+ };
+
+ static void WriteHeader(uint16_t addr, uint8_t command, uint8_t len);
+ static void ProcessRx();
+
+ static uint8_t volume;
+ static uint8_t brightness;
+
+ static rx_datagram_state_t rx_datagram_state;
+ static uint8_t rx_datagram_len;
+
+ static bool initialized;
+};
+
+template<> inline uint16_t DGUSDisplay::SwapBytes(const uint16_t value) {
+ return ((value << 8) | (value >> 8));
+}
+
+extern DGUSDisplay dgus_display;
+
+/// Helper to populate a DGUS_VP for a given VP. Return false if not found.
+extern bool DGUS_PopulateVP(const DGUS_Addr addr, DGUS_VP * const buffer);
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.cpp
new file mode 100644
index 000000000000..5f36dac7f616
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.cpp
@@ -0,0 +1,1059 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUSRxHandler.h"
+
+#include "DGUSScreenHandler.h"
+#include "config/DGUS_Screen.h"
+
+#include "../ui_api.h"
+#include "../../../core/language.h"
+#include "../../../module/temperature.h"
+#include "../../../module/printcounter.h"
+#include "../../../gcode/queue.h"
+#if ENABLED(ADVANCED_PAUSE_FEATURE)
+ #include "../../../feature/pause.h"
+#endif
+#if ENABLED(POWER_LOSS_RECOVERY)
+ #include "../../../feature/powerloss.h"
+#endif
+
+void DGUSRxHandler::ScreenChange(DGUS_VP &vp, void *data_ptr) {
+ const DGUS_Screen screen = (DGUS_Screen)((uint8_t*)data_ptr)[1];
+
+ if (vp.addr == DGUS_Addr::SCREENCHANGE_SD) {
+ #if ENABLED(SDSUPPORT)
+ #if !PIN_EXISTS(SD_DETECT)
+ card.mount();
+ #endif
+
+ if (!ExtUI::isMediaInserted()) {
+ dgus_screen_handler.SetStatusMessagePGM(GET_TEXT(MSG_NO_MEDIA));
+ return;
+ }
+
+ card.cdroot();
+ #else
+ dgus_screen_handler.SetStatusMessagePGM(GET_TEXT(MSG_NO_MEDIA));
+ return;
+ #endif
+ }
+
+ if (vp.addr == DGUS_Addr::SCREENCHANGE_Idle
+ && (printingIsActive() || printingIsPaused())) {
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("Impossible while printing"));
+ return;
+ }
+
+ if (vp.addr == DGUS_Addr::SCREENCHANGE_Printing
+ && (!printingIsActive() && !printingIsPaused())) {
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("Impossible while idle"));
+ return;
+ }
+
+ dgus_screen_handler.TriggerScreenChange(screen);
+}
+
+#if ENABLED(SDSUPPORT)
+ void DGUSRxHandler::Scroll(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Scroll scroll = (DGUS_Data::Scroll)((uint8_t*)data_ptr)[1];
+
+ switch (scroll) {
+ case DGUS_Data::Scroll::GO_BACK:
+ if (dgus_screen_handler.filelist.isAtRootDir()) {
+ return;
+ }
+
+ dgus_screen_handler.filelist_offset = 0;
+ dgus_screen_handler.filelist_selected = -1;
+ dgus_screen_handler.filelist.upDir();
+ break;
+ case DGUS_Data::Scroll::UP:
+ if (dgus_screen_handler.filelist_offset < 1) {
+ return;
+ }
+
+ --dgus_screen_handler.filelist_offset;
+ break;
+ case DGUS_Data::Scroll::DOWN:
+ if (dgus_screen_handler.filelist_offset + 1 + DGUS_FILE_COUNT > dgus_screen_handler.filelist.count()) {
+ return;
+ }
+
+ ++dgus_screen_handler.filelist_offset;
+ break;
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+ }
+
+ void DGUSRxHandler::SelectFile(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const uint8_t index = ((uint8_t*)data_ptr)[1];
+
+ if (!dgus_screen_handler.filelist.seek(dgus_screen_handler.filelist_offset + index)) {
+ return;
+ }
+
+ if (dgus_screen_handler.filelist.isDir()) {
+ dgus_screen_handler.filelist_offset = 0;
+ dgus_screen_handler.filelist_selected = -1;
+ dgus_screen_handler.filelist.changeDir(dgus_screen_handler.filelist.filename());
+ }
+ else {
+ dgus_screen_handler.filelist_selected = dgus_screen_handler.filelist_offset + index;
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+ }
+
+ void DGUSRxHandler::PrintFile(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ if (dgus_screen_handler.filelist_selected < 0) {
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("No file selected"));
+ return;
+ }
+
+ if (!dgus_screen_handler.filelist.seek(dgus_screen_handler.filelist_selected)
+ || dgus_screen_handler.filelist.isDir()) {
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ ExtUI::printFile(dgus_screen_handler.filelist.shortFilename());
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::PRINT_STATUS);
+ }
+#endif // SDSUPPORT
+
+void DGUSRxHandler::PrintAbort(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!printingIsActive() && !printingIsPaused()) {
+ dgus_screen_handler.TriggerFullUpdate();
+ return;
+ }
+
+ ExtUI::stopPrint();
+}
+
+void DGUSRxHandler::PrintPause(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!printingIsActive()) {
+ dgus_screen_handler.TriggerFullUpdate();
+ return;
+ }
+
+ ExtUI::pausePrint();
+}
+
+void DGUSRxHandler::PrintResume(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!printingIsPaused()) {
+ dgus_screen_handler.TriggerFullUpdate();
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ ExtUI::resumePrint();
+}
+
+void DGUSRxHandler::Feedrate(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const int16_t feedrate = Swap16(*(int16_t*)data_ptr);
+
+ ExtUI::setFeedrate_percent(feedrate);
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::Flowrate(DGUS_VP &vp, void *data_ptr) {
+ const int16_t flowrate = Swap16(*(int16_t*)data_ptr);
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::ADJUST_SetFlowrate_CUR:
+ #if EXTRUDERS > 1
+ ExtUI::setFlow_percent(flowrate, ExtUI::getActiveTool());
+ #else
+ ExtUI::setFlow_percent(flowrate, ExtUI::E0);
+ #endif
+ break;
+ #if EXTRUDERS > 1
+ case DGUS_Addr::ADJUST_SetFlowrate_E0:
+ ExtUI::setFlow_percent(flowrate, ExtUI::E0);
+ break;
+ case DGUS_Addr::ADJUST_SetFlowrate_E1:
+ ExtUI::setFlow_percent(flowrate, ExtUI::E1);
+ break;
+ #endif
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::BabystepSet(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const int16_t data = Swap16(*(int16_t*)data_ptr);
+ const float offset = dgus_display.FromFixedPoint(data);
+
+ const int16_t steps = ExtUI::mmToWholeSteps(offset - ExtUI::getZOffset_mm(), ExtUI::Z);
+
+ ExtUI::smartAdjustAxis_steps(steps, ExtUI::Z, true);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::Babystep(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Adjust adjust = (DGUS_Data::Adjust)((uint8_t*)data_ptr)[1];
+ int16_t steps;
+
+ switch (adjust) {
+ default: return;
+ case DGUS_Data::Adjust::INCREMENT:
+ steps = ExtUI::mmToWholeSteps(DGUS_PRINT_BABYSTEP, ExtUI::Z);
+ break;
+ case DGUS_Data::Adjust::DECREMENT:
+ steps = ExtUI::mmToWholeSteps(-DGUS_PRINT_BABYSTEP, ExtUI::Z);
+ break;
+ }
+
+ ExtUI::smartAdjustAxis_steps(steps, ExtUI::Z, true);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::TempPreset(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::TempPreset preset = (DGUS_Data::TempPreset)((uint8_t*)data_ptr)[1];
+
+ switch (preset) {
+ case DGUS_Data::TempPreset::PLA:
+ #if HOTENDS < 2
+ ExtUI::setTargetTemp_celsius(DGUS_PLA_TEMP_HOTEND, ExtUI::H0);
+ #else
+ ExtUI::setTargetTemp_celsius(DGUS_PLA_TEMP_HOTEND, ExtUI::getActiveTool());
+ #endif
+ ExtUI::setTargetTemp_celsius(DGUS_PLA_TEMP_BED, ExtUI::BED);
+ break;
+ case DGUS_Data::TempPreset::ABS:
+ #if HOTENDS < 2
+ ExtUI::setTargetTemp_celsius(DGUS_ABS_TEMP_HOTEND, ExtUI::H0);
+ #else
+ ExtUI::setTargetTemp_celsius(DGUS_ABS_TEMP_HOTEND, ExtUI::getActiveTool());
+ #endif
+ ExtUI::setTargetTemp_celsius(DGUS_ABS_TEMP_BED, ExtUI::BED);
+ break;
+ case DGUS_Data::TempPreset::PETG:
+ #if HOTENDS < 2
+ ExtUI::setTargetTemp_celsius(DGUS_PETG_TEMP_HOTEND, ExtUI::H0);
+ #else
+ ExtUI::setTargetTemp_celsius(DGUS_PETG_TEMP_HOTEND, ExtUI::getActiveTool());
+ #endif
+ ExtUI::setTargetTemp_celsius(DGUS_PETG_TEMP_BED, ExtUI::BED);
+ break;
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::TempTarget(DGUS_VP &vp, void *data_ptr) {
+ const int16_t temp = Swap16(*(int16_t*)data_ptr);
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::TEMP_SetTarget_Bed:
+ ExtUI::setTargetTemp_celsius(temp, ExtUI::BED);
+ break;
+ case DGUS_Addr::TEMP_SetTarget_H0:
+ ExtUI::setTargetTemp_celsius(temp, ExtUI::H0);
+ break;
+ #if HOTENDS > 1
+ case DGUS_Addr::TEMP_SetTarget_H1:
+ ExtUI::setTargetTemp_celsius(temp, ExtUI::H1);
+ break;
+ #endif
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::TempCool(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Heater heater = (DGUS_Data::Heater)Swap16(*(uint16_t*)data_ptr);
+
+ switch (heater) {
+ default: return;
+ case DGUS_Data::Heater::ALL:
+ ExtUI::setTargetTemp_celsius(0, ExtUI::BED);
+ ExtUI::setTargetTemp_celsius(0, ExtUI::H0);
+ #if HOTENDS > 1
+ ExtUI::setTargetTemp_celsius(0, ExtUI::H1);
+ #endif
+ break;
+ case DGUS_Data::Heater::BED:
+ ExtUI::setTargetTemp_celsius(0, ExtUI::BED);
+ break;
+ case DGUS_Data::Heater::H0:
+ ExtUI::setTargetTemp_celsius(0, ExtUI::H0);
+ break;
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ ExtUI::setTargetTemp_celsius(0, ExtUI::H1);
+ break;
+ #endif
+ }
+
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("Cooling..."));
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::Steppers(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Control control = (DGUS_Data::Control)((uint8_t*)data_ptr)[1];
+
+ switch (control) {
+ case DGUS_Data::Control::ENABLE:
+ enable_all_steppers();
+ break;
+ case DGUS_Data::Control::DISABLE:
+ disable_all_steppers();
+ break;
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::ZOffset(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ if (!ExtUI::isAxisPositionKnown(ExtUI::Z)) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_HOMING_REQUIRED);
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ const int16_t data = Swap16(*(int16_t*)data_ptr);
+ const float offset = dgus_display.FromFixedPoint(data);
+
+ const int16_t steps = ExtUI::mmToWholeSteps(offset - ExtUI::getZOffset_mm(), ExtUI::Z);
+
+ ExtUI::smartAdjustAxis_steps(steps, ExtUI::Z, true);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::ZOffsetStep(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ if (!ExtUI::isAxisPositionKnown(ExtUI::Z)) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_HOMING_REQUIRED);
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ const DGUS_Data::Adjust adjust = (DGUS_Data::Adjust)((uint8_t*)data_ptr)[1];
+ int16_t steps;
+
+ switch (dgus_screen_handler.offset_steps) {
+ default: return;
+ case DGUS_Data::StepSize::MMP1:
+ steps = ExtUI::mmToWholeSteps((adjust == DGUS_Data::Adjust::INCREMENT ? 0.1f : -0.1f), ExtUI::Z);
+ break;
+ case DGUS_Data::StepSize::MMP01:
+ steps = ExtUI::mmToWholeSteps((adjust == DGUS_Data::Adjust::INCREMENT ? 0.01f : -0.01f), ExtUI::Z);
+ break;
+ }
+
+ ExtUI::smartAdjustAxis_steps(steps, ExtUI::Z, true);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::ZOffsetSetStep(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::StepSize size = (DGUS_Data::StepSize)((uint8_t*)data_ptr)[1];
+
+ dgus_screen_handler.offset_steps = size;
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::MoveToPoint(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ if (!ExtUI::isPositionKnown()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_HOMING_REQUIRED);
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ const uint8_t point = ((uint8_t*)data_ptr)[1];
+ constexpr float lfrb[4] = LEVEL_CORNERS_INSET_LFRB;
+ float x, y;
+
+ switch (point) {
+ default: return;
+ case 1:
+ x = DGUS_LEVEL_CENTER_X;
+ y = DGUS_LEVEL_CENTER_Y;
+ break;
+ case 2:
+ x = X_MIN_POS + lfrb[0];
+ y = Y_MIN_POS + lfrb[1];
+ break;
+ case 3:
+ x = X_MAX_POS - lfrb[2];
+ y = Y_MIN_POS + lfrb[1];
+ break;
+ case 4:
+ x = X_MAX_POS - lfrb[2];
+ y = Y_MAX_POS - lfrb[3];
+ break;
+ case 5:
+ x = X_MIN_POS + lfrb[0];
+ y = Y_MAX_POS - lfrb[3];
+ break;
+ }
+
+ if (ExtUI::getAxisPosition_mm(ExtUI::Z) < Z_MIN_POS + LEVEL_CORNERS_Z_HOP) {
+ ExtUI::setAxisPosition_mm(Z_MIN_POS + LEVEL_CORNERS_Z_HOP, ExtUI::Z);
+ }
+ ExtUI::setAxisPosition_mm(x, ExtUI::X);
+ ExtUI::setAxisPosition_mm(y, ExtUI::Y);
+ ExtUI::setAxisPosition_mm(Z_MIN_POS + LEVEL_CORNERS_HEIGHT, ExtUI::Z);
+}
+
+void DGUSRxHandler::Probe(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ #if ENABLED(MESH_BED_LEVELING)
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_ABL_REQUIRED);
+ return;
+ #endif
+
+ if (!ExtUI::isPositionKnown()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_HOMING_REQUIRED);
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::LEVELING_PROBING);
+
+ #if ENABLED(AUTO_BED_LEVELING_UBL)
+ queue.enqueue_now_P(PSTR("G29P1\nG29P3\nG29P5C"));
+ #else
+ queue.enqueue_now_P(PSTR("G29"));
+ #endif
+ queue.enqueue_now_P(DGUS_CMD_EEPROM_SAVE);
+}
+
+void DGUSRxHandler::DisableABL(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ ExtUI::setLevelingActive(false);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::FilamentSelect(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Extruder extruder = (DGUS_Data::Extruder)Swap16(*(uint16_t*)data_ptr);
+
+ switch (extruder) {
+ default: return;
+ case DGUS_Data::Extruder::CURRENT:
+ case DGUS_Data::Extruder::E0:
+ #if EXTRUDERS > 1
+ case DGUS_Data::Extruder::E1:
+ #endif
+ dgus_screen_handler.filament_extruder = extruder;
+ break;
+ }
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::FilamentLength(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const uint16_t length = Swap16(*(uint16_t*)data_ptr);
+
+ dgus_screen_handler.filament_length = constrain(length, 0, EXTRUDE_MAXLENGTH);
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::FilamentMove(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ ExtUI::extruder_t extruder;
+
+ switch (dgus_screen_handler.filament_extruder) {
+ default: return;
+ case DGUS_Data::Extruder::CURRENT:
+ #if EXTRUDERS > 1
+ extruder = ExtUI::getActiveTool();
+ break;
+ #endif
+ case DGUS_Data::Extruder::E0:
+ extruder = ExtUI::E0;
+ break;
+ #if EXTRUDERS > 1
+ case DGUS_Data::Extruder::E1:
+ extruder = ExtUI::E1;
+ break;
+ #endif
+ }
+
+ if (ExtUI::getActualTemp_celsius(extruder) < (float)EXTRUDE_MINTEMP) {
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("Temperature too low"));
+ return;
+ }
+
+ const DGUS_Data::FilamentMove move = (DGUS_Data::FilamentMove)((uint8_t*)data_ptr)[1];
+
+ switch (move) {
+ case DGUS_Data::FilamentMove::RETRACT:
+ UI_DECREMENT_BY(AxisPosition_mm, (float)dgus_screen_handler.filament_length, extruder);
+ break;
+ case DGUS_Data::FilamentMove::EXTRUDE:
+ UI_INCREMENT_BY(AxisPosition_mm, (float)dgus_screen_handler.filament_length, extruder);
+ break;
+ }
+}
+
+void DGUSRxHandler::Home(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ DGUS_Data::Axis axis = (DGUS_Data::Axis)((uint8_t*)data_ptr)[1];
+
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLinePGM(DGUS_MSG_HOMING, 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+ dgus_screen_handler.ShowWaitScreen(dgus_screen_handler.GetCurrentScreen());
+
+ switch (axis) {
+ case DGUS_Data::Axis::X_Y_Z:
+ queue.enqueue_now_P(PSTR("G28XYZ"));
+ break;
+ case DGUS_Data::Axis::X_Y:
+ queue.enqueue_now_P(PSTR("G28XY"));
+ break;
+ case DGUS_Data::Axis::Z:
+ queue.enqueue_now_P(PSTR("G28Z"));
+ break;
+ }
+}
+
+void DGUSRxHandler::Move(DGUS_VP &vp, void *data_ptr) {
+ const int16_t data = Swap16(*(int16_t*)data_ptr);
+ const float position = dgus_display.FromFixedPoint(data);
+ ExtUI::axis_t axis;
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::MOVE_SetX:
+ axis = ExtUI::X;
+ break;
+ case DGUS_Addr::MOVE_SetY:
+ axis = ExtUI::Y;
+ break;
+ case DGUS_Addr::MOVE_SetZ:
+ axis = ExtUI::Z;
+ break;
+ }
+
+ if (!ExtUI::isAxisPositionKnown(axis)) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_HOMING_REQUIRED);
+ return;
+ }
+
+ ExtUI::setAxisPosition_mm(position, axis);
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::MoveStep(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ float offset;
+
+ switch (dgus_screen_handler.move_steps) {
+ default: return;
+ case DGUS_Data::StepSize::MM10:
+ offset = 10.0f;
+ break;
+ case DGUS_Data::StepSize::MM1:
+ offset = 1.0f;
+ break;
+ case DGUS_Data::StepSize::MMP1:
+ offset = 0.1f;
+ break;
+ }
+
+ const DGUS_Data::MoveDirection direction = (DGUS_Data::MoveDirection)((uint8_t*)data_ptr)[1];
+ ExtUI::axis_t axis;
+
+ switch (direction) {
+ default: return;
+ case DGUS_Data::MoveDirection::XP:
+ axis = ExtUI::X;
+ break;
+ case DGUS_Data::MoveDirection::XM:
+ axis = ExtUI::X;
+ offset = -offset;
+ break;
+ case DGUS_Data::MoveDirection::YP:
+ axis = ExtUI::Y;
+ break;
+ case DGUS_Data::MoveDirection::YM:
+ axis = ExtUI::Y;
+ offset = -offset;
+ break;
+ case DGUS_Data::MoveDirection::ZP:
+ axis = ExtUI::Z;
+ break;
+ case DGUS_Data::MoveDirection::ZM:
+ axis = ExtUI::Z;
+ offset = -offset;
+ break;
+ }
+
+ if (!ExtUI::isAxisPositionKnown(axis)) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_HOMING_REQUIRED);
+ return;
+ }
+
+ UI_INCREMENT_BY(AxisPosition_mm, offset, axis);
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::MoveSetStep(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::StepSize size = (DGUS_Data::StepSize)((uint8_t*)data_ptr)[1];
+
+ dgus_screen_handler.move_steps = size;
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::GcodeClear(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ ZERO(dgus_screen_handler.gcode);
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::GcodeExecute(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ if (!strlen(dgus_screen_handler.gcode)) {
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLinePGM(PSTR("Executing command..."), 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+ dgus_screen_handler.ShowWaitScreen(DGUS_Screen::GCODE);
+
+ queue.enqueue_one_now(dgus_screen_handler.gcode);
+}
+
+void DGUSRxHandler::ResetEEPROM(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ queue.enqueue_now_P(PSTR("M502"));
+ queue.enqueue_now_P(DGUS_CMD_EEPROM_SAVE);
+}
+
+void DGUSRxHandler::SettingsExtra(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Extra extra = (DGUS_Data::Extra)((uint8_t*)data_ptr)[1];
+
+ switch (extra) {
+ default: return;
+ case DGUS_Data::Extra::BUTTON1:
+ #if ENABLED(BLTOUCH)
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ queue.enqueue_now_P(PSTR(DGUS_RESET_BLTOUCH));
+ #else
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::INFOS);
+ #endif
+ break;
+ #if ENABLED(BLTOUCH)
+ case DGUS_Data::Extra::BUTTON2:
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::INFOS);
+ break;
+ #endif
+ }
+}
+
+void DGUSRxHandler::PIDSelect(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Heater heater = (DGUS_Data::Heater)Swap16(*(uint16_t*)data_ptr);
+
+ switch (heater) {
+ default: return;
+ case DGUS_Data::Heater::BED:
+ dgus_screen_handler.pid_temp = DGUS_PLA_TEMP_BED;
+ dgus_screen_handler.pid_heater = heater;
+ break;
+ case DGUS_Data::Heater::H0:
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ #endif
+ dgus_screen_handler.pid_temp = DGUS_PLA_TEMP_HOTEND;
+ dgus_screen_handler.pid_heater = heater;
+ break;
+ }
+
+ dgus_screen_handler.pid_cycles = 5;
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::PIDSetTemp(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ uint16_t temp = Swap16(*(uint16_t*)data_ptr);
+
+ switch (dgus_screen_handler.pid_heater) {
+ default: return;
+ case DGUS_Data::Heater::BED:
+ temp = constrain(temp, BED_MINTEMP, BED_MAX_TARGET);
+ break;
+ case DGUS_Data::Heater::H0:
+ temp = constrain(temp, HEATER_0_MINTEMP, (HEATER_0_MAXTEMP - HOTEND_OVERSHOOT));
+ break;
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ temp = constrain(temp, HEATER_1_MINTEMP, (HEATER_1_MAXTEMP - HOTEND_OVERSHOOT));
+ break;
+ #endif
+ }
+
+ dgus_screen_handler.pid_temp = temp;
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::PIDRun(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ heater_id_t heater;
+ uint8_t cycles = constrain(dgus_screen_handler.pid_cycles, 3, 10);
+
+ switch (dgus_screen_handler.pid_heater) {
+ default: return;
+ case DGUS_Data::Heater::BED:
+ #if ENABLED(PIDTEMPBED)
+ heater = H_BED;
+ break;
+ #else
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("Bed PID disabled"));
+ return;
+ #endif
+ case DGUS_Data::Heater::H0:
+ #if ENABLED(PIDTEMP)
+ heater = H_E0;
+ break;
+ #else
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("PID disabled"));
+ return;
+ #endif
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ #if ENABLED(PIDTEMP)
+ heater = H_E1;
+ break;
+ #else
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("PID disabled"));
+ return;
+ #endif
+ #endif
+ }
+
+ char buffer[24];
+ snprintf_P(buffer, sizeof(buffer), PSTR("M303C%dE%dS%dU1"), cycles, heater, dgus_screen_handler.pid_temp);
+
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLinePGM(PSTR("PID autotuning..."), 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+ dgus_screen_handler.ShowWaitScreen(DGUS_Screen::PID);
+
+ queue.enqueue_one_now(buffer);
+ queue.enqueue_now_P(DGUS_CMD_EEPROM_SAVE);
+}
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+ void DGUSRxHandler::PowerLossAbort(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::HOME);
+
+ queue.enqueue_now_P(PSTR("M1000C"));
+ }
+
+ void DGUSRxHandler::PowerLossResume(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return;
+ }
+
+ if (!recovery.valid()) {
+ dgus_screen_handler.SetStatusMessagePGM(PSTR("Invalid recovery data"));
+ return;
+ }
+
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::PRINT_STATUS);
+
+ queue.enqueue_now_P(PSTR("M1000"));
+ }
+#endif // POWER_LOSS_RECOVERY
+
+void DGUSRxHandler::WaitAbort(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ const DGUS_Data::Popup result = (DGUS_Data::Popup)((uint8_t*)data_ptr)[1];
+
+ if (result != DGUS_Data::Popup::CONFIRMED) {
+ return;
+ }
+
+ if (!printingIsPaused()
+ #if ENABLED(ADVANCED_PAUSE_FEATURE)
+ || !did_pause_print
+ #endif
+ ) {
+ dgus_screen_handler.TriggerFullUpdate();
+ return;
+ }
+
+ #if ENABLED(ADVANCED_PAUSE_FEATURE)
+ did_pause_print = 0;
+ #endif
+
+ ExtUI::setUserConfirmed();
+ ExtUI::stopPrint();
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::WaitContinue(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ ExtUI::setUserConfirmed();
+
+ dgus_screen_handler.TriggerFullUpdate();
+}
+
+void DGUSRxHandler::FanSpeed(DGUS_VP &vp, void *data_ptr) {
+ uint8_t speed = ((uint8_t*)data_ptr)[1];
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::FAN0_Speed:
+ ExtUI::setTargetFan_percent(speed, ExtUI::FAN0);
+ break;
+ }
+}
+
+void DGUSRxHandler::Volume(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ uint8_t volume = ((uint8_t*)data_ptr)[1];
+ dgus_display.SetVolume(volume);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+}
+
+void DGUSRxHandler::Brightness(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+
+ uint8_t brightness = ((uint8_t*)data_ptr)[1];
+ dgus_display.SetBrightness(brightness);
+
+ dgus_screen_handler.TriggerEEPROMSave();
+}
+
+void DGUSRxHandler::Debug(DGUS_VP &vp, void *data_ptr) {
+ UNUSED(vp);
+ UNUSED(data_ptr);
+
+ ++dgus_screen_handler.debug_count;
+
+ if (dgus_screen_handler.debug_count >= 10) {
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::DEBUG);
+ }
+}
+
+void DGUSRxHandler::StringToExtra(DGUS_VP &vp, void *data_ptr) {
+ if (!vp.size || !vp.extra) return;
+ memcpy(vp.extra, data_ptr, vp.size);
+}
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.h b/Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.h
new file mode 100644
index 000000000000..d092d3a5b74f
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.h
@@ -0,0 +1,123 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+#include "DGUSDisplay.h"
+#include "definition/DGUS_VP.h"
+
+namespace DGUSRxHandler {
+
+ void ScreenChange(DGUS_VP &, void *);
+
+ #if ENABLED(SDSUPPORT)
+ void Scroll(DGUS_VP &, void *);
+ void SelectFile(DGUS_VP &, void *);
+ void PrintFile(DGUS_VP &, void *);
+ #endif
+
+ void PrintAbort(DGUS_VP &, void *);
+ void PrintPause(DGUS_VP &, void *);
+ void PrintResume(DGUS_VP &, void *);
+
+ void Feedrate(DGUS_VP &, void *);
+ void Flowrate(DGUS_VP &, void *);
+ void BabystepSet(DGUS_VP &, void *);
+ void Babystep(DGUS_VP &, void *);
+
+ void TempPreset(DGUS_VP &, void *);
+ void TempTarget(DGUS_VP &, void *);
+ void TempCool(DGUS_VP &, void *);
+
+ void Steppers(DGUS_VP &, void *);
+
+ void ZOffset(DGUS_VP &, void *);
+ void ZOffsetStep(DGUS_VP &, void *);
+ void ZOffsetSetStep(DGUS_VP &, void *);
+
+ void MoveToPoint(DGUS_VP &, void *);
+
+ void Probe(DGUS_VP &, void *);
+ void DisableABL(DGUS_VP &, void *);
+
+ void FilamentSelect(DGUS_VP &, void *);
+ void FilamentLength(DGUS_VP &, void *);
+ void FilamentMove(DGUS_VP &, void *);
+
+ void Home(DGUS_VP &, void *);
+ void Move(DGUS_VP &, void *);
+ void MoveStep(DGUS_VP &, void *);
+ void MoveSetStep(DGUS_VP &, void *);
+
+ void GcodeClear(DGUS_VP &, void *);
+ void GcodeExecute(DGUS_VP &, void *);
+
+ void ResetEEPROM(DGUS_VP &, void *);
+
+ void SettingsExtra(DGUS_VP &, void *);
+
+ void PIDSelect(DGUS_VP &, void *);
+ void PIDSetTemp(DGUS_VP &, void *);
+ void PIDRun(DGUS_VP &, void *);
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ void PowerLossAbort(DGUS_VP &, void *);
+ void PowerLossResume(DGUS_VP &, void *);
+ #endif
+
+ void WaitAbort(DGUS_VP &, void *);
+ void WaitContinue(DGUS_VP &, void *);
+
+ void FanSpeed(DGUS_VP &, void *);
+
+ void Volume(DGUS_VP &, void *);
+
+ void Brightness(DGUS_VP &, void *);
+
+ void Debug(DGUS_VP &, void *);
+
+ void StringToExtra(DGUS_VP &, void *);
+
+ template
+ void IntegerToExtra(DGUS_VP &vp, void *data_ptr) {
+ if (!vp.size || !vp.extra) return;
+ switch (vp.size) {
+ default: return;
+ case 1: {
+ const uint8_t data = *(uint8_t*)data_ptr;
+ *(T*)vp.extra = (T)data;
+ break;
+ }
+ case 2: {
+ const uint16_t data = Swap16(*(uint16_t*)data_ptr);
+ *(T*)vp.extra = (T)data;
+ break;
+ }
+ case 4: {
+ const uint32_t data = dgus_display.SwapBytes(*(uint32_t*)data_ptr);
+ *(T*)vp.extra = (T)data;
+ break;
+ }
+ }
+ }
+
+}
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSScreenHandler.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSScreenHandler.cpp
new file mode 100644
index 000000000000..6316f1194b7e
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSScreenHandler.cpp
@@ -0,0 +1,540 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUSScreenHandler.h"
+
+#include "DGUSDisplay.h"
+#include "definition/DGUS_ScreenAddrList.h"
+#include "definition/DGUS_ScreenSetup.h"
+
+#include "../../../gcode/queue.h"
+
+uint8_t DGUSScreenHandler::debug_count = 0;
+
+#if ENABLED(SDSUPPORT)
+ ExtUI::FileList DGUSScreenHandler::filelist;
+ uint16_t DGUSScreenHandler::filelist_offset = 0;
+ int16_t DGUSScreenHandler::filelist_selected = -1;
+#endif
+
+DGUS_Data::StepSize DGUSScreenHandler::offset_steps = DGUS_Data::StepSize::MMP1;
+DGUS_Data::StepSize DGUSScreenHandler::move_steps = DGUS_Data::StepSize::MM10;
+
+uint16_t DGUSScreenHandler::probing_icons[] = { 0, 0 };
+
+DGUS_Data::Extruder DGUSScreenHandler::filament_extruder = DGUS_Data::Extruder::CURRENT;
+uint16_t DGUSScreenHandler::filament_length = DGUS_DEFAULT_FILAMENT_LEN;
+
+char DGUSScreenHandler::gcode[] = "";
+
+DGUS_Data::Heater DGUSScreenHandler::pid_heater = DGUS_Data::Heater::H0;
+uint16_t DGUSScreenHandler::pid_temp = DGUS_PLA_TEMP_HOTEND;
+uint8_t DGUSScreenHandler::pid_cycles = 5;
+
+bool DGUSScreenHandler::settings_ready = false;
+bool DGUSScreenHandler::booted = false;
+
+DGUS_Screen DGUSScreenHandler::current_screen = DGUS_Screen::BOOT;
+DGUS_Screen DGUSScreenHandler::new_screen = DGUS_Screen::BOOT;
+bool DGUSScreenHandler::full_update = false;
+
+DGUS_Screen DGUSScreenHandler::wait_return_screen = DGUS_Screen::HOME;
+bool DGUSScreenHandler::wait_continue = false;
+
+bool DGUSScreenHandler::leveling_active = false;
+
+millis_t DGUSScreenHandler::status_expire = 0;
+millis_t DGUSScreenHandler::eeprom_save = 0;
+
+const char DGUS_MSG_HOMING_REQUIRED[] PROGMEM = "Homing required",
+ DGUS_MSG_BUSY[] PROGMEM = "Busy",
+ DGUS_MSG_UNDEF[] PROGMEM = "-",
+ DGUS_MSG_HOMING[] PROGMEM = "Homing...",
+ DGUS_MSG_FW_OUTDATED[] PROGMEM = "DWIN GUI/OS update required",
+ DGUS_MSG_ABL_REQUIRED[] PROGMEM = "Auto bed leveling required";
+
+const char DGUS_CMD_HOME[] PROGMEM = "G28",
+ DGUS_CMD_EEPROM_SAVE[] PROGMEM = "M500";
+
+void DGUSScreenHandler::Init() {
+ dgus_display.Init();
+
+ MoveToScreen(DGUS_Screen::BOOT, true);
+}
+
+void DGUSScreenHandler::Ready() {
+ dgus_display.PlaySound(1);
+}
+
+void DGUSScreenHandler::Loop() {
+ if (!settings_ready || current_screen == DGUS_Screen::KILL) {
+ return;
+ }
+
+ const millis_t ms = ExtUI::safe_millis();
+ static millis_t next_event_ms = 0;
+
+ if (new_screen != DGUS_Screen::BOOT) {
+ const DGUS_Screen screen = new_screen;
+ new_screen = DGUS_Screen::BOOT;
+
+ if (current_screen == screen) {
+ TriggerFullUpdate();
+ }
+ else {
+ MoveToScreen(screen);
+ }
+ return;
+ }
+
+ if (!booted && ELAPSED(ms, 3000)) {
+ booted = true;
+
+ if (current_screen == DGUS_Screen::BOOT) {
+ MoveToScreen(DGUS_Screen::HOME);
+ }
+ return;
+ }
+
+ if (ELAPSED(ms, next_event_ms) || full_update) {
+ next_event_ms = ms + DGUS_UPDATE_INTERVAL_MS;
+
+ if (!SendScreenVPData(current_screen, full_update)) {
+ DEBUG_ECHOLNPGM("SendScreenVPData failed");
+ }
+ return;
+ }
+
+ if (current_screen == DGUS_Screen::WAIT
+ && ((wait_continue && !wait_for_user)
+ || (!wait_continue && IsPrinterIdle()))) {
+ MoveToScreen(wait_return_screen, true);
+ return;
+ }
+
+ if (current_screen == DGUS_Screen::LEVELING_PROBING
+ && IsPrinterIdle()) {
+ dgus_display.PlaySound(3);
+
+ SetStatusMessagePGM(ExtUI::getMeshValid() ?
+ PSTR("Probing successful")
+ : PSTR("Probing failed"));
+
+ MoveToScreen(DGUS_Screen::LEVELING_AUTOMATIC);
+ return;
+ }
+
+ if (status_expire > 0 && ELAPSED(ms, status_expire)) {
+ SetStatusMessagePGM(NUL_STR, 0);
+ return;
+ }
+
+ if (eeprom_save > 0 && ELAPSED(ms, eeprom_save) && IsPrinterIdle()) {
+ eeprom_save = 0;
+
+ queue.enqueue_now_P(DGUS_CMD_EEPROM_SAVE);
+ return;
+ }
+
+ dgus_display.Loop();
+}
+
+void DGUSScreenHandler::PrinterKilled(PGM_P error, PGM_P component) {
+ SetMessageLinePGM(error, 1);
+ SetMessageLinePGM(component, 2);
+ SetMessageLinePGM(NUL_STR, 3);
+ SetMessageLinePGM(GET_TEXT(MSG_PLEASE_RESET), 4);
+
+ dgus_display.PlaySound(3, 1, 200);
+
+ MoveToScreen(DGUS_Screen::KILL, true);
+}
+
+void DGUSScreenHandler::UserConfirmRequired(const char * const msg) {
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLine(msg, 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+
+ dgus_display.PlaySound(3);
+
+ dgus_screen_handler.ShowWaitScreen(current_screen, true);
+}
+
+void DGUSScreenHandler::SettingsReset() {
+ dgus_display.SetVolume(DGUS_DEFAULT_VOLUME);
+ dgus_display.SetBrightness(DGUS_DEFAULT_BRIGHTNESS);
+
+ if (!settings_ready) {
+ settings_ready = true;
+
+ Ready();
+ }
+
+ SetStatusMessagePGM(PSTR("EEPROM reset"));
+}
+
+void DGUSScreenHandler::StoreSettings(char *buff) {
+ eeprom_data_t data;
+
+ static_assert(sizeof(data) <= ExtUI::eeprom_data_size, "sizeof(eeprom_data_t) > eeprom_data_size.");
+
+ data.initialized = true;
+ data.volume = dgus_display.GetVolume();
+ data.brightness = dgus_display.GetBrightness();
+ data.abl = (ExtUI::getLevelingActive() && ExtUI::getMeshValid());
+
+ memcpy(buff, &data, sizeof(data));
+}
+
+void DGUSScreenHandler::LoadSettings(const char *buff) {
+ eeprom_data_t data;
+
+ static_assert(sizeof(data) <= ExtUI::eeprom_data_size, "sizeof(eeprom_data_t) > eeprom_data_size.");
+
+ memcpy(&data, buff, sizeof(data));
+
+ dgus_display.SetVolume(data.initialized ? data.volume : DGUS_DEFAULT_VOLUME);
+ dgus_display.SetBrightness(data.initialized ? data.brightness : DGUS_DEFAULT_BRIGHTNESS);
+
+ if (data.initialized) {
+ leveling_active = (data.abl && ExtUI::getMeshValid());
+
+ ExtUI::setLevelingActive(leveling_active);
+ }
+}
+
+void DGUSScreenHandler::ConfigurationStoreWritten(bool success) {
+ if (!success) {
+ SetStatusMessagePGM(PSTR("EEPROM write failed"));
+ }
+}
+
+void DGUSScreenHandler::ConfigurationStoreRead(bool success) {
+ if (!success) {
+ SetStatusMessagePGM(PSTR("EEPROM read failed"));
+ }
+ else if (!settings_ready) {
+ settings_ready = true;
+
+ Ready();
+ }
+}
+
+void DGUSScreenHandler::PlayTone(const uint16_t frequency, const uint16_t duration) {
+ UNUSED(duration);
+
+ if (frequency >= 1 && frequency <= 255) {
+ if (duration >= 1 && duration <= 255) {
+ dgus_display.PlaySound((uint8_t)frequency, (uint8_t)duration);
+ }
+ else {
+ dgus_display.PlaySound((uint8_t)frequency);
+ }
+ }
+}
+
+void DGUSScreenHandler::MeshUpdate(const int8_t xpos, const int8_t ypos) {
+ if (current_screen != DGUS_Screen::LEVELING_PROBING) {
+ if (current_screen == DGUS_Screen::LEVELING_AUTOMATIC) {
+ TriggerFullUpdate();
+ }
+
+ return;
+ }
+
+ uint8_t point = ypos * GRID_MAX_POINTS_X + xpos;
+ probing_icons[point < 16 ? 0 : 1] |= (1U << (point % 16));
+
+ if (xpos >= GRID_MAX_POINTS_X - 1
+ && ypos >= GRID_MAX_POINTS_Y - 1
+ && !ExtUI::getMeshValid()) {
+ probing_icons[0] = 0;
+ probing_icons[1] = 0;
+ }
+
+ TriggerFullUpdate();
+}
+
+void DGUSScreenHandler::PrintTimerStarted() {
+ TriggerScreenChange(DGUS_Screen::PRINT_STATUS);
+}
+
+void DGUSScreenHandler::PrintTimerPaused() {
+ dgus_display.PlaySound(3);
+
+ TriggerFullUpdate();
+}
+
+void DGUSScreenHandler::PrintTimerStopped() {
+ if (current_screen != DGUS_Screen::PRINT_STATUS
+ && current_screen != DGUS_Screen::PRINT_ADJUST) {
+ return;
+ }
+
+ dgus_display.PlaySound(3);
+
+ TriggerScreenChange(DGUS_Screen::PRINT_FINISHED);
+}
+
+void DGUSScreenHandler::FilamentRunout(const ExtUI::extruder_t extruder) {
+ char buffer[21];
+ snprintf_P(buffer, sizeof(buffer), PSTR("Filament runout E%d"), extruder);
+
+ SetStatusMessage(buffer);
+
+ dgus_display.PlaySound(3);
+}
+
+#if ENABLED(SDSUPPORT)
+
+ void DGUSScreenHandler::SDCardInserted() {
+ if (current_screen == DGUS_Screen::HOME) {
+ TriggerScreenChange(DGUS_Screen::PRINT);
+ }
+ }
+
+ void DGUSScreenHandler::SDCardRemoved() {
+ if (current_screen == DGUS_Screen::PRINT) {
+ TriggerScreenChange(DGUS_Screen::HOME);
+ }
+ }
+
+ void DGUSScreenHandler::SDCardError() {
+ SetStatusMessagePGM(GET_TEXT(MSG_MEDIA_READ_ERROR));
+
+ if (current_screen == DGUS_Screen::PRINT) {
+ TriggerScreenChange(DGUS_Screen::HOME);
+ }
+ }
+
+#endif // SDSUPPORT
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+
+ void DGUSScreenHandler::PowerLossResume() {
+ MoveToScreen(DGUS_Screen::POWERLOSS, true);
+ }
+
+#endif // POWER_LOSS_RECOVERY
+
+#if HAS_PID_HEATING
+
+ void DGUSScreenHandler::PidTuning(const ExtUI::result_t rst) {
+ switch (rst) {
+ case ExtUI::PID_STARTED:
+ SetStatusMessagePGM(GET_TEXT(MSG_PID_AUTOTUNE));
+ break;
+ case ExtUI::PID_BAD_EXTRUDER_NUM:
+ SetStatusMessagePGM(GET_TEXT(MSG_PID_BAD_EXTRUDER_NUM));
+ break;
+ case ExtUI::PID_TEMP_TOO_HIGH:
+ SetStatusMessagePGM(GET_TEXT(MSG_PID_TEMP_TOO_HIGH));
+ break;
+ case ExtUI::PID_TUNING_TIMEOUT:
+ SetStatusMessagePGM(GET_TEXT(MSG_PID_TIMEOUT));
+ break;
+ case ExtUI::PID_DONE:
+ SetStatusMessagePGM(GET_TEXT(MSG_PID_AUTOTUNE_DONE));
+ break;
+ default:
+ return;
+ }
+
+ dgus_display.PlaySound(3);
+ }
+
+#endif // HAS_PID_HEATING
+
+void DGUSScreenHandler::SetMessageLine(const char* msg, uint8_t line) {
+ switch (line) {
+ default: return;
+ case 1:
+ dgus_display.WriteString((uint16_t)DGUS_Addr::MESSAGE_Line1, msg, DGUS_LINE_LEN, true, true);
+ break;
+ case 2:
+ dgus_display.WriteString((uint16_t)DGUS_Addr::MESSAGE_Line2, msg, DGUS_LINE_LEN, true, true);
+ break;
+ case 3:
+ dgus_display.WriteString((uint16_t)DGUS_Addr::MESSAGE_Line3, msg, DGUS_LINE_LEN, true, true);
+ break;
+ case 4:
+ dgus_display.WriteString((uint16_t)DGUS_Addr::MESSAGE_Line4, msg, DGUS_LINE_LEN, true, true);
+ break;
+ }
+}
+
+void DGUSScreenHandler::SetMessageLinePGM(PGM_P msg, uint8_t line) {
+ switch (line) {
+ default: return;
+ case 1:
+ dgus_display.WriteStringPGM((uint16_t)DGUS_Addr::MESSAGE_Line1, msg, DGUS_LINE_LEN, true, true);
+ break;
+ case 2:
+ dgus_display.WriteStringPGM((uint16_t)DGUS_Addr::MESSAGE_Line2, msg, DGUS_LINE_LEN, true, true);
+ break;
+ case 3:
+ dgus_display.WriteStringPGM((uint16_t)DGUS_Addr::MESSAGE_Line3, msg, DGUS_LINE_LEN, true, true);
+ break;
+ case 4:
+ dgus_display.WriteStringPGM((uint16_t)DGUS_Addr::MESSAGE_Line4, msg, DGUS_LINE_LEN, true, true);
+ break;
+ }
+}
+
+void DGUSScreenHandler::SetStatusMessage(const char* msg, const millis_t duration) {
+ dgus_display.WriteString((uint16_t)DGUS_Addr::MESSAGE_Status, msg, DGUS_STATUS_LEN, false, true);
+
+ status_expire = (duration > 0 ? ExtUI::safe_millis() + duration : 0);
+}
+
+void DGUSScreenHandler::SetStatusMessagePGM(PGM_P msg, const millis_t duration) {
+ dgus_display.WriteStringPGM((uint16_t)DGUS_Addr::MESSAGE_Status, msg, DGUS_STATUS_LEN, false, true);
+
+ status_expire = (duration > 0 ? ExtUI::safe_millis() + duration : 0);
+}
+
+void DGUSScreenHandler::ShowWaitScreen(DGUS_Screen return_screen, bool has_continue) {
+ if (return_screen != DGUS_Screen::WAIT) {
+ wait_return_screen = return_screen;
+ }
+ wait_continue = has_continue;
+
+ TriggerScreenChange(DGUS_Screen::WAIT);
+}
+
+DGUS_Screen DGUSScreenHandler::GetCurrentScreen() {
+ return current_screen;
+}
+
+void DGUSScreenHandler::TriggerScreenChange(DGUS_Screen screen) {
+ new_screen = screen;
+}
+
+void DGUSScreenHandler::TriggerFullUpdate() {
+ full_update = true;
+}
+
+void DGUSScreenHandler::TriggerEEPROMSave() {
+ eeprom_save = ExtUI::safe_millis() + 500;
+}
+
+bool DGUSScreenHandler::IsPrinterIdle() {
+ return (!ExtUI::commandsInQueue()
+ && !ExtUI::isMoving());
+}
+
+const DGUS_Addr* DGUSScreenHandler::FindScreenAddrList(DGUS_Screen screen) {
+ DGUS_ScreenAddrList list;
+ const DGUS_ScreenAddrList *map = screen_addr_list_map;
+
+ do {
+ memcpy_P(&list, map, sizeof(*map));
+ if (!list.addr_list) break;
+ if (list.screen == screen) {
+ return list.addr_list;
+ }
+ } while (++map);
+
+ return nullptr;
+}
+
+bool DGUSScreenHandler::CallScreenSetup(DGUS_Screen screen) {
+ DGUS_ScreenSetup setup;
+ const DGUS_ScreenSetup *list = screen_setup_list;
+
+ do {
+ memcpy_P(&setup, list, sizeof(*list));
+ if (!setup.setup_fn) break;
+ if (setup.screen == screen) {
+ return setup.setup_fn();
+ }
+ } while (++list);
+
+ return true;
+}
+
+void DGUSScreenHandler::MoveToScreen(DGUS_Screen screen, bool abort_wait) {
+ if (current_screen == DGUS_Screen::KILL) {
+ return;
+ }
+
+ if (current_screen == DGUS_Screen::WAIT) {
+ if (screen != DGUS_Screen::WAIT) {
+ wait_return_screen = screen;
+ }
+
+ if (!abort_wait) return;
+
+ if (wait_continue && wait_for_user) {
+ ExtUI::setUserConfirmed();
+ }
+ }
+
+ if (!CallScreenSetup(screen)) return;
+
+ if (!SendScreenVPData(screen, true)) {
+ DEBUG_ECHOLNPGM("SendScreenVPData failed");
+ return;
+ }
+
+ current_screen = screen;
+ dgus_display.SwitchScreen(current_screen);
+}
+
+bool DGUSScreenHandler::SendScreenVPData(DGUS_Screen screen, bool complete_update) {
+ if (complete_update) {
+ full_update = false;
+ }
+
+ const DGUS_Addr *list = FindScreenAddrList(screen);
+
+ while (true) {
+ if (!list) return true; // Nothing left to send
+
+ const uint16_t addr = pgm_read_word(list++);
+ if (!addr) return true; // Nothing left to send
+
+ DGUS_VP vp;
+ if (!DGUS_PopulateVP((DGUS_Addr)addr, &vp)) continue; // Invalid VP
+ if (!vp.tx_handler) continue; // Nothing to send
+ if (!complete_update && !(vp.flags & VPFLAG_AUTOUPLOAD)) continue; // Unnecessary VP
+
+ uint8_t expected_tx = 6 + vp.size; // 6 bytes header + payload.
+ const millis_t try_until = ExtUI::safe_millis() + 1000;
+
+ while (expected_tx > dgus_display.GetFreeTxBuffer()) {
+ if (ELAPSED(ExtUI::safe_millis(), try_until)) return false; // Stop trying after 1 second
+
+ dgus_display.FlushTx(); // Flush the TX buffer
+ delay(50);
+ }
+
+ vp.tx_handler(vp);
+ }
+}
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSScreenHandler.h b/Marlin/src/lcd/extui/dgus_reloaded/DGUSScreenHandler.h
new file mode 100644
index 000000000000..056757fedf6c
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSScreenHandler.h
@@ -0,0 +1,152 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+#include "config/DGUS_Addr.h"
+#include "config/DGUS_Data.h"
+#include "config/DGUS_Screen.h"
+#include "config/DGUS_Constants.h"
+
+#include "../ui_api.h"
+#include "../../../inc/MarlinConfigPre.h"
+
+class DGUSScreenHandler {
+public:
+ DGUSScreenHandler() = default;
+
+ static void Init();
+ static void Ready();
+ static void Loop();
+
+ static void PrinterKilled(PGM_P error, PGM_P component);
+ static void UserConfirmRequired(const char * const msg);
+ static void SettingsReset();
+ static void StoreSettings(char *buff);
+ static void LoadSettings(const char *buff);
+ static void ConfigurationStoreWritten(bool success);
+ static void ConfigurationStoreRead(bool success);
+
+ static void PlayTone(const uint16_t frequency, const uint16_t duration);
+ static void MeshUpdate(const int8_t xpos, const int8_t ypos);
+ static void PrintTimerStarted();
+ static void PrintTimerPaused();
+ static void PrintTimerStopped();
+ static void FilamentRunout(const ExtUI::extruder_t extruder);
+
+ #if ENABLED(SDSUPPORT)
+ /// Marlin informed us that a new SD has been inserted.
+ static void SDCardInserted();
+ /// Marlin informed us that the SD Card has been removed().
+ static void SDCardRemoved();
+ /// Marlin informed us about a bad SD Card.
+ static void SDCardError();
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ static void PowerLossResume();
+ #endif
+
+ #if HAS_PID_HEATING
+ static void PidTuning(const ExtUI::result_t rst);
+ #endif
+
+ static void SetMessageLine(const char* msg, uint8_t line);
+ static void SetMessageLinePGM(PGM_P msg, uint8_t line);
+
+ static void SetStatusMessage(const char* msg, const millis_t duration = DGUS_STATUS_EXPIRATION_MS);
+ static void SetStatusMessagePGM(PGM_P msg, const millis_t duration = DGUS_STATUS_EXPIRATION_MS);
+
+ static void ShowWaitScreen(DGUS_Screen return_screen, bool has_continue = false);
+
+ static DGUS_Screen GetCurrentScreen();
+ static void TriggerScreenChange(DGUS_Screen screen);
+ static void TriggerFullUpdate();
+
+ static void TriggerEEPROMSave();
+
+ static bool IsPrinterIdle();
+
+ static uint8_t debug_count;
+
+ #if ENABLED(SDSUPPORT)
+ static ExtUI::FileList filelist;
+ static uint16_t filelist_offset;
+ static int16_t filelist_selected;
+ #endif
+
+ static DGUS_Data::StepSize offset_steps;
+ static DGUS_Data::StepSize move_steps;
+
+ static uint16_t probing_icons[2];
+
+ static DGUS_Data::Extruder filament_extruder;
+ static uint16_t filament_length;
+
+ static char gcode[DGUS_GCODE_LEN + 1];
+
+ static DGUS_Data::Heater pid_heater;
+ static uint16_t pid_temp;
+ static uint8_t pid_cycles;
+
+ static bool wait_continue;
+
+ static bool leveling_active;
+
+private:
+ static const DGUS_Addr* FindScreenAddrList(DGUS_Screen screen);
+ static bool CallScreenSetup(DGUS_Screen screen);
+
+ static void MoveToScreen(DGUS_Screen screen, bool abort_wait = false);
+ static bool SendScreenVPData(DGUS_Screen screen, bool complete_update);
+
+ static bool settings_ready;
+ static bool booted;
+
+ static DGUS_Screen current_screen;
+ static DGUS_Screen new_screen;
+ static bool full_update;
+
+ static DGUS_Screen wait_return_screen;
+
+ static millis_t status_expire;
+ static millis_t eeprom_save;
+
+ typedef struct {
+ bool initialized;
+ uint8_t volume;
+ uint8_t brightness;
+ bool abl;
+ } eeprom_data_t;
+};
+
+extern DGUSScreenHandler dgus_screen_handler;
+
+extern const char DGUS_MSG_HOMING_REQUIRED[],
+ DGUS_MSG_BUSY[],
+ DGUS_MSG_UNDEF[],
+ DGUS_MSG_HOMING[],
+ DGUS_MSG_FW_OUTDATED[],
+ DGUS_MSG_ABL_REQUIRED[];
+
+extern const char DGUS_CMD_HOME[],
+ DGUS_CMD_EEPROM_SAVE[];
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSSetupHandler.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSSetupHandler.cpp
new file mode 100644
index 000000000000..c12282c4efae
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSSetupHandler.cpp
@@ -0,0 +1,209 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUSSetupHandler.h"
+
+#include "DGUSDisplay.h"
+#include "DGUSScreenHandler.h"
+
+#include "../../../gcode/queue.h"
+
+#if ENABLED(SDSUPPORT)
+ bool DGUSSetupHandler::Print() {
+ dgus_screen_handler.filelist.refresh();
+
+ while (!dgus_screen_handler.filelist.isAtRootDir()) {
+ dgus_screen_handler.filelist.upDir();
+ }
+
+ dgus_screen_handler.filelist_offset = 0;
+ dgus_screen_handler.filelist_selected = -1;
+
+ return true;
+ }
+#endif
+
+bool DGUSSetupHandler::PrintStatus() {
+ if (printingIsActive() || printingIsPaused()) {
+ return true;
+ }
+
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::PRINT_FINISHED);
+ return false;
+}
+
+bool DGUSSetupHandler::PrintAdjust() {
+ if (printingIsActive() || printingIsPaused()) {
+ return true;
+ }
+
+ dgus_screen_handler.TriggerScreenChange(DGUS_Screen::PRINT_FINISHED);
+ return false;
+}
+
+bool DGUSSetupHandler::LevelingMenu() {
+ ExtUI::setLevelingActive(dgus_screen_handler.leveling_active);
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return false;
+ }
+
+ if (ExtUI::isPositionKnown()) {
+ if (ExtUI::getAxisPosition_mm(ExtUI::Z) < 10.0f) {
+ queue.enqueue_now_P(PSTR("G0Z10"));
+ }
+
+ return true;
+ }
+
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLinePGM(DGUS_MSG_HOMING, 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+ dgus_screen_handler.ShowWaitScreen(DGUS_Screen::LEVELING_MENU);
+
+ queue.enqueue_now_P(DGUS_CMD_HOME);
+
+ return false;
+}
+
+bool DGUSSetupHandler::LevelingManual() {
+ ExtUI::setLevelingActive(false);
+
+ if (ExtUI::isPositionKnown()) {
+ return true;
+ }
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return false;
+ }
+
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLinePGM(DGUS_MSG_HOMING, 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+ dgus_screen_handler.ShowWaitScreen(DGUS_Screen::LEVELING_MANUAL);
+
+ queue.enqueue_now_P(DGUS_CMD_HOME);
+
+ return false;
+}
+
+bool DGUSSetupHandler::LevelingOffset() {
+ dgus_screen_handler.offset_steps = DGUS_Data::StepSize::MMP1;
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return false;
+ }
+
+ if (ExtUI::isPositionKnown()) {
+ if (ExtUI::getAxisPosition_mm(ExtUI::Z) < 4.0f) {
+ queue.enqueue_now_P(PSTR("G0Z4"));
+ }
+
+ char buffer[20];
+ snprintf_P(buffer, sizeof(buffer), PSTR("G0X%dY%d"), DGUS_LEVEL_CENTER_X, DGUS_LEVEL_CENTER_Y);
+
+ queue.enqueue_one_now(buffer);
+ queue.enqueue_now_P(PSTR("G0Z0"));
+
+ return true;
+ }
+
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 1);
+ dgus_screen_handler.SetMessageLinePGM(DGUS_MSG_HOMING, 2);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 3);
+ dgus_screen_handler.SetMessageLinePGM(NUL_STR, 4);
+ dgus_screen_handler.ShowWaitScreen(DGUS_Screen::LEVELING_OFFSET);
+
+ queue.enqueue_now_P(DGUS_CMD_HOME);
+
+ return false;
+}
+
+bool DGUSSetupHandler::LevelingAutomatic() {
+ if (ExtUI::getMeshValid()) {
+ dgus_screen_handler.leveling_active = true;
+
+ ExtUI::setLevelingActive(true);
+ }
+
+ return true;
+}
+
+bool DGUSSetupHandler::LevelingProbing() {
+ dgus_screen_handler.probing_icons[0] = 0;
+ dgus_screen_handler.probing_icons[1] = 0;
+
+ return true;
+}
+
+bool DGUSSetupHandler::Filament() {
+ dgus_screen_handler.filament_extruder = DGUS_Data::Extruder::CURRENT;
+ dgus_screen_handler.filament_length = DGUS_DEFAULT_FILAMENT_LEN;
+
+ return true;
+}
+
+bool DGUSSetupHandler::Move() {
+ dgus_screen_handler.move_steps = DGUS_Data::StepSize::MM10;
+
+ if (!dgus_screen_handler.IsPrinterIdle()) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_BUSY);
+ return false;
+ }
+
+ return true;
+}
+
+bool DGUSSetupHandler::Gcode() {
+ ZERO(dgus_screen_handler.gcode);
+
+ if (dgus_display.gui_version < 0x30 || dgus_display.os_version < 0x21) {
+ dgus_screen_handler.SetStatusMessagePGM(DGUS_MSG_FW_OUTDATED);
+ return false;
+ }
+
+ return true;
+}
+
+bool DGUSSetupHandler::PID() {
+ dgus_screen_handler.pid_heater = DGUS_Data::Heater::H0;
+ dgus_screen_handler.pid_temp = DGUS_PLA_TEMP_HOTEND;
+
+ return true;
+}
+
+bool DGUSSetupHandler::Infos() {
+ dgus_screen_handler.debug_count = 0;
+
+ return true;
+}
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSSetupHandler.h b/Marlin/src/lcd/extui/dgus_reloaded/DGUSSetupHandler.h
new file mode 100644
index 000000000000..b1159ff7083c
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSSetupHandler.h
@@ -0,0 +1,43 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+namespace DGUSSetupHandler {
+
+ #if ENABLED(SDSUPPORT)
+ bool Print();
+ #endif
+ bool PrintStatus();
+ bool PrintAdjust();
+ bool LevelingMenu();
+ bool LevelingOffset();
+ bool LevelingManual();
+ bool LevelingAutomatic();
+ bool LevelingProbing();
+ bool Filament();
+ bool Move();
+ bool Gcode();
+ bool PID();
+ bool Infos();
+
+}
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp
new file mode 100644
index 000000000000..04362b07e8ed
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp
@@ -0,0 +1,632 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUSTxHandler.h"
+
+#include "DGUSScreenHandler.h"
+#include "config/DGUS_Data.h"
+
+#include "../ui_api.h"
+#include "../../../module/stepper.h"
+#include "../../../module/printcounter.h"
+#if ENABLED(ADVANCED_PAUSE_FEATURE)
+ #include "../../../feature/pause.h"
+#endif
+
+#if ENABLED(SDSUPPORT)
+ void DGUSTxHandler::SetFileControlState(int file, bool state) {
+ DGUS_Control control;
+
+ switch (file) {
+ default: return;
+ case 0:
+ control = DGUS_Control::FILE0;
+ break;
+ case 1:
+ control = DGUS_Control::FILE1;
+ break;
+ case 2:
+ control = DGUS_Control::FILE2;
+ break;
+ case 3:
+ control = DGUS_Control::FILE3;
+ break;
+ case 4:
+ control = DGUS_Control::FILE4;
+ break;
+ }
+
+ if (state) {
+ dgus_display.EnableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ control);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ control);
+ }
+ }
+
+ void DGUSTxHandler::FileType(DGUS_VP &vp) {
+ // Batch send
+ uint16_t data[DGUS_FILE_COUNT];
+
+ for (int i = 0; i < DGUS_FILE_COUNT; i++) {
+ if (!dgus_screen_handler.filelist.seek(dgus_screen_handler.filelist_offset + i)) {
+ data[i] = Swap16((uint16_t)DGUS_Data::SDType::NONE);
+
+ SetFileControlState(i, false);
+ continue;
+ }
+
+ data[i] = dgus_screen_handler.filelist.isDir() ?
+ Swap16((uint16_t)DGUS_Data::SDType::DIRECTORY)
+ : Swap16((uint16_t)DGUS_Data::SDType::FILE);
+
+ SetFileControlState(i, true);
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, data, sizeof(*data) * DGUS_FILE_COUNT);
+ }
+
+ void DGUSTxHandler::FileName(DGUS_VP &vp) {
+ uint8_t offset;
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::SD_FileName0:
+ offset = 0;
+ break;
+ case DGUS_Addr::SD_FileName1:
+ offset = 1;
+ break;
+ case DGUS_Addr::SD_FileName2:
+ offset = 2;
+ break;
+ case DGUS_Addr::SD_FileName3:
+ offset = 3;
+ break;
+ case DGUS_Addr::SD_FileName4:
+ offset = 4;
+ break;
+ }
+
+ if (dgus_screen_handler.filelist.seek(dgus_screen_handler.filelist_offset + offset)) {
+ dgus_display.WriteString((uint16_t)vp.addr, dgus_screen_handler.filelist.filename(), vp.size);
+ }
+ else {
+ dgus_display.WriteStringPGM((uint16_t)vp.addr, NUL_STR, vp.size);
+ }
+ }
+
+ void DGUSTxHandler::ScrollIcons(DGUS_VP &vp) {
+ uint16_t icons = 0;
+
+ if (!dgus_screen_handler.filelist.isAtRootDir()) {
+ icons |= (uint16_t)DGUS_Data::ScrollIcon::GO_BACK;
+
+ dgus_display.EnableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::GO_BACK);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::GO_BACK);
+ }
+
+ if (dgus_screen_handler.filelist_offset > 0) {
+ icons |= (uint16_t)DGUS_Data::ScrollIcon::UP;
+
+ dgus_display.EnableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::SCROLL_UP);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::SCROLL_UP);
+ }
+
+ if (dgus_screen_handler.filelist_offset + DGUS_FILE_COUNT < dgus_screen_handler.filelist.count()) {
+ icons |= (uint16_t)DGUS_Data::ScrollIcon::DOWN;
+
+ dgus_display.EnableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::SCROLL_DOWN);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::PRINT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::SCROLL_DOWN);
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(icons));
+ }
+
+ void DGUSTxHandler::SelectedFileName(DGUS_VP &vp) {
+ if (dgus_screen_handler.filelist_selected < 0
+ || !dgus_screen_handler.filelist.seek(dgus_screen_handler.filelist_selected)) {
+ dgus_display.WriteStringPGM((uint16_t)vp.addr, NUL_STR, vp.size);
+ return;
+ }
+
+ dgus_display.WriteString((uint16_t)vp.addr, dgus_screen_handler.filelist.filename(), vp.size);
+ }
+#endif // SDSUPPORT
+
+void DGUSTxHandler::PositionZ(DGUS_VP &vp) {
+ float position = ExtUI::isAxisPositionKnown(ExtUI::Z) ?
+ planner.get_axis_position_mm(Z_AXIS)
+ : 0;
+
+ const int16_t data = dgus_display.ToFixedPoint(position);
+ dgus_display.Write((uint16_t)vp.addr, Swap16(data));
+}
+
+void DGUSTxHandler::Ellapsed(DGUS_VP &vp) {
+ char buffer[21];
+ duration_t(print_job_timer.duration()).toString(buffer);
+
+ dgus_display.WriteString((uint16_t)vp.addr, buffer, vp.size);
+}
+
+void DGUSTxHandler::Percent(DGUS_VP &vp) {
+ uint16_t progress;
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::STATUS_Percent:
+ progress = constrain(ExtUI::getProgress_percent(), 0, 100);
+ break;
+ case DGUS_Addr::STATUS_Percent_Complete:
+ progress = 100;
+ break;
+ }
+
+ dgus_display.Write((uint16_t)DGUS_Addr::STATUS_Percent, Swap16(progress));
+}
+
+void DGUSTxHandler::StatusIcons(DGUS_VP &vp) {
+ uint16_t icons = 0;
+
+ if (printingIsActive()) {
+ icons |= (uint16_t)DGUS_Data::StatusIcon::PAUSE;
+
+ dgus_display.EnableControl(DGUS_Screen::PRINT_STATUS,
+ DGUSDisplay::POPUP_WINDOW,
+ DGUS_Control::PAUSE);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::PRINT_STATUS,
+ DGUSDisplay::POPUP_WINDOW,
+ DGUS_Control::PAUSE);
+ }
+
+ if (printingIsPaused()) {
+ icons |= (uint16_t)DGUS_Data::StatusIcon::RESUME;
+
+ dgus_display.EnableControl(DGUS_Screen::PRINT_STATUS,
+ DGUSDisplay::POPUP_WINDOW,
+ DGUS_Control::RESUME);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::PRINT_STATUS,
+ DGUSDisplay::POPUP_WINDOW,
+ DGUS_Control::RESUME);
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(icons));
+}
+
+void DGUSTxHandler::Flowrate(DGUS_VP &vp) {
+ int16_t flowrate;
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::ADJUST_Flowrate_CUR:
+ #if EXTRUDERS > 1
+ flowrate = ExtUI::getFlow_percent(ExtUI::getActiveTool());
+ #else
+ flowrate = ExtUI::getFlow_percent(ExtUI::E0);
+ #endif
+ break;
+ #if EXTRUDERS > 1
+ case DGUS_Addr::ADJUST_Flowrate_E0:
+ flowrate = ExtUI::getFlow_percent(ExtUI::E0);
+ break;
+ case DGUS_Addr::ADJUST_Flowrate_E1:
+ flowrate = ExtUI::getFlow_percent(ExtUI::E1);
+ break;
+ #endif
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(flowrate));
+}
+
+void DGUSTxHandler::TempMax(DGUS_VP &vp) {
+ uint16_t temp;
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::TEMP_Max_Bed:
+ temp = BED_MAX_TARGET;
+ break;
+ case DGUS_Addr::TEMP_Max_H0:
+ temp = HEATER_0_MAXTEMP - HOTEND_OVERSHOOT;
+ break;
+ #if HOTENDS > 1
+ case DGUS_Addr::TEMP_Max_H1:
+ temp = HEATER_1_MAXTEMP - HOTEND_OVERSHOOT;
+ break;
+ #endif
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(temp));
+}
+
+void DGUSTxHandler::StepperStatus(DGUS_VP &vp) {
+ if (X_ENABLE_READ() == X_ENABLE_ON
+ && Y_ENABLE_READ() == Y_ENABLE_ON
+ && Z_ENABLE_READ() == Z_ENABLE_ON) {
+ dgus_display.Write((uint16_t)vp.addr, Swap16((uint16_t)DGUS_Data::Status::ENABLED));
+ }
+ else {
+ dgus_display.Write((uint16_t)vp.addr, Swap16((uint16_t)DGUS_Data::Status::DISABLED));
+ }
+}
+
+void DGUSTxHandler::StepIcons(DGUS_VP &vp) {
+ if (!vp.extra) return;
+ uint16_t icons = 0;
+ DGUS_Data::StepSize size = *(DGUS_Data::StepSize*)vp.extra;
+
+ switch (size) {
+ case DGUS_Data::StepSize::MM10:
+ icons |= (uint16_t)DGUS_Data::StepIcon::MM10;
+ break;
+ case DGUS_Data::StepSize::MM1:
+ icons |= (uint16_t)DGUS_Data::StepIcon::MM1;
+ break;
+ case DGUS_Data::StepSize::MMP1:
+ icons |= (uint16_t)DGUS_Data::StepIcon::MMP1;
+ break;
+ case DGUS_Data::StepSize::MMP01:
+ icons |= (uint16_t)DGUS_Data::StepIcon::MMP01;
+ break;
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(icons));
+}
+
+void DGUSTxHandler::ABLDisableIcon(DGUS_VP &vp) {
+ uint16_t data;
+
+ if (ExtUI::getLevelingActive()) {
+ data = (uint16_t)DGUS_Data::Status::ENABLED;
+
+ dgus_display.EnableControl(DGUS_Screen::LEVELING_AUTOMATIC,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::DISABLE);
+ }
+ else {
+ data = (uint16_t)DGUS_Data::Status::DISABLED;
+
+ dgus_display.DisableControl(DGUS_Screen::LEVELING_AUTOMATIC,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::DISABLE);
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(data));
+}
+
+void DGUSTxHandler::ABLGrid(DGUS_VP &vp) {
+ // Batch send
+ int16_t data[DGUS_LEVEL_GRID_SIZE];
+ xy_uint8_t point;
+ int16_t fixed;
+
+ for (int i = 0; i < DGUS_LEVEL_GRID_SIZE; i++) {
+ point.x = i % GRID_MAX_POINTS_X;
+ point.y = i / GRID_MAX_POINTS_X;
+ fixed = dgus_display.ToFixedPoint(ExtUI::getMeshPoint(point));
+ data[i] = Swap16(fixed);
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, data, sizeof(*data) * DGUS_LEVEL_GRID_SIZE);
+}
+
+void DGUSTxHandler::FilamentIcons(DGUS_VP &vp) {
+ uint16_t icons = 0;
+
+ switch (dgus_screen_handler.filament_extruder) {
+ default: return;
+ case DGUS_Data::Extruder::CURRENT:
+ #if EXTRUDERS > 1
+ switch (ExtUI::getActiveTool()) {
+ default: break;
+ case ExtUI::E0:
+ icons |= (uint16_t)DGUS_Data::ExtruderIcon::E0;
+ break;
+ case ExtUI::E1:
+ icons |= (uint16_t)DGUS_Data::ExtruderIcon::E1;
+ break;
+ }
+ break;
+ #endif
+ case DGUS_Data::Extruder::E0:
+ icons |= (uint16_t)DGUS_Data::ExtruderIcon::E0;
+ break;
+ case DGUS_Data::Extruder::E1:
+ icons |= (uint16_t)DGUS_Data::ExtruderIcon::E1;
+ break;
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(icons));
+}
+
+void DGUSTxHandler::BLTouch(DGUS_VP &vp) {
+ #if ENABLED(BLTOUCH)
+ dgus_display.EnableControl(DGUS_Screen::SETTINGS_MENU2,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::EXTRA2);
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16((uint16_t)DGUS_Data::Status::ENABLED));
+ #else
+ dgus_display.DisableControl(DGUS_Screen::SETTINGS_MENU2,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::EXTRA2);
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16((uint16_t)DGUS_Data::Status::DISABLED));
+ #endif
+}
+
+void DGUSTxHandler::PIDIcons(DGUS_VP &vp) {
+ uint16_t icons = 0;
+
+ switch (dgus_screen_handler.pid_heater) {
+ default: return;
+ case DGUS_Data::Heater::BED:
+ icons |= (uint16_t)DGUS_Data::HeaterIcon::BED;
+ break;
+ case DGUS_Data::Heater::H0:
+ icons |= (uint16_t)DGUS_Data::HeaterIcon::H0;
+ break;
+ case DGUS_Data::Heater::H1:
+ icons |= (uint16_t)DGUS_Data::HeaterIcon::H1;
+ break;
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(icons));
+}
+
+void DGUSTxHandler::PIDKp(DGUS_VP &vp) {
+ float value;
+
+ switch (dgus_screen_handler.pid_heater) {
+ default: return;
+ #if ENABLED(PIDTEMPBED)
+ case DGUS_Data::Heater::BED:
+ value = ExtUI::getBedPIDValues_Kp();
+ break;
+ #endif
+ #if ENABLED(PIDTEMP)
+ case DGUS_Data::Heater::H0:
+ value = ExtUI::getPIDValues_Kp(ExtUI::E0);
+ break;
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ value = ExtUI::getPIDValues_Kp(ExtUI::E1);
+ break;
+ #endif
+ #endif
+ }
+
+ const int32_t data = dgus_display.ToFixedPoint(value);
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(data));
+}
+
+void DGUSTxHandler::PIDKi(DGUS_VP &vp) {
+ float value;
+
+ switch (dgus_screen_handler.pid_heater) {
+ default: return;
+ #if ENABLED(PIDTEMPBED)
+ case DGUS_Data::Heater::BED:
+ value = ExtUI::getBedPIDValues_Ki();
+ break;
+ #endif
+ #if ENABLED(PIDTEMP)
+ case DGUS_Data::Heater::H0:
+ value = ExtUI::getPIDValues_Ki(ExtUI::E0);
+ break;
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ value = ExtUI::getPIDValues_Ki(ExtUI::E1);
+ break;
+ #endif
+ #endif
+ }
+
+ const int32_t data = dgus_display.ToFixedPoint(value);
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(data));
+}
+
+void DGUSTxHandler::PIDKd(DGUS_VP &vp) {
+ float value;
+
+ switch (dgus_screen_handler.pid_heater) {
+ default: return;
+ #if ENABLED(PIDTEMPBED)
+ case DGUS_Data::Heater::BED:
+ value = ExtUI::getBedPIDValues_Kd();
+ break;
+ #endif
+ #if ENABLED(PIDTEMP)
+ case DGUS_Data::Heater::H0:
+ value = ExtUI::getPIDValues_Kd(ExtUI::E0);
+ break;
+ #if HOTENDS > 1
+ case DGUS_Data::Heater::H1:
+ value = ExtUI::getPIDValues_Kd(ExtUI::E1);
+ break;
+ #endif
+ #endif
+ }
+
+ const int32_t data = dgus_display.ToFixedPoint(value);
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(data));
+}
+
+void DGUSTxHandler::BuildVolume(DGUS_VP &vp) {
+ char buffer[vp.size];
+ snprintf_P(buffer, vp.size, PSTR("%dx%dx%d"), X_BED_SIZE, Y_BED_SIZE, (Z_MAX_POS - Z_MIN_POS));
+
+ dgus_display.WriteString((uint16_t)vp.addr, buffer, vp.size);
+}
+
+void DGUSTxHandler::TotalPrints(DGUS_VP &vp) {
+ #if ENABLED(PRINTCOUNTER)
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(print_job_timer.getStats().totalPrints));
+ #else
+ UNUSED(vp);
+ #endif
+}
+
+void DGUSTxHandler::FinishedPrints(DGUS_VP &vp) {
+ #if ENABLED(PRINTCOUNTER)
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(print_job_timer.getStats().finishedPrints));
+ #else
+ UNUSED(vp);
+ #endif
+}
+
+void DGUSTxHandler::PrintTime(DGUS_VP &vp) {
+ #if ENABLED(PRINTCOUNTER)
+ char buffer[21];
+ ExtUI::getTotalPrintTime_str(buffer);
+
+ dgus_display.WriteString((uint16_t)vp.addr, buffer, vp.size);
+ #else
+ dgus_display.WriteStringPGM((uint16_t)vp.addr, DGUS_MSG_UNDEF, vp.size);
+ #endif
+}
+
+void DGUSTxHandler::LongestPrint(DGUS_VP &vp) {
+ #if ENABLED(PRINTCOUNTER)
+ char buffer[21];
+ ExtUI::getLongestPrint_str(buffer);
+
+ dgus_display.WriteString((uint16_t)vp.addr, buffer, vp.size);
+ #else
+ dgus_display.WriteStringPGM((uint16_t)vp.addr, DGUS_MSG_UNDEF, vp.size);
+ #endif
+}
+
+void DGUSTxHandler::FilamentUsed(DGUS_VP &vp) {
+ #if ENABLED(PRINTCOUNTER)
+ char buffer[21];
+ ExtUI::getFilamentUsed_str(buffer);
+
+ dgus_display.WriteString((uint16_t)vp.addr, buffer, vp.size);
+ #else
+ dgus_display.WriteStringPGM((uint16_t)vp.addr, DGUS_MSG_UNDEF, vp.size);
+ #endif
+}
+
+void DGUSTxHandler::WaitIcons(DGUS_VP &vp) {
+ uint16_t icons = 0;
+
+ if (printingIsPaused()
+ #if ENABLED(ADVANCED_PAUSE_FEATURE)
+ && did_pause_print
+ #endif
+ ) {
+ icons |= (uint16_t)DGUS_Data::WaitIcon::ABORT;
+
+ dgus_display.EnableControl(DGUS_Screen::WAIT,
+ DGUSDisplay::POPUP_WINDOW,
+ DGUS_Control::ABORT);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::WAIT,
+ DGUSDisplay::POPUP_WINDOW,
+ DGUS_Control::ABORT);
+ }
+
+ if (dgus_screen_handler.wait_continue) {
+ icons |= (uint16_t)DGUS_Data::WaitIcon::CONTINUE;
+
+ dgus_display.EnableControl(DGUS_Screen::WAIT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::CONTINUE);
+ }
+ else {
+ dgus_display.DisableControl(DGUS_Screen::WAIT,
+ DGUSDisplay::RETURN_KEY_CODE,
+ DGUS_Control::CONTINUE);
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(icons));
+}
+
+void DGUSTxHandler::FanSpeed(DGUS_VP &vp) {
+ uint16_t fan_speed;
+
+ switch (vp.addr) {
+ default: return;
+ case DGUS_Addr::FAN0_Speed: fan_speed = ExtUI::getTargetFan_percent(ExtUI::FAN0); break;
+ }
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(fan_speed));
+}
+
+void DGUSTxHandler::Volume(DGUS_VP &vp) {
+ const uint16_t volume = dgus_display.GetVolume();
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(volume));
+}
+
+void DGUSTxHandler::Brightness(DGUS_VP &vp) {
+ const uint16_t brightness = dgus_display.GetBrightness();
+
+ dgus_display.Write((uint16_t)vp.addr, Swap16(brightness));
+}
+
+void DGUSTxHandler::ExtraToString(DGUS_VP &vp) {
+ if (!vp.size || !vp.extra) return;
+
+ dgus_display.WriteString((uint16_t)vp.addr, vp.extra, vp.size, true, false, false);
+}
+
+void DGUSTxHandler::ExtraPGMToString(DGUS_VP &vp) {
+ if (!vp.size || !vp.extra) return;
+
+ dgus_display.WriteStringPGM((uint16_t)vp.addr, vp.extra, vp.size, true, false, false);
+}
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.h b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.h
new file mode 100644
index 000000000000..5715abbedfd7
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.h
@@ -0,0 +1,127 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+#include "DGUSDisplay.h"
+#include "definition/DGUS_VP.h"
+
+namespace DGUSTxHandler {
+
+ #if ENABLED(SDSUPPORT)
+ void SetFileControlState(int, bool);
+ void FileType(DGUS_VP &);
+ void FileName(DGUS_VP &);
+ void ScrollIcons(DGUS_VP &);
+ void SelectedFileName(DGUS_VP &);
+ #endif
+
+ void PositionZ(DGUS_VP &);
+ void Ellapsed(DGUS_VP &);
+ void Percent(DGUS_VP &);
+ void StatusIcons(DGUS_VP &);
+
+ void Flowrate(DGUS_VP &);
+
+ void TempMax(DGUS_VP &);
+
+ void StepperStatus(DGUS_VP &);
+
+ void StepIcons(DGUS_VP &);
+
+ void ABLDisableIcon(DGUS_VP &);
+ void ABLGrid(DGUS_VP &);
+
+ void FilamentIcons(DGUS_VP &);
+
+ void BLTouch(DGUS_VP &);
+
+ void PIDIcons(DGUS_VP &);
+ void PIDKp(DGUS_VP &);
+ void PIDKi(DGUS_VP &);
+ void PIDKd(DGUS_VP &);
+
+ void BuildVolume(DGUS_VP &);
+ void TotalPrints(DGUS_VP &);
+ void FinishedPrints(DGUS_VP &);
+ void PrintTime(DGUS_VP &);
+ void LongestPrint(DGUS_VP &);
+ void FilamentUsed(DGUS_VP &);
+
+ void WaitIcons(DGUS_VP &);
+
+ void FanSpeed(DGUS_VP &);
+
+ void Volume(DGUS_VP &);
+
+ void Brightness(DGUS_VP &);
+
+ void ExtraToString(DGUS_VP &);
+ void ExtraPGMToString(DGUS_VP &);
+
+ template
+ void ExtraToInteger(DGUS_VP &vp) {
+ if (!vp.size || !vp.extra) return;
+ switch (vp.size) {
+ default: return;
+ case 1: {
+ const uint8_t data = (uint8_t)(*(T*)vp.extra);
+ dgus_display.Write((uint16_t)vp.addr, data);
+ break;
+ }
+ case 2: {
+ const uint16_t data = (uint16_t)(*(T*)vp.extra);
+ dgus_display.Write((uint16_t)vp.addr, Swap16(data));
+ break;
+ }
+ case 4: {
+ const uint32_t data = (uint32_t)(*(T*)vp.extra);
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(data));
+ break;
+ }
+ }
+ }
+
+ template
+ void ExtraToFixedPoint(DGUS_VP &vp) {
+ if (!vp.size || !vp.extra) return;
+ switch (vp.size) {
+ default: return;
+ case 1: {
+ const uint8_t data = dgus_display.ToFixedPoint(*(T*)vp.extra);
+ dgus_display.Write((uint16_t)vp.addr, data);
+ break;
+ }
+ case 2: {
+ const uint16_t data = dgus_display.ToFixedPoint(*(T*)vp.extra);
+ dgus_display.Write((uint16_t)vp.addr, Swap16(data));
+ break;
+ }
+ case 4: {
+ const uint32_t data = dgus_display.ToFixedPoint(*(T*)vp.extra);
+ dgus_display.Write((uint16_t)vp.addr, dgus_display.SwapBytes(data));
+ break;
+ }
+ }
+ }
+
+}
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Addr.h b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Addr.h
new file mode 100644
index 000000000000..de64fe2b106b
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Addr.h
@@ -0,0 +1,173 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+constexpr uint8_t DGUS_LINE_LEN = 32;
+constexpr uint8_t DGUS_STATUS_LEN = 32;
+constexpr uint8_t DGUS_FILE_COUNT = 5;
+constexpr uint8_t DGUS_FILENAME_LEN = 32;
+constexpr uint8_t DGUS_ELLAPSED_LEN = 15;
+constexpr uint8_t DGUS_LEVEL_GRID_SIZE = 25;
+constexpr uint8_t DGUS_MACHINE_LEN = 24;
+constexpr uint8_t DGUS_BUILDVOLUME_LEN = 24;
+constexpr uint8_t DGUS_VERSION_LEN = 16;
+constexpr uint8_t DGUS_PRINTTIME_LEN = 24;
+constexpr uint8_t DGUS_LONGESTPRINT_LEN = 24;
+constexpr uint8_t DGUS_FILAMENTUSED_LEN = 24;
+constexpr uint8_t DGUS_GCODE_LEN = 32;
+
+enum class DGUS_Addr : uint16_t {
+ MESSAGE_Line1 = 0x1100, // 0x1100 - 0x111F
+ MESSAGE_Line2 = 0x1120, // 0x1120 - 0x113F
+ MESSAGE_Line3 = 0x1140, // 0x1140 - 0x115F
+ MESSAGE_Line4 = 0x1160, // 0x1160 - 0x117F
+
+ // READ-ONLY VARIABLES
+
+ SCREENCHANGE = 0x2000, // Screen change request. Data contains target screen in low byte.
+ SCREENCHANGE_SD = 0x2001, // Only change if SD card present.
+ SCREENCHANGE_Idle = 0x2002, // Only change if not printing.
+ SCREENCHANGE_Printing = 0x2003, // Only change if printing.
+ SD_SelectFile = 0x2004, // Data: file index (0-4)
+ SD_Scroll = 0x2005, // Data: DGUS_Data::Scroll
+ SD_Print = 0x2006,
+ STATUS_Abort = 0x2007, // Popup / Data: DGUS_Data::Popup
+ STATUS_Pause = 0x2008, // Popup / Data: DGUS_Data::Popup
+ STATUS_Resume = 0x2009, // Popup / Data: DGUS_Data::Popup
+ ADJUST_SetFeedrate = 0x200A, // Type: Integer (16 bits signed)
+ ADJUST_SetFlowrate_CUR = 0x200B, // Type: Integer (16 bits signed)
+ #if EXTRUDERS > 1
+ ADJUST_SetFlowrate_E0 = 0x200C, // Type: Integer (16 bits signed)
+ ADJUST_SetFlowrate_E1 = 0x200D, // Type: Integer (16 bits signed)
+ #endif
+ ADJUST_SetBabystep = 0x200E, // Type: Fixed point, 2 decimals (16 bits signed)
+ ADJUST_Babystep = 0x200F, // Data: DGUS_Data::Adjust
+ TEMP_Preset = 0x2010, // Popup / Data: DGUS_Data::TempPreset
+ TEMP_SetTarget_Bed = 0x2011, // Type: Integer (16 bits signed)
+ TEMP_SetTarget_H0 = 0x2012, // Type: Integer (16 bits signed)
+ #if HOTENDS > 1
+ TEMP_SetTarget_H1 = 0x2013, // Type: Integer (16 bits signed)
+ #endif
+ TEMP_Cool = 0x2014, // Data: DGUS_Data::Heater
+ STEPPER_Control = 0x2015, // Popup / Data: DGUS_Data::Control
+ LEVEL_OFFSET_Set = 0x2016, // Type: Fixed point, 2 decimals (16 bits signed)
+ LEVEL_OFFSET_Step = 0x2017, // Data: DGUS_Data::Adjust
+ LEVEL_OFFSET_SetStep = 0x2018, // Data: DGUS_Data::StepSize
+ LEVEL_MANUAL_Point = 0x2019, // Data: point index (1-5)
+ LEVEL_AUTO_Probe = 0x201A,
+ LEVEL_AUTO_Disable = 0x201B,
+ FILAMENT_Select = 0x201C, // Data: DGUS_Data::Extruder
+ FILAMENT_SetLength = 0x201D, // Type: Integer (16 bits unsigned)
+ FILAMENT_Move = 0x201E, // Data: DGUS_Data::FilamentMove
+ MOVE_Home = 0x201F, // Data: DGUS_Data::Axis
+ MOVE_SetX = 0x2020, // Type: Fixed point, 1 decimal (16 bits signed)
+ MOVE_SetY = 0x2021, // Type: Fixed point, 1 decimal (16 bits signed)
+ MOVE_SetZ = 0x2022, // Type: Fixed point, 1 decimal (16 bits signed)
+ MOVE_Step = 0x2023, // Data: DGUS_Data::MoveDirection
+ MOVE_SetStep = 0x2024, // Data: DGUS_Data::StepSize
+ GCODE_Clear = 0x2025,
+ GCODE_Execute = 0x2026,
+ EEPROM_Reset = 0x2027, // Popup / Data: DGUS_Data::Popup
+ SETTINGS2_Extra = 0x2028, // Data: DGUS_Data::Extra
+ PID_Select = 0x2029, // Data: DGUS_Data::Heater
+ PID_SetTemp = 0x202A, // Type: Integer (16 bits unsigned)
+ PID_Run = 0x202B,
+ POWERLOSS_Abort = 0x202C, // Popup / Data: DGUS_Data::Popup
+ POWERLOSS_Resume = 0x202D, // Popup / Data: DGUS_Data::Popup
+ WAIT_Abort = 0x202E, // Popup / Data: DGUS_Data::Popup
+ WAIT_Continue = 0x202F,
+
+ // WRITE-ONLY VARIABLES
+
+ MESSAGE_Status = 0x3000, // 0x3000 - 0x301F
+ SD_Type = 0x3020, // 0x3020 - 0x3024 / Data: DGUS_Data::SDType
+ SD_FileName0 = 0x3025, // 0x3025 - 0x3044
+ SD_FileName1 = 0x3045, // 0x3045 - 0x3064
+ SD_FileName2 = 0x3065, // 0x3065 - 0x3084
+ SD_FileName3 = 0x3085, // 0x3085 - 0x30A4
+ SD_FileName4 = 0x30A5, // 0x30A5 - 0x30C4
+ SD_ScrollIcons = 0x30C5, // Bits: DGUS_Data::ScrollIcon
+ SD_SelectedFileName = 0x30C6, // 0x30C6 - 0x30E5
+ STATUS_PositionZ = 0x30E6, // Type: Fixed point, 1 decimal (16 bits signed)
+ STATUS_Ellapsed = 0x30E7, // 0x30E7 - 0x30F5
+ STATUS_Percent = 0x30F6, // Type: Integer (16 bits unsigned)
+ STATUS_Icons = 0x30F7, // Bits: DGUS_Data::StatusIcon
+ ADJUST_Feedrate = 0x30F8, // Type: Integer (16 bits signed)
+ ADJUST_Flowrate_CUR = 0x30F9, // Type: Integer (16 bits signed)
+ #if EXTRUDERS > 1
+ ADJUST_Flowrate_E0 = 0x30FA, // Type: Integer (16 bits signed)
+ ADJUST_Flowrate_E1 = 0x30FB, // Type: Integer (16 bits signed)
+ #endif
+ TEMP_Current_Bed = 0x30FC, // Type: Integer (16 bits signed)
+ TEMP_Target_Bed = 0x30FD, // Type: Integer (16 bits signed)
+ TEMP_Max_Bed = 0x30FE, // Type: Integer (16 bits unsigned)
+ TEMP_Current_H0 = 0x30FF, // Type: Integer (16 bits signed)
+ TEMP_Target_H0 = 0x3100, // Type: Integer (16 bits signed)
+ TEMP_Max_H0 = 0x3101, // Type: Integer (16 bits unsigned)
+ #if HOTENDS > 1
+ TEMP_Current_H1 = 0x3102, // Type: Integer (16 bits signed)
+ TEMP_Target_H1 = 0x3103, // Type: Integer (16 bits signed)
+ TEMP_Max_H1 = 0x3104, // Type: Integer (16 bits unsigned)
+ #endif
+ STEPPER_Status = 0x3105, // Data: DGUS_Data::Status
+ LEVEL_OFFSET_Current = 0x3106, // Type: Fixed point, 2 decimals (16 bits signed)
+ LEVEL_OFFSET_StepIcons = 0x3107, // Bits: DGUS_Data::StepIcon
+ LEVEL_AUTO_DisableIcon = 0x3108, // Data: DGUS_Data::Status
+ LEVEL_AUTO_Grid = 0x3109, // 0x3109 - 0x3121 / Type: Fixed point, 3 decimals (16 bits signed)
+ LEVEL_PROBING_Icons1 = 0x3122, // Type: Integer (16 bits unsigned) / Each bit represents a grid point
+ LEVEL_PROBING_Icons2 = 0x3123, // Type: Integer (16 bits unsigned) / Each bit represents a grid point
+ FILAMENT_ExtruderIcons = 0x3124, // Data: DGUS_Data::ExtruderIcon
+ FILAMENT_Length = 0x3125, // Type: Integer (16 bits unsigned)
+ MOVE_CurrentX = 0x3126, // Type: Fixed point, 1 decimal (16 bits signed)
+ MOVE_CurrentY = 0x3127, // Type: Fixed point, 1 decimal (16 bits signed)
+ MOVE_CurrentZ = 0x3128, // Type: Fixed point, 1 decimal (16 bits signed)
+ MOVE_StepIcons = 0x3129, // Bits: DGUS_Data::StepIcon
+ SETTINGS2_BLTouch = 0x312A, // Data: DGUS_Data::Status
+ PID_HeaterIcons = 0x312B, // Data: DGUS_Data::HeaterIcon
+ PID_Temp = 0x312C, // Type: Integer (16 bits unsigned)
+ PID_Kp = 0x312D, // Type: Fixed point, 2 decimals (32 bits signed)
+ PID_Ki = 0x312F, // Type: Fixed point, 2 decimals (32 bits signed)
+ PID_Kd = 0x3131, // Type: Fixed point, 2 decimals (32 bits signed)
+ INFOS_Machine = 0x3133, // 0x3133 - 0x314A
+ INFOS_BuildVolume = 0x314B, // 0x314B - 0x3162
+ INFOS_Version = 0x3163, // 0x3163 - 0x3172
+ INFOS_TotalPrints = 0x3173, // Type: Integer (16 bits unsigned)
+ INFOS_FinishedPrints = 0x3174, // Type: Integer (16 bits unsigned)
+ INFOS_PrintTime = 0x3175, // 0x3175 - 0x318C
+ INFOS_LongestPrint = 0x318D, // 0x318D - 0x31A4
+ INFOS_FilamentUsed = 0x31A5, // 0x31A5 - 0x31BC
+ WAIT_Icons = 0x31BD, // Bits: DGUS_Data::WaitIcon
+
+ // READ-WRITE VARIABLES
+
+ FAN0_Speed = 0x4000, // Type: Integer (16 bits unsigned) / Data: fan speed as percent (0-100)
+ GCODE_Data = 0x4001, // 0x4001 - 0x4020
+ PID_Cycles = 0x4021, // Type: Integer (16 bits unsigned)
+ VOLUME_Level = 0x4022, // Type: Integer (16 bits unsigned) / Data: volume as percent (0-100)
+ BRIGHTNESS_Level = 0x4023, // Type: Integer (16 bits unsigned) / Data: brightness as percent (0-100)
+
+ // SPECIAL CASES
+
+ STATUS_Percent_Complete = 0x5000, // Same as STATUS_Percent, but always 100%
+ INFOS_Debug = 0x5001,
+
+};
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Constants.h b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Constants.h
new file mode 100644
index 000000000000..4047a6d6dcb9
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Constants.h
@@ -0,0 +1,96 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#include "DGUS_Addr.h"
+
+static_assert((DGUS_LEVEL_GRID_SIZE == GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y), "DGUS_LEVEL_GRID_SIZE incompatible with current mesh.");
+
+#ifndef DGUS_DEFAULT_VOLUME
+ #define DGUS_DEFAULT_VOLUME 50
+#endif
+
+#ifndef DGUS_DEFAULT_BRIGHTNESS
+ #define DGUS_DEFAULT_BRIGHTNESS 100
+#endif
+
+#ifndef DGUS_STATUS_EXPIRATION_MS
+ #define DGUS_STATUS_EXPIRATION_MS 30000
+#endif
+
+#ifndef DGUS_PRINT_BABYSTEP
+ #define DGUS_PRINT_BABYSTEP 0.01f
+#endif
+
+#ifndef DGUS_PLA_TEMP_HOTEND
+ #define DGUS_PLA_TEMP_HOTEND 200
+#endif
+
+#ifndef DGUS_PLA_TEMP_BED
+ #define DGUS_PLA_TEMP_BED 60
+#endif
+
+#ifndef DGUS_ABS_TEMP_HOTEND
+ #define DGUS_ABS_TEMP_HOTEND 240
+#endif
+
+#ifndef DGUS_ABS_TEMP_BED
+ #define DGUS_ABS_TEMP_BED 80
+#endif
+
+#ifndef DGUS_PETG_TEMP_HOTEND
+ #define DGUS_PETG_TEMP_HOTEND 240
+#endif
+
+#ifndef DGUS_PETG_TEMP_BED
+ #define DGUS_PETG_TEMP_BED 60
+#endif
+
+#ifndef DGUS_DEFAULT_FILAMENT_LEN
+ #define DGUS_DEFAULT_FILAMENT_LEN 10
+#endif
+
+#ifndef LEVEL_CORNERS_Z_HOP
+ #define LEVEL_CORNERS_Z_HOP 4.0
+#endif
+
+#ifndef LEVEL_CORNERS_HEIGHT
+ #define LEVEL_CORNERS_HEIGHT 0.0
+#endif
+
+static_assert(LEVEL_CORNERS_Z_HOP >= 0, "LEVEL_CORNERS_Z_HOP must be >= 0. Please update your configuration.");
+
+#ifndef DGUS_LEVEL_CENTER_X
+ #define DGUS_LEVEL_CENTER_X ((X_BED_SIZE) / 2)
+#endif
+
+#ifndef DGUS_LEVEL_CENTER_Y
+ #define DGUS_LEVEL_CENTER_Y ((Y_BED_SIZE) / 2)
+#endif
+
+#if ENABLED(BLTOUCH)
+ #ifndef DGUS_RESET_BLTOUCH
+ #define DGUS_RESET_BLTOUCH "M999\nM280P0S160"
+ #endif
+#endif
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Control.h b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Control.h
new file mode 100644
index 000000000000..92d2f5ece215
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Control.h
@@ -0,0 +1,50 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+enum class DGUS_Control : uint8_t {
+
+ // PRINT
+ FILE0 = 1, // RETURN_KEY_CODE
+ FILE1 = 2, // RETURN_KEY_CODE
+ FILE2 = 3, // RETURN_KEY_CODE
+ FILE3 = 4, // RETURN_KEY_CODE
+ FILE4 = 5, // RETURN_KEY_CODE
+ GO_BACK = 6, // RETURN_KEY_CODE
+ SCROLL_UP = 7, // RETURN_KEY_CODE
+ SCROLL_DOWN = 8, // RETURN_KEY_CODE
+
+ // PRINT_STATUS
+ PAUSE = 1, // POPUP_WINDOW
+ RESUME = 2, // POPUP_WINDOW
+
+ // LEVELING_AUTOMATIC
+ DISABLE = 5, // RETURN_KEY_CODE
+
+ // SETTINGS_MENU2
+ EXTRA2 = 6, // RETURN_KEY_CODE
+
+ // WAIT
+ ABORT = 1, // POPUP_WINDOW
+ CONTINUE = 2 // RETURN_KEY_CODE
+
+};
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Data.h b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Data.h
new file mode 100644
index 000000000000..886109054c3b
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Data.h
@@ -0,0 +1,148 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+namespace DGUS_Data {
+
+ // RX constants
+
+ enum class Scroll : uint8_t {
+ GO_BACK = 0,
+ UP = 1,
+ DOWN = 2
+ };
+
+ enum class Popup : uint8_t {
+ CONFIRMED = 1
+ };
+
+ enum class Adjust : uint8_t {
+ INCREMENT = 0,
+ DECREMENT = 1
+ };
+
+ enum class TempPreset : uint8_t {
+ PLA = 1,
+ ABS = 2,
+ PETG = 3
+ };
+
+ enum class Extruder : int8_t {
+ CURRENT = -1,
+ E0 = 0,
+ E1 = 1
+ };
+
+ enum class Heater : int8_t {
+ ALL = -2,
+ BED = -1,
+ H0 = 0,
+ H1 = 1
+ };
+
+ enum class Control : uint8_t {
+ ENABLE = 1,
+ DISABLE = 2
+ };
+
+ enum class StepSize : uint8_t {
+ MM10 = 0, // 10mm
+ MM1 = 1, // 1mm
+ MMP1 = 2, // 0.1mm
+ MMP01 = 3 // 0.01mm
+ };
+
+ enum class FilamentMove : uint8_t {
+ RETRACT = 0,
+ EXTRUDE = 1
+ };
+
+ enum class Axis : uint8_t {
+ X_Y_Z = 0,
+ X_Y = 1,
+ Z = 2
+ };
+
+ enum class MoveDirection : uint8_t {
+ XP = 0, // X+
+ XM = 1, // X-
+ YP = 2, // Y+
+ YM = 3, // Y-
+ ZP = 4, // Z+
+ ZM = 5 // Z-
+ };
+
+ enum class Extra : uint8_t {
+ BUTTON1 = 0,
+ BUTTON2 = 1
+ };
+
+ // TX constants
+
+ enum class SDType : uint16_t {
+ NONE = 0,
+ FILE = 1,
+ DIRECTORY = 2
+ };
+
+ enum class ScrollIcon : uint16_t {
+ GO_BACK = 1U << 0,
+ UP = 1U << 1,
+ DOWN = 1U << 2
+ };
+
+ enum class StatusIcon : uint16_t {
+ PAUSE = 1U << 0,
+ RESUME = 1U << 1
+ };
+
+ enum class Status : uint16_t {
+ DISABLED = 0,
+ ENABLED = 1
+ };
+
+ enum class StepIcon : uint16_t {
+ MM10 = 1U << 0, // 10mm
+ MM1 = 1U << 1, // 1mm
+ MMP1 = 1U << 2, // 0.1mm
+ MMP01 = 1U << 3 // 0.01mm
+ };
+
+ enum class ExtruderIcon : uint16_t {
+ E0 = 1U << 0,
+ E1 = 1U << 1
+ };
+
+ enum class HeaterIcon : uint16_t {
+ BED = 1U << 0,
+ H0 = 1U << 1,
+ H1 = 1U << 2
+ };
+
+ enum class WaitIcon : uint16_t {
+ ABORT = 1U << 0,
+ CONTINUE = 1U << 1
+ };
+
+};
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Screen.h b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Screen.h
new file mode 100644
index 000000000000..b3d2ad6d3c07
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/config/DGUS_Screen.h
@@ -0,0 +1,52 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+enum class DGUS_Screen : uint8_t {
+ BOOT = 0,
+ HOME = 1,
+ PRINT = 2,
+ PRINT_STATUS = 3,
+ PRINT_ADJUST = 4,
+ PRINT_FINISHED = 5,
+ TEMP_MENU = 6,
+ TEMP_MANUAL = 7,
+ FAN = 8,
+ SETTINGS_MENU = 9,
+ LEVELING_MENU = 10,
+ LEVELING_OFFSET = 11,
+ LEVELING_MANUAL = 12,
+ LEVELING_AUTOMATIC = 13,
+ LEVELING_PROBING = 14,
+ FILAMENT = 15,
+ MOVE = 16,
+ GCODE = 17,
+ SETTINGS_MENU2 = 18,
+ PID = 19,
+ VOLUME = 20,
+ BRIGHTNESS = 21,
+ INFOS = 22,
+ DEBUG = 240,
+ POWERLOSS = 248,
+ WAIT = 249,
+ KILL = 250
+};
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenAddrList.cpp b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenAddrList.cpp
new file mode 100644
index 000000000000..95e6444956bc
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenAddrList.cpp
@@ -0,0 +1,240 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUS_ScreenAddrList.h"
+
+#include "../../ui_api.h"
+
+constexpr DGUS_Addr LIST_HOME[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ (DGUS_Addr)0
+};
+
+#if ENABLED(SDSUPPORT)
+ constexpr DGUS_Addr LIST_PRINT[] PROGMEM = {
+ DGUS_Addr::SD_Type,
+ DGUS_Addr::SD_FileName0,
+ DGUS_Addr::SD_FileName1,
+ DGUS_Addr::SD_FileName2,
+ DGUS_Addr::SD_FileName3,
+ DGUS_Addr::SD_FileName4,
+ DGUS_Addr::SD_ScrollIcons,
+ DGUS_Addr::SD_SelectedFileName,
+ (DGUS_Addr)0
+ };
+#endif
+
+constexpr DGUS_Addr LIST_PRINT_STATUS[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ DGUS_Addr::STATUS_PositionZ,
+ DGUS_Addr::STATUS_Ellapsed,
+ DGUS_Addr::STATUS_Percent,
+ DGUS_Addr::STATUS_Icons,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_PRINT_ADJUST[] PROGMEM = {
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Target_Bed,
+ DGUS_Addr::FAN0_Speed,
+ DGUS_Addr::ADJUST_Feedrate,
+ DGUS_Addr::ADJUST_Flowrate_CUR,
+ DGUS_Addr::LEVEL_OFFSET_Current,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_PRINT_FINISHED[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ DGUS_Addr::STATUS_PositionZ,
+ DGUS_Addr::STATUS_Ellapsed,
+ DGUS_Addr::STATUS_Percent_Complete,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_TEMP_MENU[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_TEMP_MANUAL[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Max_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ DGUS_Addr::TEMP_Max_Bed,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_FAN[] PROGMEM = {
+ DGUS_Addr::FAN0_Speed,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_SETTINGS_MENU[] PROGMEM = {
+ DGUS_Addr::STEPPER_Status,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_LEVELING_OFFSET[] PROGMEM = {
+ DGUS_Addr::LEVEL_OFFSET_Current,
+ DGUS_Addr::LEVEL_OFFSET_StepIcons,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_LEVELING_MANUAL[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_LEVELING_AUTOMATIC[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::TEMP_Current_Bed,
+ DGUS_Addr::TEMP_Target_Bed,
+ DGUS_Addr::LEVEL_AUTO_DisableIcon,
+ DGUS_Addr::LEVEL_AUTO_Grid,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_LEVELING_PROBING[] PROGMEM = {
+ DGUS_Addr::LEVEL_PROBING_Icons1,
+ DGUS_Addr::LEVEL_PROBING_Icons2,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_FILAMENT[] PROGMEM = {
+ DGUS_Addr::TEMP_Current_H0,
+ DGUS_Addr::TEMP_Target_H0,
+ DGUS_Addr::FILAMENT_ExtruderIcons,
+ DGUS_Addr::FILAMENT_Length,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_MOVE[] PROGMEM = {
+ DGUS_Addr::MOVE_CurrentX,
+ DGUS_Addr::MOVE_CurrentY,
+ DGUS_Addr::MOVE_CurrentZ,
+ DGUS_Addr::MOVE_StepIcons,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_GCODE[] PROGMEM = {
+ DGUS_Addr::GCODE_Data,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_SETTINGS_MENU2[] PROGMEM = {
+ DGUS_Addr::SETTINGS2_BLTouch,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_PID[] PROGMEM = {
+ DGUS_Addr::PID_HeaterIcons,
+ DGUS_Addr::PID_Temp,
+ DGUS_Addr::PID_Cycles,
+ DGUS_Addr::PID_Kp,
+ DGUS_Addr::PID_Ki,
+ DGUS_Addr::PID_Kd,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_VOLUME[] PROGMEM = {
+ DGUS_Addr::VOLUME_Level,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_BRIGHTNESS[] PROGMEM = {
+ DGUS_Addr::BRIGHTNESS_Level,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_INFOS[] PROGMEM = {
+ DGUS_Addr::INFOS_Machine,
+ DGUS_Addr::INFOS_BuildVolume,
+ DGUS_Addr::INFOS_Version,
+ DGUS_Addr::INFOS_TotalPrints,
+ DGUS_Addr::INFOS_FinishedPrints,
+ DGUS_Addr::INFOS_PrintTime,
+ DGUS_Addr::INFOS_LongestPrint,
+ DGUS_Addr::INFOS_FilamentUsed,
+ (DGUS_Addr)0
+};
+
+constexpr DGUS_Addr LIST_WAIT[] PROGMEM = {
+ DGUS_Addr::WAIT_Icons,
+ (DGUS_Addr)0
+};
+
+#define MAP_HELPER(SCREEN, LIST) \
+ { .screen = SCREEN, \
+ .addr_list = LIST }
+
+const struct DGUS_ScreenAddrList screen_addr_list_map[] PROGMEM = {
+ MAP_HELPER(DGUS_Screen::HOME, LIST_HOME),
+ #if ENABLED(SDSUPPORT)
+ MAP_HELPER(DGUS_Screen::PRINT, LIST_PRINT),
+ #endif
+ MAP_HELPER(DGUS_Screen::PRINT_STATUS, LIST_PRINT_STATUS),
+ MAP_HELPER(DGUS_Screen::PRINT_ADJUST, LIST_PRINT_ADJUST),
+ MAP_HELPER(DGUS_Screen::PRINT_FINISHED, LIST_PRINT_FINISHED),
+ MAP_HELPER(DGUS_Screen::TEMP_MENU, LIST_TEMP_MENU),
+ MAP_HELPER(DGUS_Screen::TEMP_MANUAL, LIST_TEMP_MANUAL),
+ MAP_HELPER(DGUS_Screen::FAN, LIST_FAN),
+ MAP_HELPER(DGUS_Screen::SETTINGS_MENU, LIST_SETTINGS_MENU),
+ MAP_HELPER(DGUS_Screen::LEVELING_OFFSET, LIST_LEVELING_OFFSET),
+ MAP_HELPER(DGUS_Screen::LEVELING_MANUAL, LIST_LEVELING_MANUAL),
+ MAP_HELPER(DGUS_Screen::LEVELING_AUTOMATIC, LIST_LEVELING_AUTOMATIC),
+ MAP_HELPER(DGUS_Screen::LEVELING_PROBING, LIST_LEVELING_PROBING),
+ MAP_HELPER(DGUS_Screen::FILAMENT, LIST_FILAMENT),
+ MAP_HELPER(DGUS_Screen::MOVE, LIST_MOVE),
+ MAP_HELPER(DGUS_Screen::GCODE, LIST_GCODE),
+ MAP_HELPER(DGUS_Screen::SETTINGS_MENU2, LIST_SETTINGS_MENU2),
+ MAP_HELPER(DGUS_Screen::PID, LIST_PID),
+ MAP_HELPER(DGUS_Screen::VOLUME, LIST_VOLUME),
+ MAP_HELPER(DGUS_Screen::BRIGHTNESS, LIST_BRIGHTNESS),
+ MAP_HELPER(DGUS_Screen::INFOS, LIST_INFOS),
+ MAP_HELPER(DGUS_Screen::WAIT, LIST_WAIT),
+
+ MAP_HELPER((DGUS_Screen)0, nullptr)
+};
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenAddrList.h b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenAddrList.h
new file mode 100644
index 000000000000..af05c46d28fd
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenAddrList.h
@@ -0,0 +1,32 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../config/DGUS_Screen.h"
+#include "../config/DGUS_Addr.h"
+
+struct DGUS_ScreenAddrList {
+ DGUS_Screen screen;
+ const DGUS_Addr *addr_list;
+};
+
+extern const struct DGUS_ScreenAddrList screen_addr_list_map[];
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenSetup.cpp b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenSetup.cpp
new file mode 100644
index 000000000000..213e430334f2
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenSetup.cpp
@@ -0,0 +1,57 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUS_ScreenSetup.h"
+
+#include "../DGUSSetupHandler.h"
+
+#include "../../ui_api.h"
+
+#define SETUP_HELPER(SCREEN, SETUP) \
+ { .screen = SCREEN, \
+ .setup_fn = SETUP }
+
+const struct DGUS_ScreenSetup screen_setup_list[] PROGMEM = {
+ #if ENABLED(SDSUPPORT)
+ SETUP_HELPER(DGUS_Screen::PRINT, &DGUSSetupHandler::Print),
+ #endif
+ SETUP_HELPER(DGUS_Screen::PRINT_STATUS, &DGUSSetupHandler::PrintStatus),
+ SETUP_HELPER(DGUS_Screen::PRINT_ADJUST, &DGUSSetupHandler::PrintAdjust),
+ SETUP_HELPER(DGUS_Screen::LEVELING_MENU, &DGUSSetupHandler::LevelingMenu),
+ SETUP_HELPER(DGUS_Screen::LEVELING_OFFSET, &DGUSSetupHandler::LevelingOffset),
+ SETUP_HELPER(DGUS_Screen::LEVELING_MANUAL, &DGUSSetupHandler::LevelingManual),
+ SETUP_HELPER(DGUS_Screen::LEVELING_AUTOMATIC, &DGUSSetupHandler::LevelingAutomatic),
+ SETUP_HELPER(DGUS_Screen::LEVELING_PROBING, &DGUSSetupHandler::LevelingProbing),
+ SETUP_HELPER(DGUS_Screen::FILAMENT, &DGUSSetupHandler::Filament),
+ SETUP_HELPER(DGUS_Screen::MOVE, &DGUSSetupHandler::Move),
+ SETUP_HELPER(DGUS_Screen::GCODE, &DGUSSetupHandler::Gcode),
+ SETUP_HELPER(DGUS_Screen::PID, &DGUSSetupHandler::PID),
+ SETUP_HELPER(DGUS_Screen::INFOS, &DGUSSetupHandler::Infos),
+
+ SETUP_HELPER((DGUS_Screen)0, nullptr)
+};
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenSetup.h b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenSetup.h
new file mode 100644
index 000000000000..3b9208e5ec2b
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_ScreenSetup.h
@@ -0,0 +1,31 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../config/DGUS_Screen.h"
+
+struct DGUS_ScreenSetup {
+ DGUS_Screen screen;
+ bool (*setup_fn)(void);
+};
+
+extern const struct DGUS_ScreenSetup screen_setup_list[];
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VP.h b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VP.h
new file mode 100644
index 000000000000..b1b6792224c5
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VP.h
@@ -0,0 +1,40 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../config/DGUS_Addr.h"
+
+#define VPFLAG_NONE 0
+#define VPFLAG_AUTOUPLOAD (1U << 0) // Upload on every DGUS update
+#define VPFLAG_RXSTRING (1U << 1) // Treat the received data as a string (terminated with 0xFFFF)
+
+struct DGUS_VP {
+ DGUS_Addr addr;
+ uint8_t size;
+ uint8_t flags;
+ void *extra;
+
+ // Callback that will be called if the display modified the value.
+ // nullptr makes it readonly for the display.
+ void (*rx_handler)(DGUS_VP &, void *);
+ void (*tx_handler)(DGUS_VP &);
+};
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VPList.cpp b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VPList.cpp
new file mode 100644
index 000000000000..3f5690cfe7bd
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VPList.cpp
@@ -0,0 +1,368 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "DGUS_VPList.h"
+
+#include "../config/DGUS_Addr.h"
+#include "../DGUSScreenHandler.h"
+#include "../DGUSRxHandler.h"
+#include "../DGUSTxHandler.h"
+
+#include "../../ui_api.h"
+#include "../../../../module/probe.h"
+#include "../../../../module/motion.h"
+#include "../../../../module/temperature.h"
+
+const char DGUS_MACHINENAME[] PROGMEM = MACHINE_NAME;
+const char DGUS_MARLINVERSION[] PROGMEM = SHORT_BUILD_VERSION;
+
+#define VP_HELPER(ADDR, SIZE, FLAGS, EXTRA, RXHANDLER, TXHANDLER) \
+ { .addr = ADDR, \
+ .size = SIZE, \
+ .flags = FLAGS, \
+ .extra = EXTRA, \
+ .rx_handler = RXHANDLER, \
+ .tx_handler = TXHANDLER }
+
+#define VP_HELPER_WORD(ADDR, FLAGS, EXTRA, RXHANDLER, TXHANDLER) \
+ VP_HELPER(ADDR, 2, FLAGS, EXTRA, RXHANDLER, TXHANDLER)
+
+#define VP_HELPER_DWORD(ADDR, FLAGS, EXTRA, RXHANDLER, TXHANDLER) \
+ VP_HELPER(ADDR, 4, FLAGS, EXTRA, RXHANDLER, TXHANDLER)
+
+#define VP_HELPER_RX(ADDR, RXHANDLER) \
+ VP_HELPER_WORD(ADDR, VPFLAG_NONE, nullptr, RXHANDLER, nullptr)
+
+#define VP_HELPER_RX_NODATA(ADDR, RXHANDLER) \
+ VP_HELPER(ADDR, 0, VPFLAG_NONE, nullptr, RXHANDLER, nullptr)
+
+#define VP_HELPER_TX(ADDR, TXHANDLER) \
+ VP_HELPER_WORD(ADDR, VPFLAG_NONE, nullptr, nullptr, TXHANDLER)
+
+#define VP_HELPER_TX_SIZE(ADDR, SIZE, TXHANDLER) \
+ VP_HELPER(ADDR, SIZE, VPFLAG_NONE, nullptr, nullptr, TXHANDLER)
+
+#define VP_HELPER_TX_EXTRA(ADDR, EXTRA, TXHANDLER) \
+ VP_HELPER_WORD(ADDR, VPFLAG_NONE, EXTRA, nullptr, TXHANDLER)
+
+#define VP_HELPER_TX_AUTO(ADDR, EXTRA, TXHANDLER) \
+ VP_HELPER_WORD(ADDR, VPFLAG_AUTOUPLOAD, EXTRA, nullptr, TXHANDLER)
+
+const struct DGUS_VP vp_list[] PROGMEM = {
+
+ // READ-ONLY VARIABLES
+
+ VP_HELPER_RX(DGUS_Addr::SCREENCHANGE, &DGUSRxHandler::ScreenChange),
+ VP_HELPER_RX(DGUS_Addr::SCREENCHANGE_SD, &DGUSRxHandler::ScreenChange),
+ VP_HELPER_RX(DGUS_Addr::SCREENCHANGE_Idle, &DGUSRxHandler::ScreenChange),
+ VP_HELPER_RX(DGUS_Addr::SCREENCHANGE_Printing, &DGUSRxHandler::ScreenChange),
+
+ #if ENABLED(SDSUPPORT)
+ VP_HELPER_RX(DGUS_Addr::SD_SelectFile, &DGUSRxHandler::SelectFile),
+ VP_HELPER_RX(DGUS_Addr::SD_Scroll, &DGUSRxHandler::Scroll),
+ VP_HELPER_RX_NODATA(DGUS_Addr::SD_Print, &DGUSRxHandler::PrintFile),
+ #endif
+
+ VP_HELPER_RX(DGUS_Addr::STATUS_Abort, &DGUSRxHandler::PrintAbort),
+ VP_HELPER_RX(DGUS_Addr::STATUS_Pause, &DGUSRxHandler::PrintPause),
+ VP_HELPER_RX(DGUS_Addr::STATUS_Resume, &DGUSRxHandler::PrintResume),
+
+ VP_HELPER_RX(DGUS_Addr::ADJUST_SetFeedrate, &DGUSRxHandler::Feedrate),
+ VP_HELPER_RX(DGUS_Addr::ADJUST_SetFlowrate_CUR, &DGUSRxHandler::Flowrate),
+ #if EXTRUDERS > 1
+ VP_HELPER_RX(DGUS_Addr::ADJUST_SetFlowrate_E0, &DGUSRxHandler::Flowrate),
+ VP_HELPER_RX(DGUS_Addr::ADJUST_SetFlowrate_E1, &DGUSRxHandler::Flowrate),
+ #endif
+ VP_HELPER_RX(DGUS_Addr::ADJUST_SetBabystep, &DGUSRxHandler::BabystepSet),
+ VP_HELPER_RX(DGUS_Addr::ADJUST_Babystep, &DGUSRxHandler::Babystep),
+
+ VP_HELPER_RX(DGUS_Addr::TEMP_Preset, &DGUSRxHandler::TempPreset),
+ VP_HELPER_RX(DGUS_Addr::TEMP_SetTarget_Bed, &DGUSRxHandler::TempTarget),
+ VP_HELPER_RX(DGUS_Addr::TEMP_SetTarget_H0, &DGUSRxHandler::TempTarget),
+ #if HOTENDS > 1
+ VP_HELPER_RX(DGUS_Addr::TEMP_SetTarget_H1, &DGUSRxHandler::TempTarget),
+ #endif
+ VP_HELPER_RX(DGUS_Addr::TEMP_Cool, &DGUSRxHandler::TempCool),
+
+ VP_HELPER_RX(DGUS_Addr::STEPPER_Control, &DGUSRxHandler::Steppers),
+
+ VP_HELPER_RX(DGUS_Addr::LEVEL_OFFSET_Set, &DGUSRxHandler::ZOffset),
+ VP_HELPER_RX(DGUS_Addr::LEVEL_OFFSET_Step, &DGUSRxHandler::ZOffsetStep),
+ VP_HELPER_RX(DGUS_Addr::LEVEL_OFFSET_SetStep, &DGUSRxHandler::ZOffsetSetStep),
+
+ VP_HELPER_RX(DGUS_Addr::LEVEL_MANUAL_Point, &DGUSRxHandler::MoveToPoint),
+
+ VP_HELPER_RX_NODATA(DGUS_Addr::LEVEL_AUTO_Probe, &DGUSRxHandler::Probe),
+ VP_HELPER_RX_NODATA(DGUS_Addr::LEVEL_AUTO_Disable,
+ &DGUSRxHandler::DisableABL),
+
+ VP_HELPER_RX(DGUS_Addr::FILAMENT_Select, &DGUSRxHandler::FilamentSelect),
+ VP_HELPER_RX(DGUS_Addr::FILAMENT_SetLength, &DGUSRxHandler::FilamentLength),
+ VP_HELPER_RX(DGUS_Addr::FILAMENT_Move, &DGUSRxHandler::FilamentMove),
+
+ VP_HELPER_RX(DGUS_Addr::MOVE_Home, &DGUSRxHandler::Home),
+ VP_HELPER_RX(DGUS_Addr::MOVE_SetX, &DGUSRxHandler::Move),
+ VP_HELPER_RX(DGUS_Addr::MOVE_SetY, &DGUSRxHandler::Move),
+ VP_HELPER_RX(DGUS_Addr::MOVE_SetZ, &DGUSRxHandler::Move),
+ VP_HELPER_RX(DGUS_Addr::MOVE_Step, &DGUSRxHandler::MoveStep),
+ VP_HELPER_RX(DGUS_Addr::MOVE_SetStep, &DGUSRxHandler::MoveSetStep),
+
+ VP_HELPER_RX_NODATA(DGUS_Addr::GCODE_Clear, &DGUSRxHandler::GcodeClear),
+ VP_HELPER_RX_NODATA(DGUS_Addr::GCODE_Execute, &DGUSRxHandler::GcodeExecute),
+
+ VP_HELPER_RX(DGUS_Addr::EEPROM_Reset, &DGUSRxHandler::ResetEEPROM),
+
+ VP_HELPER_RX(DGUS_Addr::SETTINGS2_Extra, &DGUSRxHandler::SettingsExtra),
+
+ VP_HELPER_RX(DGUS_Addr::PID_Select, &DGUSRxHandler::PIDSelect),
+ VP_HELPER_RX(DGUS_Addr::PID_SetTemp, &DGUSRxHandler::PIDSetTemp),
+ VP_HELPER_RX_NODATA(DGUS_Addr::PID_Run, &DGUSRxHandler::PIDRun),
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ VP_HELPER_RX(DGUS_Addr::POWERLOSS_Abort, &DGUSRxHandler::PowerLossAbort),
+ VP_HELPER_RX(DGUS_Addr::POWERLOSS_Resume, &DGUSRxHandler::PowerLossResume),
+ #endif
+
+ VP_HELPER_RX(DGUS_Addr::WAIT_Abort, &DGUSRxHandler::WaitAbort),
+ VP_HELPER_RX_NODATA(DGUS_Addr::WAIT_Continue, &DGUSRxHandler::WaitContinue),
+
+ // WRITE-ONLY VARIABLES
+
+ #if ENABLED(SDSUPPORT)
+ VP_HELPER_TX(DGUS_Addr::SD_Type, &DGUSTxHandler::FileType),
+ VP_HELPER_TX_SIZE(DGUS_Addr::SD_FileName0,
+ DGUS_FILENAME_LEN,
+ &DGUSTxHandler::FileName),
+ VP_HELPER_TX_SIZE(DGUS_Addr::SD_FileName1,
+ DGUS_FILENAME_LEN,
+ &DGUSTxHandler::FileName),
+ VP_HELPER_TX_SIZE(DGUS_Addr::SD_FileName2,
+ DGUS_FILENAME_LEN,
+ &DGUSTxHandler::FileName),
+ VP_HELPER_TX_SIZE(DGUS_Addr::SD_FileName3,
+ DGUS_FILENAME_LEN,
+ &DGUSTxHandler::FileName),
+ VP_HELPER_TX_SIZE(DGUS_Addr::SD_FileName4,
+ DGUS_FILENAME_LEN,
+ &DGUSTxHandler::FileName),
+ VP_HELPER_TX(DGUS_Addr::SD_ScrollIcons, &DGUSTxHandler::ScrollIcons),
+ VP_HELPER_TX_SIZE(DGUS_Addr::SD_SelectedFileName,
+ DGUS_FILENAME_LEN,
+ &DGUSTxHandler::SelectedFileName),
+ #endif
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::STATUS_PositionZ,
+ nullptr,
+ &DGUSTxHandler::PositionZ),
+ VP_HELPER(DGUS_Addr::STATUS_Ellapsed,
+ DGUS_ELLAPSED_LEN,
+ VPFLAG_AUTOUPLOAD,
+ nullptr,
+ nullptr,
+ &DGUSTxHandler::Ellapsed),
+ VP_HELPER_TX_AUTO(DGUS_Addr::STATUS_Percent,
+ nullptr,
+ &DGUSTxHandler::Percent),
+ VP_HELPER_TX(DGUS_Addr::STATUS_Icons, &DGUSTxHandler::StatusIcons),
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::ADJUST_Feedrate,
+ &feedrate_percentage,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX_AUTO(DGUS_Addr::ADJUST_Flowrate_CUR,
+ nullptr,
+ &DGUSTxHandler::Flowrate),
+ #if EXTRUDERS > 1
+ VP_HELPER_TX_AUTO(DGUS_Addr::ADJUST_Flowrate_E0,
+ nullptr,
+ &DGUSTxHandler::Flowrate),
+ VP_HELPER_TX_AUTO(DGUS_Addr::ADJUST_Flowrate_E1,
+ nullptr,
+ &DGUSTxHandler::Flowrate),
+ #endif
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::TEMP_Current_Bed,
+ &thermalManager.temp_bed.celsius,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX_AUTO(DGUS_Addr::TEMP_Target_Bed,
+ &thermalManager.temp_bed.target,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX(DGUS_Addr::TEMP_Max_Bed, &DGUSTxHandler::TempMax),
+ VP_HELPER_TX_AUTO(DGUS_Addr::TEMP_Current_H0,
+ &thermalManager.temp_hotend[ExtUI::heater_t::H0].celsius,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX_AUTO(DGUS_Addr::TEMP_Target_H0,
+ &thermalManager.temp_hotend[ExtUI::heater_t::H0].target,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX(DGUS_Addr::TEMP_Max_H0, &DGUSTxHandler::TempMax),
+ #if HOTENDS > 1
+ VP_HELPER_TX_AUTO(DGUS_Addr::TEMP_Current_H1,
+ &thermalManager.temp_hotend[ExtUI::heater_t::H1].celsius,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX_AUTO(DGUS_Addr::TEMP_Target_H1,
+ &thermalManager.temp_hotend[ExtUI::heater_t::H1].target,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX(DGUS_Addr::TEMP_Max_H1, &DGUSTxHandler::TempMax),
+ #endif
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::STEPPER_Status,
+ nullptr,
+ &DGUSTxHandler::StepperStatus),
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::LEVEL_OFFSET_Current,
+ &probe.offset.z,
+ (&DGUSTxHandler::ExtraToFixedPoint)),
+ VP_HELPER_TX_EXTRA(DGUS_Addr::LEVEL_OFFSET_StepIcons,
+ &DGUSScreenHandler::offset_steps,
+ &DGUSTxHandler::StepIcons),
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::LEVEL_AUTO_DisableIcon,
+ nullptr,
+ &DGUSTxHandler::ABLDisableIcon),
+ VP_HELPER_TX(DGUS_Addr::LEVEL_AUTO_Grid, &DGUSTxHandler::ABLGrid),
+
+ VP_HELPER_TX_EXTRA(DGUS_Addr::LEVEL_PROBING_Icons1,
+ &DGUSScreenHandler::probing_icons[0],
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_TX_EXTRA(DGUS_Addr::LEVEL_PROBING_Icons2,
+ &DGUSScreenHandler::probing_icons[1],
+ &DGUSTxHandler::ExtraToInteger),
+
+ VP_HELPER_TX(DGUS_Addr::FILAMENT_ExtruderIcons, &DGUSTxHandler::FilamentIcons),
+ VP_HELPER_TX_EXTRA(DGUS_Addr::FILAMENT_Length,
+ &DGUSScreenHandler::filament_length,
+ &DGUSTxHandler::ExtraToInteger),
+
+ VP_HELPER_TX_AUTO(DGUS_Addr::MOVE_CurrentX,
+ ¤t_position.x,
+ (&DGUSTxHandler::ExtraToFixedPoint)),
+ VP_HELPER_TX_AUTO(DGUS_Addr::MOVE_CurrentY,
+ ¤t_position.y,
+ (&DGUSTxHandler::ExtraToFixedPoint)),
+ VP_HELPER_TX_AUTO(DGUS_Addr::MOVE_CurrentZ,
+ ¤t_position.z,
+ (&DGUSTxHandler::ExtraToFixedPoint)),
+ VP_HELPER_TX_EXTRA(DGUS_Addr::MOVE_StepIcons,
+ &DGUSScreenHandler::move_steps,
+ &DGUSTxHandler::StepIcons),
+
+ VP_HELPER_TX(DGUS_Addr::SETTINGS2_BLTouch, &DGUSTxHandler::BLTouch),
+
+ VP_HELPER_TX(DGUS_Addr::PID_HeaterIcons, &DGUSTxHandler::PIDIcons),
+ VP_HELPER_TX_EXTRA(DGUS_Addr::PID_Temp,
+ &DGUSScreenHandler::pid_temp,
+ &DGUSTxHandler::ExtraToInteger),
+ VP_HELPER_DWORD(DGUS_Addr::PID_Kp,
+ VPFLAG_AUTOUPLOAD,
+ nullptr,
+ nullptr,
+ &DGUSTxHandler::PIDKp),
+ VP_HELPER_DWORD(DGUS_Addr::PID_Ki,
+ VPFLAG_AUTOUPLOAD,
+ nullptr,
+ nullptr,
+ &DGUSTxHandler::PIDKi),
+ VP_HELPER_DWORD(DGUS_Addr::PID_Kd,
+ VPFLAG_AUTOUPLOAD,
+ nullptr,
+ nullptr,
+ &DGUSTxHandler::PIDKd),
+
+ VP_HELPER(DGUS_Addr::INFOS_Machine,
+ DGUS_MACHINE_LEN,
+ VPFLAG_NONE,
+ (void*)DGUS_MACHINENAME,
+ nullptr,
+ &DGUSTxHandler::ExtraPGMToString),
+ VP_HELPER_TX_SIZE(DGUS_Addr::INFOS_BuildVolume,
+ DGUS_BUILDVOLUME_LEN,
+ &DGUSTxHandler::BuildVolume),
+ VP_HELPER(DGUS_Addr::INFOS_Version,
+ DGUS_VERSION_LEN,
+ VPFLAG_NONE,
+ (void*)DGUS_MARLINVERSION,
+ nullptr,
+ &DGUSTxHandler::ExtraPGMToString),
+ VP_HELPER_TX(DGUS_Addr::INFOS_TotalPrints, &DGUSTxHandler::TotalPrints),
+ VP_HELPER_TX(DGUS_Addr::INFOS_FinishedPrints, &DGUSTxHandler::FinishedPrints),
+ VP_HELPER_TX_SIZE(DGUS_Addr::INFOS_PrintTime,
+ DGUS_PRINTTIME_LEN,
+ &DGUSTxHandler::PrintTime),
+ VP_HELPER_TX_SIZE(DGUS_Addr::INFOS_LongestPrint,
+ DGUS_LONGESTPRINT_LEN,
+ &DGUSTxHandler::LongestPrint),
+ VP_HELPER_TX_SIZE(DGUS_Addr::INFOS_FilamentUsed,
+ DGUS_FILAMENTUSED_LEN,
+ &DGUSTxHandler::FilamentUsed),
+
+ VP_HELPER_TX(DGUS_Addr::WAIT_Icons, &DGUSTxHandler::WaitIcons),
+
+ // READ-WRITE VARIABLES
+
+ VP_HELPER(DGUS_Addr::FAN0_Speed,
+ 2,
+ VPFLAG_AUTOUPLOAD,
+ nullptr,
+ &DGUSRxHandler::FanSpeed,
+ &DGUSTxHandler::FanSpeed),
+
+ VP_HELPER(DGUS_Addr::GCODE_Data,
+ DGUS_GCODE_LEN,
+ VPFLAG_RXSTRING,
+ (void*)DGUSScreenHandler::gcode,
+ &DGUSRxHandler::StringToExtra,
+ &DGUSTxHandler::ExtraToString),
+
+ VP_HELPER(DGUS_Addr::PID_Cycles,
+ 2,
+ VPFLAG_NONE,
+ &DGUSScreenHandler::pid_cycles,
+ &DGUSRxHandler::IntegerToExtra,
+ &DGUSTxHandler::ExtraToInteger),
+
+ VP_HELPER(DGUS_Addr::VOLUME_Level,
+ 2,
+ VPFLAG_NONE,
+ nullptr,
+ &DGUSRxHandler::Volume,
+ &DGUSTxHandler::Volume),
+
+ VP_HELPER(DGUS_Addr::BRIGHTNESS_Level,
+ 2,
+ VPFLAG_NONE,
+ nullptr,
+ &DGUSRxHandler::Brightness,
+ &DGUSTxHandler::Brightness),
+
+ // SPECIAL CASES
+
+ VP_HELPER_TX(DGUS_Addr::STATUS_Percent_Complete, &DGUSTxHandler::Percent),
+ VP_HELPER_RX_NODATA(DGUS_Addr::INFOS_Debug, &DGUSRxHandler::Debug),
+
+ VP_HELPER((DGUS_Addr)0, 0, VPFLAG_NONE, nullptr, nullptr, nullptr)
+
+};
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VPList.h b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VPList.h
new file mode 100644
index 000000000000..d481fbab5c42
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/definition/DGUS_VPList.h
@@ -0,0 +1,26 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "DGUS_VP.h"
+
+extern const struct DGUS_VP vp_list[];
diff --git a/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp b/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp
new file mode 100644
index 000000000000..4d57fbd7e2f8
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp
@@ -0,0 +1,142 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_RELOADED)
+
+#include "../ui_api.h"
+#include "DGUSScreenHandler.h"
+
+namespace ExtUI {
+
+ void onStartup() { dgus_screen_handler.Init(); }
+
+ void onIdle() {
+ static bool processing = false;
+
+ // Prevent recursion
+ if (!processing) {
+ processing = true;
+ dgus_screen_handler.Loop();
+ processing = false;
+ }
+ }
+
+ void onPrinterKilled(PGM_P error, PGM_P component) {
+ dgus_screen_handler.PrinterKilled(error, component);
+ }
+
+ void onMediaInserted() { TERN_(SDSUPPORT, dgus_screen_handler.SDCardInserted()); }
+ void onMediaError() { TERN_(SDSUPPORT, dgus_screen_handler.SDCardError()); }
+ void onMediaRemoved() { TERN_(SDSUPPORT, dgus_screen_handler.SDCardRemoved()); }
+
+ void onPlayTone(const uint16_t frequency, const uint16_t duration) {
+ dgus_screen_handler.PlayTone(frequency, duration);
+ }
+
+ void onPrintTimerStarted() {
+ dgus_screen_handler.PrintTimerStarted();
+ }
+
+ void onPrintTimerPaused() {
+ dgus_screen_handler.PrintTimerPaused();
+ }
+
+ void onPrintTimerStopped() {
+ dgus_screen_handler.PrintTimerStopped();
+ }
+
+ void onFilamentRunout(const extruder_t extruder) {
+ dgus_screen_handler.FilamentRunout(extruder);
+ }
+
+ void onUserConfirmRequired(const char * const msg) {
+ dgus_screen_handler.UserConfirmRequired(msg);
+ }
+
+ void onStatusChanged(const char * const msg) {
+ dgus_screen_handler.SetStatusMessage(msg);
+ }
+
+ void onHomingStart() {}
+ void onHomingComplete() {}
+ void onPrintFinished() {}
+
+ void onFactoryReset() {
+ dgus_screen_handler.SettingsReset();
+ }
+
+ void onStoreSettings(char *buff) {
+ dgus_screen_handler.StoreSettings(buff);
+ }
+
+ void onLoadSettings(const char *buff) {
+ dgus_screen_handler.LoadSettings(buff);
+ }
+
+ void onPostprocessSettings() {}
+
+ void onConfigurationStoreWritten(bool success) {
+ dgus_screen_handler.ConfigurationStoreWritten(success);
+ }
+
+ void onConfigurationStoreRead(bool success) {
+ dgus_screen_handler.ConfigurationStoreRead(success);
+ }
+
+ #if HAS_MESH
+ void onMeshLevelingStart() {}
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) {
+ dgus_screen_handler.MeshUpdate(xpos, ypos);
+ }
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const probe_state_t state) {
+ if (state == G29_POINT_FINISH)
+ dgus_screen_handler.MeshUpdate(xpos, ypos);
+ }
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ void onPowerLossResume() {
+ // Called on resume from power-loss
+ dgus_screen_handler.PowerLossResume();
+ }
+ #endif
+
+ #if HAS_PID_HEATING
+ void onPidTuning(const result_t rst) {
+ // Called for temperature PID tuning result
+ dgus_screen_handler.PidTuning(rst);
+ }
+ #endif
+
+ void onSteppersDisabled() {}
+ void onSteppersEnabled() {}
+}
+
+#endif // DGUS_LCD_UI_RELOADED
diff --git a/ini/features.ini b/ini/features.ini
index fa7d1519389e..4a1c638de273 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -78,7 +78,8 @@ HAS_MENU_TRAMMING = src_filter=+
ANYCUBIC_LCD_CHIRON = src_filter=+
ANYCUBIC_LCD_I3MEGA = src_filter=+
-HAS_DGUS_LCD = src_filter=+
+HAS_DGUS_LCD_CLASSIC = src_filter=+
+DGUS_LCD_UI_RELOADED = src_filter=+
DGUS_LCD_UI_FYSETC = src_filter=+
DGUS_LCD_UI_HIPRECY = src_filter=+
DGUS_LCD_UI_MKS = src_filter=+
diff --git a/platformio.ini b/platformio.ini
index 9ee1e76a5b14..55c7577e3731 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -77,6 +77,7 @@ default_src_filter = + - - +
-
-
- - - - -
+ -
-
-
-