diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index becad3f2f0..7f6e7daed5 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -3132,15 +3132,23 @@
//#define TOUCH_UI_FTDI_EVE
//
-// Touch-screen LCD for Anycubic printers
+// Touch-screen LCD for Anycubic Chiron
+//
+//#define ANYCUBIC_LCD_CHIRON
+
+//
+// Touch-screen LCD for Anycubic i3 Mega
//
//#define ANYCUBIC_LCD_I3MEGA
-//#define ANYCUBIC_LCD_CHIRON
-#if EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
- //#define ANYCUBIC_LCD_DEBUG
+#if ENABLED(ANYCUBIC_LCD_I3MEGA)
//#define ANYCUBIC_LCD_GCODE_EXT // Add ".gcode" to menu entries for DGUS clone compatibility
#endif
+//
+// Touch-screen LCD for Anycubic Vyper
+//
+//#define ANYCUBIC_LCD_VYPER
+
//
// 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028
//
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index eb04f473b7..e8fc947d3e 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -1957,7 +1957,7 @@
//
// Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
//
-#if ANY(DOGLCD, TFT_COLOR_UI, TOUCH_UI_FTDI_EVE, IS_DWIN_MARLINUI)
+#if ANY(DOGLCD, TFT_COLOR_UI, TOUCH_UI_FTDI_EVE, IS_DWIN_MARLINUI, ANYCUBIC_LCD_VYPER)
//#define LCD_LANGUAGE_2 fr
//#define LCD_LANGUAGE_3 de
//#define LCD_LANGUAGE_4 es
diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h
index 63bec2b720..15d61d30d1 100644
--- a/Marlin/src/HAL/LPC1768/HAL.h
+++ b/Marlin/src/HAL/LPC1768/HAL.h
@@ -249,9 +249,9 @@ public:
static bool adc_ready() { return LPC176x::adc_hardware.done(LPC176x::pin_get_adc_channel(adc_pin)); }
// The current value of the ADC register
- static uint16_t adc_value() {
+ static uint16_t adc_value() {
adc_result = FilteredADC::read(adc_pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
- return uint16_t(adc_result);
+ return uint16_t(adc_result);
}
/**
diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h
index 8a1cec714e..0ca26d2ab2 100644
--- a/Marlin/src/core/boards.h
+++ b/Marlin/src/core/boards.h
@@ -382,6 +382,7 @@
#define BOARD_ERYONE_ERY32_MINI 5065 // Eryone Ery32 mini (STM32F103VE)
#define BOARD_PANDA_PI_V29 5066 // Panda Pi V2.9 - Standalone (STM32F103RC)
#define BOARD_SOVOL_V131 5067 // Sovol V1.3.1 (GD32F103RET6)
+#define BOARD_TRIGORILLA_V006 5068 // Trigorilla V0.0.6 (GD32F103RE)
//
// ARM Cortex-M4F
diff --git a/Marlin/src/feature/bedlevel/abl/bbl.cpp b/Marlin/src/feature/bedlevel/abl/bbl.cpp
index d0044303c7..6ef3945fa5 100644
--- a/Marlin/src/feature/bedlevel/abl/bbl.cpp
+++ b/Marlin/src/feature/bedlevel/abl/bbl.cpp
@@ -175,13 +175,13 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values/*=nullptr
xy_float_t LevelingBilinear::grid_factor_virt;
#define LINEAR_EXTRAPOLATION(E, I) ((E) * 2 - (I))
- float LevelingBilinear::bed_level_virt_coord(const uint8_t x, const uint8_t y) {
+ float LevelingBilinear::virt_coord(const uint8_t x, const uint8_t y) {
uint8_t ep = 0, ip = 1;
if (x > (GRID_MAX_POINTS_X) + 1 || y > (GRID_MAX_POINTS_Y) + 1) {
// The requested point requires extrapolating two points beyond the mesh.
// These values are only requested for the edges of the mesh, which are always an actual mesh point,
// and do not require interpolation. When interpolation is not needed, this "Mesh + 2" point is
- // cancelled out in bed_level_virt_cmr and does not impact the result. Return 0.0 rather than
+ // cancelled out in virt_cmr and does not impact the result. Return 0.0 rather than
// making this function more complex by extrapolating two points.
return 0.0;
}
@@ -197,8 +197,8 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values/*=nullptr
);
else
return LINEAR_EXTRAPOLATION(
- bed_level_virt_coord(ep + 1, y),
- bed_level_virt_coord(ip + 1, y)
+ virt_coord(ep + 1, y),
+ virt_coord(ip + 1, y)
);
}
if (!y || y == ABL_TEMP_POINTS_Y - 1) {
@@ -213,14 +213,14 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values/*=nullptr
);
else
return LINEAR_EXTRAPOLATION(
- bed_level_virt_coord(x, ep + 1),
- bed_level_virt_coord(x, ip + 1)
+ virt_coord(x, ep + 1),
+ virt_coord(x, ip + 1)
);
}
return z_values[x - 1][y - 1];
}
- float LevelingBilinear::bed_level_virt_cmr(const float p[4], const uint8_t i, const float t) {
+ float LevelingBilinear::virt_cmr(const float p[4], const uint8_t i, const float t) {
return (
p[i-1] * -t * sq(1 - t)
+ p[i] * (2 - 5 * sq(t) + 3 * t * sq(t))
@@ -229,18 +229,18 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values/*=nullptr
) * 0.5f;
}
- float LevelingBilinear::bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty) {
+ float LevelingBilinear::virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty) {
float row[4], column[4];
LOOP_L_N(i, 4) {
LOOP_L_N(j, 4) {
- column[j] = bed_level_virt_coord(i + x - 1, j + y - 1);
+ column[j] = virt_coord(i + x - 1, j + y - 1);
}
- row[i] = bed_level_virt_cmr(column, 1, ty);
+ row[i] = virt_cmr(column, 1, ty);
}
- return bed_level_virt_cmr(row, 1, tx);
+ return virt_cmr(row, 1, tx);
}
- void LevelingBilinear::bed_level_virt_interpolate() {
+ void LevelingBilinear::subdivide_mesh() {
grid_spacing_virt = grid_spacing / (BILINEAR_SUBDIVISIONS);
grid_factor_virt = grid_spacing_virt.reciprocal();
LOOP_L_N(y, GRID_MAX_POINTS_Y)
@@ -250,12 +250,7 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values/*=nullptr
if ((ty && y == (GRID_MAX_POINTS_Y) - 1) || (tx && x == (GRID_MAX_POINTS_X) - 1))
continue;
z_values_virt[x * (BILINEAR_SUBDIVISIONS) + tx][y * (BILINEAR_SUBDIVISIONS) + ty] =
- bed_level_virt_2cmr(
- x + 1,
- y + 1,
- (float)tx / (BILINEAR_SUBDIVISIONS),
- (float)ty / (BILINEAR_SUBDIVISIONS)
- );
+ virt_2cmr(x + 1, y + 1, (float)tx / (BILINEAR_SUBDIVISIONS), (float)ty / (BILINEAR_SUBDIVISIONS));
}
}
@@ -263,7 +258,7 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values/*=nullptr
// Refresh after other values have been updated
void LevelingBilinear::refresh_bed_level() {
- TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
+ TERN_(ABL_BILINEAR_SUBDIVISION, subdivide_mesh());
cached_rel.x = cached_rel.y = -999.999;
cached_g.x = cached_g.y = -99;
}
diff --git a/Marlin/src/feature/bedlevel/abl/bbl.h b/Marlin/src/feature/bedlevel/abl/bbl.h
index 60dde9060f..ca2e96593f 100644
--- a/Marlin/src/feature/bedlevel/abl/bbl.h
+++ b/Marlin/src/feature/bedlevel/abl/bbl.h
@@ -43,10 +43,10 @@ private:
static xy_pos_t grid_spacing_virt;
static xy_float_t grid_factor_virt;
- static float bed_level_virt_coord(const uint8_t x, const uint8_t y);
- static float bed_level_virt_cmr(const float p[4], const uint8_t i, const float t);
- static float bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty);
- static void bed_level_virt_interpolate();
+ static float virt_coord(const uint8_t x, const uint8_t y);
+ static float virt_cmr(const float p[4], const uint8_t i, const float t);
+ static float virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty);
+ static void subdivide_mesh();
#endif
public:
diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp
index dd20d04278..29c4695ca4 100644
--- a/Marlin/src/feature/powerloss.cpp
+++ b/Marlin/src/feature/powerloss.cpp
@@ -113,7 +113,7 @@ void PrintJobRecovery::changed() {
purge();
else if (IS_SD_PRINTING())
save(true);
- TERN_(EXTENSIBLE_UI, ExtUI::onSetPowerLoss(onoff));
+ TERN_(EXTENSIBLE_UI, ExtUI::onSetPowerLoss(enabled));
}
/**
diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp
index c951fc6333..edf0ddfdbf 100644
--- a/Marlin/src/gcode/queue.cpp
+++ b/Marlin/src/gcode/queue.cpp
@@ -303,6 +303,24 @@ static bool serial_data_available(serial_index_t index) {
inline int read_serial(const serial_index_t index) { return SERIAL_IMPL.read(index); }
+#if (defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32)) && defined(USBCON)
+
+ /**
+ * arduinoststm32's USB receive buffer is not well behaved when the buffer overflows
+ *
+ * This can happen when the host programs (such as Pronterface) automatically
+ * send M105 temperature requests.
+ */
+ void GCodeQueue::flush_rx() {
+ // Flush receive buffer
+ LOOP_L_N(p, NUM_SERIAL) {
+ if (!serial_data_available(p)) continue; // No data for this port? Skip.
+ while (SERIAL_IMPL.available(p)) (void)read_serial(p);
+ }
+ }
+
+#endif // (ARDUINO_ARCH_STM32F4 || ARDUINO_ARCH_STM32) && USBCON
+
void GCodeQueue::gcode_line_error(FSTR_P const ferr, const serial_index_t serial_ind) {
PORT_REDIRECT(SERIAL_PORTMASK(serial_ind)); // Reply to the serial port that sent the command
SERIAL_ERROR_START();
diff --git a/Marlin/src/gcode/queue.h b/Marlin/src/gcode/queue.h
index 1422830080..19fb359e15 100644
--- a/Marlin/src/gcode/queue.h
+++ b/Marlin/src/gcode/queue.h
@@ -201,6 +201,12 @@ public:
*/
static void flush_and_request_resend(const serial_index_t serial_ind);
+ #if (defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32)) && defined(USBCON)
+ static void flush_rx();
+ #else
+ static void flush_rx() {}
+ #endif
+
/**
* (Re)Set the current line number for the last received command
*/
diff --git a/Marlin/src/gcode/temp/M303.cpp b/Marlin/src/gcode/temp/M303.cpp
index e0ad26027e..48eebaa0e4 100644
--- a/Marlin/src/gcode/temp/M303.cpp
+++ b/Marlin/src/gcode/temp/M303.cpp
@@ -25,6 +25,7 @@
#if HAS_PID_HEATING
#include "../gcode.h"
+#include "../queue.h" // for flush_tx
#include "../../lcd/marlinui.h"
#include "../../module/temperature.h"
@@ -85,6 +86,8 @@ void GcodeSuite::M303() {
LCD_MESSAGE(MSG_PID_AUTOTUNE);
thermalManager.PID_autotune(temp, hid, c, u);
ui.reset_status();
+
+ queue.flush_rx();
}
#endif // HAS_PID_HEATING
diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 3c821e5306..403db47e42 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -477,7 +477,7 @@
#endif
// Aliases for LCD features
-#if !DGUS_UI_IS(NONE)
+#if !DGUS_UI_IS(NONE) || ENABLED(ANYCUBIC_LCD_VYPER)
#define HAS_DGUS_LCD 1
#if DGUS_UI_IS(ORIGIN, FYSETC, HIPRECY, MKS)
#define HAS_DGUS_LCD_CLASSIC 1
@@ -485,7 +485,7 @@
#endif
// Extensible UI serial touch screens. (See src/lcd/extui)
-#if ANY(HAS_DGUS_LCD, MALYAN_LCD, TOUCH_UI_FTDI_EVE, ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, NEXTION_TFT)
+#if ANY(HAS_DGUS_LCD, MALYAN_LCD, TOUCH_UI_FTDI_EVE, ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, ANYCUBIC_LCD_VYPER, NEXTION_TFT)
#define IS_EXTUI 1
#define EXTENSIBLE_UI
#endif
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 1f43d01bb8..e67a4c9e49 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -3140,7 +3140,7 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
+ (ENABLED(EXTENSIBLE_UI) && DISABLED(IS_EXTUI)) \
+ (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(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, ANYCUBIC_TFT35, ANYCUBIC_LCD_VYPER) \
+ DGUS_UI_IS(ORIGIN) + DGUS_UI_IS(FYSETC) + DGUS_UI_IS(HIPRECY) + DGUS_UI_IS(MKS) + DGUS_UI_IS(RELOADED) + DGUS_UI_IS(IA_CREALITY) \
+ COUNT_ENABLED(ENDER2_STOCKDISPLAY, CR10_STOCKDISPLAY) \
+ COUNT_ENABLED(DWIN_CREALITY_LCD, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI, DWIN_MARLINUI_PORTRAIT, DWIN_MARLINUI_LANDSCAPE) \
@@ -3254,6 +3254,10 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#endif
#endif
+#if ENABLED(ANYCUBIC_LCD_VYPER)
+ static_assert(strcmp(STRINGIFY(LCD_LANGUAGE_2), "zh_CN") == 0, "LCD_LANGUAGE_2 must be set to zh_CN for ANYCUBIC_LCD_VYPER.");
+#endif
+
#if EITHER(MKS_TS35_V2_0, BTT_TFT35_SPI_V1_0) && SD_CONNECTION_IS(LCD)
#error "SDCARD_CONNECTION cannot be set to LCD for the enabled TFT. No available SD card reader."
#endif
@@ -3353,8 +3357,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#else
#if HAS_DGUS_LCD
#error "The DGUS LCD requires LCD_SERIAL_PORT to be defined."
- #elif EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
- #error "The ANYCUBIC LCD requires LCD_SERIAL_PORT to be defined."
+ #elif ANY(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, ANYCUBIC_LCD_VYPER)
+ #error "ANYCUBIC_LCD_* requires LCD_SERIAL_PORT to be defined."
#elif ENABLED(MALYAN_LCD)
#error "MALYAN_LCD requires LCD_SERIAL_PORT to be defined."
#elif ENABLED(NEXTION_LCD)
diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp
index 405e7a351e..3b9bc17b6f 100644
--- a/Marlin/src/inc/Warnings.cpp
+++ b/Marlin/src/inc/Warnings.cpp
@@ -780,8 +780,8 @@
/**
* GD32 is not exactly like STM32
*/
-#if MB(SOVOL_V131)
- #warning "GD32 based controllers may not be fully compatible with Maple Generic STM32F103RE. Please report any issues."
+#if MB(SOVOL_V131, TRIGORILLA_V006)
+ #warning "GD32 based controllers may not be fully compatible with STM32 platforms. Please report any issues."
#endif
/**
diff --git a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp
index 285729cc15..dce503776b 100644
--- a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp
+++ b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp
@@ -72,14 +72,6 @@ void ChironTFT::Startup() {
live_Zoffset = 0.0;
file_menu = AC_menu_file;
- // Setup pins for powerloss detection
- // Two IO pins are connected on the Trigorilla Board
- // On a power interruption the OUTAGECON_PIN goes low.
-
- #if ENABLED(POWER_LOSS_RECOVERY)
- OUT_WRITE(OUTAGECON_PIN, HIGH);
- #endif
-
// Filament runout is handled by Marlin settings in Configuration.h
// opt_set FIL_RUNOUT_STATE HIGH // Pin state indicating that filament is NOT present.
// opt_enable FIL_RUNOUT_PULLUP
diff --git a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.h b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.h
index c9a32e584d..e0517ec640 100644
--- a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.h
+++ b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.h
@@ -76,7 +76,6 @@ class ChironTFT {
static void CheckHeaters();
static void SendFileList(int8_t);
static void SelectFile();
- static void InjectCommandandWait(PGM_P);
static void ProcessPanelRequest();
static void PanelInfo(uint8_t);
static void PanelAction(uint8_t);
diff --git a/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp b/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp
index 774ba55e43..1bc52bfcaf 100644
--- a/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp
+++ b/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp
@@ -23,6 +23,8 @@
#if ENABLED(ANYCUBIC_LCD_I3MEGA)
+//#define ANYCUBIC_LCD_DEBUG
+
#include "anycubic_i3mega_lcd.h"
#include "../ui_api.h"
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/FileNavigator.cpp b/Marlin/src/lcd/extui/anycubic_vyper/FileNavigator.cpp
new file mode 100644
index 0000000000..38603f5679
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/FileNavigator.cpp
@@ -0,0 +1,161 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/anycubic_vyper/FileNavigator.cpp
+ */
+
+/***************************************************************************
+ * The AC panel wants files in block of 4 and can only display a flat list *
+ * This library allows full folder traversal. *
+ ***************************************************************************/
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_VYPER)
+
+#include "FileNavigator.h"
+#include "dgus_tft.h"
+
+using namespace ExtUI;
+
+namespace Anycubic {
+
+ FileList FileNavigator::filelist; // Instance of the Marlin file API
+ char FileNavigator::currentfoldername[MAX_PATH_LEN]; // Current folder path
+ uint16_t FileNavigator::lastindex;
+ uint8_t FileNavigator::folderdepth;
+ uint16_t FileNavigator::currentindex; // override the panel request
+
+ FileNavigator filenavigator;
+
+ FileNavigator::FileNavigator() { reset(); }
+
+ void FileNavigator::reset() {
+ currentfoldername[0] = '\0';
+ folderdepth = 0;
+ currentindex = 0;
+ lastindex = 0;
+ // Start at root folder
+ while (!filelist.isAtRootDir()) filelist.upDir();
+ refresh();
+ }
+
+ void FileNavigator::refresh() { filelist.refresh(); }
+
+ void FileNavigator::getFiles(uint16_t index) {
+ uint8_t files = 5;
+ if (index == 0) currentindex = 0;
+
+ // Each time we change folder we reset the file index to 0 and keep track
+ // of the current position as the TFT panel isnt aware of folders trees.
+ if (index > 0) {
+ //--currentindex; // go back a file to take account off the .. we added to the root.
+ if (index > lastindex)
+ currentindex += files;
+ else
+ currentindex = currentindex < 5 ? 0 : currentindex - files;
+ }
+ lastindex = index;
+
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPGM("index=", index, " currentindex=", currentindex, " lastindex=", lastindex);
+ #endif
+
+ uint8_t file_num = 0;
+ for (uint16_t _seek = currentindex; _seek < currentindex + files; _seek++) {
+
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPGM("_seek: ", _seek, " currentindex: ", currentindex, " files: ", files);
+ #endif
+
+ if (filelist.seek(_seek)) {
+ //sendFile();
+
+ DgusTFT::SendTxtToTFT(filelist.longFilename(), TXT_FILE_0 + file_num*0x30);
+
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPGM("seek: ", _seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
+ #endif
+ }
+ else {
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPGM("over seek: ", _seek);
+ #endif
+
+ DgusTFT::SendTxtToTFT("\0", TXT_FILE_0 + file_num*0x30);
+ }
+
+ file_num++;
+ }
+ }
+
+ void FileNavigator::sendFile() {
+ // Send the file and folder info to the panel.
+ // This info will be returned when the file is selected.
+ // Permitted special characters in file name: -_*#~
+ // Panel can display 22 characters per line.
+ if (!filelist.isDir())
+ DgusTFT::SendTxtToTFT(filelist.longFilename(), TXT_FILE_0);
+ }
+
+ void FileNavigator::changeDIR(char *folder) {
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPGM("currentfolder: ", currentfoldername, " New: ", folder);
+ #endif
+ if (folderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
+ strcat(currentfoldername, folder);
+ strcat(currentfoldername, "/");
+ filelist.changeDir(folder);
+ refresh();
+ folderdepth++;
+ currentindex = 0;
+ }
+
+ void FileNavigator::upDIR() {
+ filelist.upDir();
+ refresh();
+ folderdepth--;
+ currentindex = 0;
+ // Remove the last child folder from the stored path
+ if (folderdepth == 0) {
+ currentfoldername[0] = '\0';
+ reset();
+ }
+ else {
+ char *pos = nullptr;
+ for (uint8_t f = 0; f < folderdepth; f++)
+ pos = strchr(currentfoldername, '/');
+
+ *(pos + 1) = '\0';
+ }
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPGM("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
+ #endif
+ }
+
+ char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
+
+ uint16_t FileNavigator::getFileNum() { return filelist.count(); }
+}
+
+#endif // ANYCUBIC_LCD_VYPER
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/FileNavigator.h b/Marlin/src/lcd/extui/anycubic_vyper/FileNavigator.h
new file mode 100644
index 0000000000..c39e66b63e
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/FileNavigator.h
@@ -0,0 +1,57 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * lcd/extui/anycubic_vyper/FileNavigator.h
+ */
+
+#include "dgus_tft_defs.h"
+#include "../ui_api.h"
+
+using namespace ExtUI;
+
+namespace Anycubic {
+ class FileNavigator {
+ public:
+ FileNavigator();
+
+ static FileList filelist;
+
+ void reset();
+ void getFiles(uint16_t);
+ void upDIR();
+ void changeDIR(char *);
+ void sendFile();
+ void refresh();
+ char * getCurrentFolderName();
+ uint16_t getFileNum();
+
+ private:
+
+ static char currentfoldername[MAX_PATH_LEN];
+ static uint16_t lastindex;
+ static uint8_t folderdepth;
+ static uint16_t currentindex;
+ };
+ extern FileNavigator filenavigator;
+}
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/Tunes.cpp b/Marlin/src/lcd/extui/anycubic_vyper/Tunes.cpp
new file mode 100644
index 0000000000..d7f0e4b6d4
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/Tunes.cpp
@@ -0,0 +1,58 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/anycubic_vyper/Tunes.cpp
+ */
+
+/***********************************************************************
+ * A Utility to play tunes using the buzzer in the printer controller. *
+ * See Tunes.h for note and tune definitions. *
+ ***********************************************************************/
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_VYPER)
+
+#include "Tunes.h"
+#include "../ui_api.h"
+
+namespace Anycubic {
+
+ void PlayTune(const uint8_t beeperPin, const uint16_t *tune, const uint8_t speed=1) {
+ uint8_t pos = 1;
+ uint16_t wholenotelen = tune[0] / speed;
+ do {
+ uint16_t freq = tune[pos];
+ uint16_t notelen = wholenotelen / tune[pos + 1];
+
+ ::tone(beeperPin, freq, notelen);
+ ExtUI::delay_ms(notelen);
+ pos += 2;
+
+ if (pos >= MAX_TUNE_LENGTH) break;
+ } while (tune[pos] != n_END);
+ }
+
+}
+
+#endif // ANYCUBIC_LCD_VYPER
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/Tunes.h b/Marlin/src/lcd/extui/anycubic_vyper/Tunes.h
new file mode 100644
index 0000000000..9a06768ac6
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/Tunes.h
@@ -0,0 +1,220 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * lcd/extui/anycubic_vyper/Tunes.h
+ */
+
+/**************************************************************************
+ * Notes definition from https://pages.mtu.edu/~suits/NoteFreqCalcs.html *
+ * *
+ * The format of a tune is: *
+ * {,,, ,, ... } *
+ * *
+ * 1) The first value is the length of a whole note in milliseconds *
+ * 2) Then a sequence of pitch and duration pairs *
+ * 3) Finally the END marker so your tunes can be any length up to *
+ * MAX_TUNE_LEN *
+ *************************************************************************/
+
+#include
+
+#define MAX_TUNE_LENGTH 128
+
+// Special notes!
+#define n_P 0 // silence or pause
+#define n_END 10000 // end of tune marker
+
+// Note duration divisors
+#define l_T1 1
+#define l_T2 2
+#define l_T3 3
+#define l_T4 4
+#define l_T8 8
+#define l_T16 16
+
+// Note Frequency
+#define n_C0 16
+#define n_CS0 17
+#define n_D0 18
+#define n_DS0 19
+#define n_E0 21
+#define n_F0 22
+#define n_FS0 23
+#define n_G0 25
+#define n_GS0 26
+#define n_A0 28
+#define n_AS0 29
+#define n_B0 31
+#define n_C1 33
+#define n_CS1 35
+#define n_D1 37
+#define n_DS1 39
+#define n_E1 41
+#define n_F1 44
+#define n_FS1 46
+#define n_G1 49
+#define n_GS1 52
+#define n_A1 55
+#define n_AS1 58
+#define n_B1 62
+#define n_C2 65
+#define n_CS2 69
+#define n_D2 73
+#define n_DS2 78
+#define n_E2 82
+#define n_F2 87
+#define n_FS2 93
+#define n_G2 98
+#define n_GS2 104
+#define n_A2 110
+#define n_AS2 117
+#define n_B2 123
+#define n_C3 131
+#define n_CS3 139
+#define n_D3 147
+#define n_DS3 156
+#define n_E3 165
+#define n_F3 175
+#define n_FS3 185
+#define n_G3 196
+#define n_GS3 208
+#define n_A3 220
+#define n_AS3 233
+#define n_B3 247
+#define n_C4 262
+#define n_CS4 277
+#define n_D4 294
+#define n_DS4 311
+#define n_E4 330
+#define n_F4 349
+#define n_FS4 370
+#define n_G4 392
+#define n_GS4 415
+#define n_A4 440
+#define n_AS4 466
+#define n_B4 494
+#define n_C5 523
+#define n_CS5 554
+#define n_D5 587
+#define n_DS5 622
+#define n_E5 659
+#define n_F5 698
+#define n_FS5 740
+#define n_G5 784
+#define n_GS5 831
+#define n_A5 880
+#define n_AS5 932
+#define n_B5 988
+#define n_C6 1047
+#define n_CS6 1109
+#define n_D6 1175
+#define n_DS6 1245
+#define n_E6 1319
+#define n_F6 1397
+#define n_FS6 1480
+#define n_G6 1568
+#define n_GS6 1661
+#define n_A6 1760
+#define n_AS6 1865
+#define n_B6 1976
+#define n_C7 2093
+#define n_CS7 2217
+#define n_D7 2349
+#define n_DS7 2489
+#define n_E7 2637
+#define n_F7 2794
+#define n_FS7 2960
+#define n_G7 3136
+#define n_GS7 3322
+#define n_A7 3520
+#define n_AS7 3729
+#define n_B7 3951
+#define n_C8 4186
+#define n_CS8 4435
+#define n_D8 4699
+#define n_DS8 4978
+#define n_E8 5274
+#define n_F8 5587
+#define n_FS8 5920
+#define n_G8 6272
+#define n_GS8 6645
+#define n_A8 7040
+#define n_AS8 7459
+#define n_B8 7902
+
+namespace Anycubic {
+
+ void PlayTune(const uint8_t beeperPin, const uint16_t *tune, const uint8_t speed);
+
+ // Only uncomment the tunes you are using to save memory
+ // This will help you write tunes!
+ // https://www.apronus.com/music/flashpiano.htm
+
+ const uint16_t SOS[] = {
+ 250,
+ n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T1,
+ n_G6,l_T1, n_P,l_T3, n_G6,l_T1, n_P,l_T3, n_G6,l_T1, n_P,l_T1,
+ n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T1,
+ n_END
+ };
+
+ const uint16_t BeepBeep[] = {
+ 500,
+ n_C7,l_T8, n_P,l_T16, n_C7,l_T8, n_P,l_T8,
+ n_END
+ };
+
+ const uint16_t BeepBeepBeeep[] = {
+ 1000,
+ n_G7,l_T4, n_P,l_T16, n_G7,l_T4, n_P,l_T8, n_G7,l_T2,
+ n_END
+ };
+
+ const uint16_t Anycubic_PowerOn[] = {
+ 1000,
+ n_F7,l_T8, n_P,l_T8, n_C7,l_T8, n_P,l_T8, n_D7,l_T8, n_P,l_T8,
+ n_E7,l_T8, n_P,l_T8, n_D7,l_T4, n_P,l_T4, n_G7,l_T4, n_P,l_T4,
+ n_A7,l_T2, n_P,l_T1,
+ n_END
+ };
+
+ const uint16_t GB_PowerOn[] = {
+ 500,
+ n_C6,l_T4, n_P,l_T16, n_C7,l_T2, n_P,l_T8,
+ n_END
+ };
+
+ const uint16_t Heater_Timedout[] = {
+ 1000,
+ n_C6,l_T1,
+ n_END
+ };
+
+ const uint16_t FilamentOut[] = {
+ 1000,
+ n_AS7,l_T4, n_P,l_T16, n_FS7,l_T2,
+ n_END
+ };
+
+}
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp
new file mode 100644
index 0000000000..9487f22e89
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp
@@ -0,0 +1,3305 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/anycubic_vyper/dgus_tft.cpp
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_VYPER)
+
+#include "dgus_tft.h"
+#include "Tunes.h"
+#include "FileNavigator.h"
+
+#include "../../../gcode/queue.h"
+#include "../../../sd/cardreader.h"
+#include "../../../libs/numtostr.h"
+#include "../../../MarlinCore.h"
+#include "../../../core/serial.h"
+#include "../../../module/stepper.h"
+#include "../../../module/probe.h"
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+ #include "../../../feature/powerloss.h"
+#endif
+
+#define DEBUG_OUT ACDEBUGLEVEL
+#include "../../../core/debug_out.h"
+
+#include
+
+namespace Anycubic {
+
+ const char MESSAGE_charu[] = {0xB4, 0xE6, 0xB4, 0xA2, 0xBF, 0xA8, 0xD2, 0xD1, 0xB2, 0xE5, 0xC8, 0xEB, 0x00}; // '忙'垄驴篓脪脩虏氓脠毛
+ const char MESSAGE_bachu[] = {0xB4, 0xE6, 0xB4, 0xA2, 0xBF, 0xA8, 0xD2, 0xD1, 0xB0, 0xCE, 0xB3, 0xF6, 0x00};
+ const char MESSAGE_wuka[] = {0xCE, 0xDE, 0xB4, 0xE6, 0xB4, 0xA2, 0xBF, 0xA8, 0x00};
+ const char MESSAGE_lianji[] = {0xC1, 0xAA, 0xBB, 0xFA, 0xD6, 0xD0, 0x00};
+ const char MESSAGE_tuoji[] = {0xCD, 0xD1, 0xBB, 0xFA, 0xB4, 0xF2, 0xD3, 0xA1, 0xD6, 0xD0, 0x00};
+ const char MESSAGE_zanting[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xD4, 0xDD, 0xCD, 0xA3, 0xD6, 0xD0, 0x00};
+ const char MESSAGE_tingzhi[] = {0xCD, 0xA3, 0xD6, 0xB9, 0xB4, 0xF2, 0xD3, 0xA1, 0x00};
+ const char MESSAGE_wancheng[] = {0xCD, 0xEA, 0xB3, 0xC9, 0xB4, 0xF2, 0xD3, 0xA1, 0x00};
+ const char MESSAGE_hotend_heating[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xCD, 0xB7, 0xD5, 0xFD, 0xD4, 0xDA, 0xBC, 0xD3, 0xC8, 0xC8, 0x00};
+ const char MESSAGE_hotend_over[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xCD, 0xB7, 0xBC, 0xD3, 0xC8, 0xC8, 0xCD, 0xEA, 0xB3, 0xC9, 0x00};
+ const char MESSAGE_bed_heating[] = {0xC8, 0xC8, 0xB4, 0xB2, 0xD5, 0xFD, 0xD4, 0xDA, 0xBC, 0xD3, 0xC8, 0xC8, 0x00};
+ const char MESSAGE_bed_over[] = {0xC8, 0xC8, 0xB4, 0xB2, 0xBC, 0xD3, 0xC8, 0xC8, 0xCD, 0xEA, 0xB3, 0xC9, 0x00};
+ const char MESSAGE_ready[] = {0xD7, 0xBC, 0xB1, 0xB8, 0xBE, 0xCD, 0xD0, 0xF7, 0x00};
+ const char MESSAGE_cold[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xCD, 0xB7, 0xCE, 0xC2, 0xB6, 0xC8, 0xB9, 0xFD, 0xB5, 0xCD, 0x00};
+
+ const char *p_mesage[] = { MESSAGE_charu, MESSAGE_bachu, MESSAGE_wuka, MESSAGE_lianji, MESSAGE_tuoji, MESSAGE_zanting,
+ MESSAGE_tingzhi, MESSAGE_wancheng, MESSAGE_hotend_heating, MESSAGE_hotend_over, MESSAGE_bed_heating,
+ MESSAGE_bed_over, MESSAGE_ready, MESSAGE_cold };
+
+ DgusTFT::p_fun fun_array[] = {
+ DgusTFT::page1, DgusTFT::page2, DgusTFT::page3, DgusTFT::page4, DgusTFT::page5, DgusTFT::page6,
+ DgusTFT::page7, DgusTFT::page8, DgusTFT::page9, DgusTFT::page10, DgusTFT::page11, DgusTFT::page12,
+ DgusTFT::page13, DgusTFT::page14, DgusTFT::page15, DgusTFT::page16, DgusTFT::page17, DgusTFT::page18,
+ DgusTFT::page19, DgusTFT::page20, DgusTFT::page21, DgusTFT::page22, DgusTFT::page23, DgusTFT::page24,
+ DgusTFT::page25, DgusTFT::page26, DgusTFT::page27, DgusTFT::page28, DgusTFT::page29, DgusTFT::page30,
+ DgusTFT::page31, DgusTFT::page32
+ #if HAS_LEVELING
+ , DgusTFT::page33 , DgusTFT::page34
+ #endif
+ };
+
+ printer_state_t DgusTFT::printer_state;
+ paused_state_t DgusTFT::pause_state;
+ #if HAS_HOTEND
+ heater_state_t DgusTFT::hotend_state;
+ #endif
+ #if HAS_HEATED_BED
+ heater_state_t DgusTFT::hotbed_state;
+ #endif
+ char DgusTFT::selectedfile[MAX_PATH_LEN];
+ char DgusTFT::panel_command[MAX_CMND_LEN];
+ uint8_t DgusTFT::command_len;
+ file_menu_t DgusTFT::file_menu;
+
+ bool DgusTFT::data_received;
+ uint8_t DgusTFT::data_buf[DATA_BUF_SIZE];
+ uint8_t DgusTFT::data_index;
+ uint16_t DgusTFT::page_index_now, DgusTFT::page_index_last, DgusTFT::page_index_last_2;
+ uint8_t DgusTFT::message_index;
+ uint8_t DgusTFT::pop_up_index;
+ uint32_t DgusTFT::key_value;
+ uint8_t DgusTFT::lcd_txtbox_index;
+ uint8_t DgusTFT::lcd_txtbox_page;
+ int16_t DgusTFT::feedrate_back;
+ lcd_info_t DgusTFT::lcd_info, DgusTFT::lcd_info_back;
+ language_t DgusTFT::ui_language;
+ uint16_t page_index_saved; // flags to keep from bombing the host display
+ uint8_t pop_up_index_saved;
+ uint32_t key_value_saved;
+
+ void DEBUG_PRINT_PAUSED_STATE(FSTR_P const msg, paused_state_t state);
+ void DEBUG_PRINT_PRINTER_STATE(FSTR_P const msg, printer_state_t state);
+ void DEBUG_PRINT_TIMER_EVENT(FSTR_P const msg, timer_event_t event);
+ void DEBUG_PRINT_MEDIA_EVENT(FSTR_P const msg, media_event_t event);
+
+ DgusTFT Dgus;
+
+ DgusTFT::DgusTFT() {
+ data_buf[0] = '\0';
+ message_index = 100;
+ pop_up_index = 100;
+ page_index_now = page_index_last = page_index_last_2 = 1;
+ lcd_txtbox_index = 0;
+ feedrate_back = -1;
+ }
+
+ void DgusTFT::Startup() {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("DgusTFT::Startup()");
+ #endif
+ selectedfile[0] = '\0';
+ panel_command[0] = '\0';
+ command_len = 0;
+ printer_state = AC_printer_idle;
+ pause_state = AC_paused_idle;
+ TERN_(HAS_HOTEND, hotend_state = AC_heater_off);
+ TERN_(HAS_HEATED_BED, hotbed_state = AC_heater_off);
+ file_menu = AC_menu_file;
+ set_language(ui_language); // use language stored in EEPROM
+
+ // Filament runout is handled by Marlin settings in Configuration.h
+ // opt_set FIL_RUNOUT_STATE HIGH // Pin state indicating that filament is NOT present.
+ // opt_enable FIL_RUNOUT_PULLUP
+
+ TFTSer.begin(115200);
+
+ // Signal Board has reset
+ SendtoTFTLN(AC_msg_main_board_has_reset);
+
+ // Enable levelling and Disable end stops during print
+ // as Z home places nozzle above the bed so we need to allow it past the end stops
+ injectCommands_P(AC_cmnd_enable_levelling);
+
+ // Startup tunes are defined in Tunes.h
+ //PlayTune(BEEPER_PIN, Anycubic_PowerOn, 1);
+ //PlayTune(BEEPER_PIN, GB_PowerOn, 1);
+ #if ACDEBUGLEVEL
+ DEBUG_ECHOLNPGM("Startup AC Debug Level ", ACDEBUGLEVEL);
+ #endif
+ SendtoTFTLN(AC_msg_ready);
+ }
+
+ void DgusTFT::ParamInit() {
+
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("DgusTFT::ParamInit()");
+ #endif
+
+ if (lcd_info.language == CHS)
+ page_index_now = 1;
+ else if (lcd_info.language == ENG)
+ page_index_now = 121;
+
+ LcdAudioSet(lcd_info.audio_on);
+
+ #if ACDEBUG(AC_MARLIN)
+ if (lcd_info.language == CHS)
+ DEBUG_ECHOLNPGM("ParamInit lcd language: CHS");
+ else if (lcd_info.language == ENG)
+ DEBUG_ECHOLNPGM("ParamInit lcd language: ENG");
+
+ if (lcd_info.audio_on)
+ DEBUG_ECHOLNPGM("ParamInit lcd audio: ON");
+ else
+ DEBUG_ECHOLNPGM("ParamInit lcd audio: OFF");
+ #endif
+
+ RequestValueFromTFT(0x14); // get page ID
+ }
+
+ void DgusTFT::IdleLoop() {
+ if (ReadTFTCommand()) {
+ ProcessPanelRequest();
+ command_len = 0;
+ }
+
+ #if ACDEBUG(AC_MARLIN)
+ if (key_value) {
+ DEBUG_ECHOLNPGM("IdleLoop page: ", page_index_now);
+ DEBUG_ECHOLNPGM("key: ", key_value);
+ }
+ #endif
+
+ switch (page_index_now) {
+ case 115: page115(); break;
+ case 117: page117(); break;
+ //case 124: page124(); break;
+ //case 125: page125(); break;
+ case 170: page170(); break;
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ case 171: page171(); break;
+ case 173: page173(); break;
+ #endif
+
+ #if HAS_LEVELING
+ case 175: page175(); break;
+ case 176: page176(); break;
+ #endif
+
+ case 177 ... 198: {
+ #if 0 // ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("line: ", __LINE__);
+ DEBUG_ECHOLNPGM("func: ", page_index_now);
+ #endif
+ //page177_to_198();
+ } break;
+
+ case 199 ... 200: {
+ #if 0 // ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("line: ", __LINE__);
+ DEBUG_ECHOLNPGM("func: ", page_index_now);
+ #endif
+ page199_to_200();
+ } break;
+
+ case 201: case 204: page201(); break;
+ case 202: case 205: page202(); break;
+ case 203: case 206: page203(); break;
+
+ default:
+ if (lcd_info.language == CHS) {
+ if (WITHIN(page_index_now, 1, 1 + COUNT(fun_array))) {
+ fun_array[page_index_now - 1]();
+ }
+ else {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("line: ", __LINE__);
+ DEBUG_ECHOLNPGM("fun doesn't exist: ", page_index_now);
+ #endif
+ }
+ }
+ else if (lcd_info.language == ENG) {
+ if (WITHIN(page_index_now, 121, 121 + COUNT(fun_array))) {
+ fun_array[page_index_now - 121](); // ENG page_index is 120 more than CHS
+ }
+ else {
+ SERIAL_ECHOLNPGM("lcd function doesn't exist");
+ SERIAL_ECHOLNPGM("page_index_last: ", page_index_last);
+ SERIAL_ECHOLNPGM("page_index_last_2: ", page_index_last_2);
+ }
+ }
+ break;
+ }
+
+ pop_up_manager();
+ key_value = 0;
+
+ CheckHeaters();
+ }
+
+ uint8_t FSHlength(FSTR_P FSHinput) {
+ PGM_P FSHinputPointer = reinterpret_cast(FSHinput);
+ uint8_t stringLength = 0;
+ while (pgm_read_byte(FSHinputPointer++)) stringLength++;
+ return stringLength;
+ }
+
+ void DgusTFT::PrinterKilled(FSTR_P error_p, FSTR_P component_p) {
+
+ // copy string in FLASH to RAM for strcmp_P
+
+ uint8_t textLength = FSHlength(error_p);
+ char error[FSHlength(error_p) + 1];
+ memcpy_P(error, error_p, textLength + 1); // +1 for the null terminator
+
+ textLength = FSHlength(component_p);
+ char component[FSHlength(component_p) + 1];
+ memcpy_P(component, component_p, textLength + 1); // +1 for the null terminator
+
+ SendtoTFTLN(AC_msg_kill_lcd);
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("PrinterKilled()\nerror: ", error, "\ncomponent: ", component);
+ #endif
+
+ if (strcmp_P(error, PSTR("Heating Failed")) == 0) {
+
+ if (strcmp_P(component, PSTR("Bed")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_BED_HEATER);
+ SERIAL_ECHOLNPGM("Check Bed heater");
+ }
+ else if (strcmp_P(component, PSTR("E1")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_HOTEND_HEATER);
+ SERIAL_ECHOLNPGM("Check E1 heater");
+ }
+
+ }
+ else if (strcmp_P(error, PSTR("Err: MINTEMP")) == 0) {
+
+ if (strcmp_P(component, PSTR("Bed")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_BED_NTC);
+ SERIAL_ECHOLNPGM("Check Bed thermistor");
+ }
+ else if (strcmp_P(component, PSTR("E1")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_HOTEND_NTC);
+ SERIAL_ECHOLNPGM("Check E1 thermistor");
+ }
+
+ }
+ else if (strcmp_P(error, PSTR("Err: MAXTEMP")) == 0) {
+
+ if (strcmp_P(component, PSTR("Bed")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_BED_NTC);
+ SERIAL_ECHOLNPGM("Check Bed thermistor");
+ }
+ else if (strcmp_P(component, PSTR("E1")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_HOTEND_NTC);
+ SERIAL_ECHOLNPGM("Check E1 thermistor");
+ }
+
+ }
+ else if (strcmp_P(error, PSTR("THERMAL RUNAWAY")) == 0) {
+
+ if (strcmp_P(component, PSTR("Bed")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_BED_HEATER);
+ SERIAL_ECHOLNPGM("Check Bed thermal runaway");
+ }
+ else if (strcmp_P(component, PSTR("E1")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_HOTEND_HEATER);
+ SERIAL_ECHOLNPGM("Check E1 thermal runaway");
+ }
+
+ }
+ else if (strcmp_P(error, PSTR("Homing Failed")) == 0) {
+
+ if (strcmp_P(component, PSTR("X")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_X_ENDSTOP);
+ SERIAL_ECHOLNPGM("Check X endstop");
+ }
+ else if (strcmp_P(component, PSTR("Y")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_Y_ENDSTOP);
+ SERIAL_ECHOLNPGM("Check Y endstop");
+ }
+ else if (strcmp_P(component, PSTR("Z")) == 0) {
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_Z_ENDSTOP);
+ SERIAL_ECHOLNPGM("Check Z endstop");
+ }
+
+ }
+
+ }
+
+ void DgusTFT::set_descript_color(const uint16_t color, const uint8_t index/*=lcd_txtbox_index*/) {
+ SendColorToTFT(color, TXT_DESCRIPT_0 + 0x30 * (index - 1));
+ }
+
+ void DgusTFT::MediaEvent(media_event_t event) {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_PRINT_MEDIA_EVENT(F("ProcessMediaStatus() "), event);
+ #endif
+ switch (event) {
+ case AC_media_inserted:
+
+ filenavigator.reset();
+
+ lcd_txtbox_page = 0;
+ if (lcd_txtbox_index) {
+ set_descript_color(COLOR_BLUE);
+ lcd_txtbox_index = 0;
+ }
+
+ SendFileList(lcd_txtbox_index);
+
+ break;
+
+ case AC_media_removed:
+ SendtoTFTLN(AC_msg_sd_card_removed);
+
+ filenavigator.reset();
+
+ lcd_txtbox_page = 0;
+ if (lcd_txtbox_index) {
+ set_descript_color(COLOR_BLUE);
+ lcd_txtbox_index = 0;
+ }
+
+ SendFileList(lcd_txtbox_index);
+ break;
+
+ case AC_media_error:
+ SendtoTFTLN(AC_msg_no_sd_card);
+ break;
+ }
+ }
+
+ void DgusTFT::TimerEvent(timer_event_t event) {
+
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_PRINT_TIMER_EVENT(F("TimerEvent() "), event);
+ DEBUG_PRINT_PRINTER_STATE(F("Printer State: "), printer_state);
+ #endif
+
+ switch (event) {
+ case AC_timer_started:
+ setSoftEndstopState(false); // disable endstops to print
+ printer_state = AC_printer_printing;
+ SendtoTFTLN(AC_msg_print_from_sd_card);
+ break;
+
+ case AC_timer_paused:
+ //printer_state = AC_printer_paused;
+ //pause_state = AC_paused_idle;
+ SendtoTFTLN(AC_msg_paused);
+ break;
+
+ case AC_timer_stopped:
+ if (printer_state != AC_printer_idle) {
+ if (printer_state == AC_printer_stopping_from_media_remove) {
+ ChangePageOfTFT(PAGE_NO_SD);
+ }
+ else {
+ printer_state = AC_printer_stopping;
+
+ // Get Printing Time
+ uint32_t time = getProgress_seconds_elapsed() / 60;
+ char str_buf[20];
+ sprintf(str_buf, "%s H ", utostr3(time / 60));
+ sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60));
+ SendTxtToTFT(str_buf, TXT_FINISH_TIME);
+ ChangePageOfTFT(PAGE_PRINT_FINISH);
+ SendtoTFTLN(AC_msg_print_complete);
+ pop_up_index = 100;
+ }
+ }
+ setSoftEndstopState(true); // enable endstops
+ break;
+ }
+ }
+
+ #if ENABLED(FILAMENT_RUNOUT_SENSOR)
+
+ void DgusTFT::FilamentRunout() {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_PRINT_PRINTER_STATE(F("FilamentRunout() printer_state "), printer_state);
+
+ // 1 Signal filament out
+ SendtoTFTLN(isPrintingFromMedia() ? AC_msg_filament_out_alert : AC_msg_filament_out_block);
+ //printer_state = AC_printer_filament_out;
+
+ DEBUG_ECHOLNPGM("getFilamentRunoutState: ", getFilamentRunoutState());
+ #endif
+
+ pop_up_index = 15; // show filament lack.
+
+ if (READ(FIL_RUNOUT_PIN) == FIL_RUNOUT_STATE) {
+ PlayTune(BEEPER_PIN, FilamentOut, 1);
+
+ feedrate_back = getFeedrate_percent();
+
+ if (isPrintingFromMedia()) {
+ pausePrint();
+ printer_state = AC_printer_pausing;
+ pause_state = AC_paused_filament_lack;
+ }
+ }
+ }
+
+ #endif // FILAMENT_RUNOUT_SENSOR
+
+ void DgusTFT::ConfirmationRequest(const char * const msg) {
+ // M108 continue
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("HomingComplete, line: ", __LINE__);
+ DEBUG_ECHOLNPGM("ConfirmationRequest() ", msg);
+ DEBUG_PRINT_PRINTER_STATE(F("printer_state: " ), printer_state);
+ DEBUG_PRINT_PAUSED_STATE(F("pause_state: "), pause_state);
+ #endif
+
+ switch (printer_state) {
+ case AC_printer_pausing: {
+ if (strcmp_P(msg, MARLIN_msg_print_paused) == 0 || strcmp_P(msg, MARLIN_msg_nozzle_parked) == 0) {
+ if (pause_state != AC_paused_filament_lack)
+ ChangePageOfTFT(PAGE_STATUS1); // enable continue button
+ printer_state = AC_printer_paused;
+ }
+ }
+ break;
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ case AC_printer_resuming_from_power_outage:
+ #endif
+ case AC_printer_printing:
+ case AC_printer_paused:
+ // Heater timout, send acknowledgement
+ if (strcmp_P(msg, MARLIN_msg_heater_timeout) == 0) {
+ pause_state = AC_paused_heater_timed_out;
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ PlayTune(BEEPER_PIN, Heater_Timedout, 1);
+ }
+ // Reheat finished, send acknowledgement
+ else if (strcmp_P(msg, MARLIN_msg_reheat_done) == 0) {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("send M108 ", __LINE__);
+ #endif
+ injectCommands(F("M108"));
+
+ if (pause_state != AC_paused_filament_lack)
+ pause_state = AC_paused_idle;
+
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ }
+ // Filament Purging, send acknowledgement enter run mode
+ else if (strcmp_P(msg, MARLIN_msg_filament_purging) == 0) {
+ pause_state = AC_paused_purging_filament;
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ }
+ else if (strcmp_P(msg, MARLIN_msg_nozzle_parked) == 0) {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("send M108 ", __LINE__);
+ #endif
+ injectCommands(F("M108"));
+
+ if (pause_state != AC_paused_filament_lack)
+ pause_state = AC_paused_idle;
+ }
+
+ break;
+
+ default: break;
+ }
+ }
+
+ void DgusTFT::StatusChange(const char * const msg) {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("StatusChange() ", msg);
+ DEBUG_PRINT_PRINTER_STATE(F("printer_state: "), printer_state);
+ DEBUG_PRINT_PAUSED_STATE(F("pause_state: "), pause_state);
+ #endif
+ bool msg_matched = false;
+
+ #if HAS_LEVELING
+ static uint8_t probe_cnt = 0;
+ #endif
+
+ // The only way to get printer status is to parse messages
+ // Use the state to minimise the work we do here.
+ switch (printer_state) {
+ #if HAS_LEVELING
+ case AC_printer_probing:
+
+ if (strncmp_P(msg, MARLIN_msg_probing_point, strlen_P(MARLIN_msg_probing_point)) == 0)
+ probe_cnt++;
+
+ // If probing completes ok save the mesh and park
+ // Ignore the custom machine name
+ if (strcmp_P(msg + strlen(MACHINE_NAME), MARLIN_msg_ready) == 0) {
+ if (probe_cnt == GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y) {
+ probe_cnt = 0;
+ injectCommands(F("M500")); // G27 park nozzle
+ //ChangePageOfTFT(PAGE_PreLEVEL);
+ FakeChangePageOfTFT(PAGE_PreLEVEL); // Prevent UI refreshing too quickly when probing is done
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ }
+
+ // If probing fails don't save the mesh raise the probe above the bad point
+ if (strcmp_P(msg, MARLIN_msg_probing_failed) == 0) {
+ PlayTune(BEEPER_PIN, BeepBeepBeeep, 1);
+ injectCommands(F("G1 Z50 F500"));
+ ChangePageOfTFT(PAGE_CHS_ABNORMAL_LEVELING_SENSOR);
+ SendtoTFTLN(AC_msg_probing_complete);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+
+ if (strcmp_P(msg, MARLIN_msg_probe_preheat_start) == 0)
+ ChangePageOfTFT(PAGE_CHS_PROBE_PREHEATING);
+
+ if (strcmp_P(msg, MARLIN_msg_probe_preheat_stop) == 0)
+ ChangePageOfTFT(PAGE_LEVELING);
+
+ break;
+ #endif
+
+ case AC_printer_printing:
+ if (strcmp_P(msg, MARLIN_msg_reheating) == 0) {
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ ChangePageOfTFT(PAGE_STATUS2);
+ msg_matched = true;
+ }
+ else if (strcmp_P(msg, MARLIN_msg_media_removed) == 0) {
+ msg_matched = true;
+ printer_state = AC_printer_stopping_from_media_remove;
+ }
+ else {
+ #if ENABLED(FILAMENT_RUNOUT_SENSOR)
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("setFilamentRunoutState: ", __LINE__);
+ #endif
+ setFilamentRunoutState(false);
+ #endif
+ }
+ break;
+
+ case AC_printer_pausing:
+ if (strcmp_P(msg, MARLIN_msg_print_paused) == 0) {
+ if (pause_state != AC_paused_filament_lack) {
+ ChangePageOfTFT(PAGE_STATUS1); // show resume
+ pause_state = AC_paused_idle;
+ }
+
+ printer_state = AC_printer_paused;
+ msg_matched = true;
+ }
+ break;
+
+ case AC_printer_paused:
+ if (strcmp_P(msg, MARLIN_msg_print_paused) == 0) {
+ if (pause_state != AC_paused_filament_lack) {
+ ChangePageOfTFT(PAGE_STATUS1); // show resume
+ pause_state = AC_paused_idle;
+ }
+
+ printer_state = AC_printer_paused;
+ msg_matched = true;
+ }
+ break;
+
+ case AC_printer_stopping:
+ if (strcmp_P(msg, MARLIN_msg_print_aborted) == 0) {
+ ChangePageOfTFT(PAGE_MAIN);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ break;
+
+ default: break;
+ }
+
+ // If not matched earlier see if this was a heater message
+ if (!msg_matched) {
+ #if HAS_HOTEND
+ if (strcmp_P(msg, MARLIN_msg_extruder_heating) == 0) {
+ SendtoTFTLN(AC_msg_nozzle_heating);
+ hotend_state = AC_heater_temp_set;
+ return;
+ }
+ #endif
+ #if HAS_HEATED_BED
+ if (strcmp_P(msg, MARLIN_msg_bed_heating) == 0) {
+ SendtoTFTLN(AC_msg_bed_heating);
+ hotbed_state = AC_heater_temp_set;
+ }
+ #endif
+ }
+ }
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+
+ void DgusTFT::PowerLoss() {
+ // On: 5A A5 05 82 00 82 00 00
+ // Off: 5A A5 05 82 00 82 00 64
+ uint8_t data[] = { 0x5A, 0xA5, 0x05, 0x82, 0x00, 0x82, 0x00, uint8_t(recovery.enabled ? 0x00 : 0x64) };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ }
+
+ void DgusTFT::PowerLossRecovery() {
+ printer_state = AC_printer_resuming_from_power_outage; // Play tune to notify user we can recover.
+ }
+
+ #endif // POWER_LOSS_RECOVERY
+
+ void DgusTFT::HomingStart() {
+ if (!isPrintingFromMedia())
+ ChangePageOfTFT(PAGE_CHS_HOMING);
+ }
+
+ void DgusTFT::HomingComplete() {
+ if (lcd_info.language == ENG && page_index_last > 120)
+ page_index_last -= 120;
+
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("HomingComplete, line: ", __LINE__);
+ DEBUG_ECHOLNPGM("page_index_last: ", page_index_last);
+ #endif
+
+ if (!isPrintingFromMedia())
+ ChangePageOfTFT(page_index_last);
+ }
+
+ void DgusTFT::SendtoTFT(FSTR_P const fstr/*=nullptr*/) { // A helper to print PROGMEM string to the panel
+ #if ACDEBUG(AC_SOME)
+ DEBUG_ECHOF(fstr);
+ #endif
+ PGM_P str = FTOP(fstr);
+ while (const char c = pgm_read_byte(str++)) TFTSer.write(c);
+ }
+
+ void DgusTFT::SendtoTFTLN(FSTR_P const fstr/*=nullptr*/) {
+ if (fstr) {
+ #if ACDEBUG(AC_SOME)
+ DEBUG_ECHOPGM("> ");
+ #endif
+ SendtoTFT(fstr);
+ #if ACDEBUG(AC_SOME)
+ SERIAL_EOL();
+ #endif
+ }
+ TFTSer.println();
+ }
+
+ void DgusTFT::SendValueToTFT(const uint16_t value, const uint16_t address) {
+ uint8_t data[] = { 0x5A, 0xA5, 0x05, 0x82, uint8_t(address >> 8), uint8_t(address & 0xFF), uint8_t(value >> 8), uint8_t(value & 0xFF) };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ }
+
+ void DgusTFT::RequestValueFromTFT(const uint16_t address) {
+ uint8_t data[] = { 0x5A, 0xA5, 0x04, 0x83, uint8_t(address >> 8), uint8_t(address & 0xFF), 0x01 };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ }
+
+ void DgusTFT::SendTxtToTFT(const char *pdata, const uint16_t address) {
+ uint8_t data_len = strlen(pdata);
+ uint8_t data[] = { 0x5A, 0xA5, uint8_t(data_len + 5), 0x82, uint8_t(address >> 8), uint8_t(address & 0xFF) };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ LOOP_L_N(i, data_len) TFTSer.write(pdata[i]);
+ TFTSer.write(0xFF); TFTSer.write(0xFF);
+ }
+
+ void DgusTFT::SendColorToTFT(const uint16_t color, const uint16_t address) {
+ uint8_t data[] = { 0x5A, 0xA5, 0x05, 0x82, uint8_t(address >> 8), uint8_t(address & 0xFF), uint8_t(color >> 8), uint8_t(color & 0xFF) };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ }
+
+ void DgusTFT::SendReadNumOfTxtToTFT(const uint8_t number, const uint16_t address) {
+ uint8_t data[] = { 0x5A, 0xA5, 0x04, 0x83, uint8_t(address >> 8), uint8_t(address & 0xFF), number };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ }
+
+ void DgusTFT::ChangePageOfTFT(const uint16_t page_index, const bool no_send/*=false*/) {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("ChangePageOfTFT: ", page_index);
+ #endif
+
+ uint32_t data_temp = 0;
+
+ if (lcd_info.language == CHS) {
+ data_temp = page_index;
+ }
+ else if (lcd_info.language == ENG) {
+ switch (page_index) {
+ case PAGE_OUTAGE_RECOVERY:
+ data_temp = PAGE_ENG_OUTAGE_RECOVERY; break;
+ case PAGE_CHS_PROBE_PREHEATING:
+ data_temp = PAGE_ENG_PROBE_PREHEATING; break;
+ case PAGE_CHS_HOMING ... PAGE_ENG_HOMING:
+ data_temp = page_index + 12; break;
+ case PAGE_CHS_PROBE_PRECHECK ... PAGE_CHS_PROBE_PRECHECK_FAILED:
+ data_temp = page_index + 3; break;
+ default:
+ data_temp = page_index + 120; break;
+ }
+ }
+
+ if (!no_send) {
+ uint8_t data[] = { 0x5A, 0xA5, 0x07, 0x82, 0x00, 0x84, 0x5A, 0x01, uint8_t(data_temp >> 8), uint8_t(data_temp & 0xFF) };
+ LOOP_L_N(i, COUNT(data)) TFTSer.write(data[i]);
+ }
+
+ page_index_last_2 = page_index_last;
+ page_index_last = page_index_now;
+ page_index_now = data_temp;
+
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("page_index_last_2: ", page_index_last_2);
+ DEBUG_ECHOLNPGM("page_index_last: ", page_index_last);
+ DEBUG_ECHOLNPGM("page_index_now: ", page_index_now);
+ #endif
+ }
+
+ void DgusTFT::FakeChangePageOfTFT(const uint16_t page_index) {
+ #if ACDEBUG(AC_MARLIN)
+ if (page_index_saved != page_index_now)
+ DEBUG_ECHOLNPGM("FakeChangePageOfTFT: ", page_index);
+ #endif
+ ChangePageOfTFT(page_index, true);
+ }
+
+ void DgusTFT::LcdAudioSet(const bool audio_on) {
+ // On: 5A A5 07 82 00 80 5A 00 00 1A
+ // Off: 5A A5 07 82 00 80 5A 00 00 12
+ uint8_t data[] = { 0x5A, 0xA5, 0x07, 0x82, 0x00, 0x80, 0x5A, 0x00, 0x00, uint8_t(audio_on ? 0x1A : 0x12) };
+ LOOP_L_N(i, 10) TFTSer.write(data[i]);
+ }
+
+ bool DgusTFT::ReadTFTCommand() {
+ static uint8_t length = 0, cnt = 0, tft_receive_steps = 0;
+ uint8_t data;
+
+ if (0 == TFTSer.available() || data_received) return false;
+
+ data = TFTSer.read();
+
+ if (tft_receive_steps == 0) {
+ if (data != 0x5A) {
+ cnt = 0;
+ length = 0;
+ data_index = 0;
+ data_received = false;
+ return false;
+ }
+
+ while (!TFTSer.available()) TERN_(USE_WATCHDOG, hal.watchdog_refresh());
+
+ data = TFTSer.read();
+ // MYSERIAL.write(data );
+ if (data == 0xA5) tft_receive_steps = 2;
+ }
+ else if (tft_receive_steps == 2) {
+ length = data;
+ tft_receive_steps = 3;
+ data_index = 0;
+ cnt = 0;
+ }
+ else if (tft_receive_steps == 3) {
+ if (data_index >= (DATA_BUF_SIZE -1)) {
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("lcd uart buff overflow: ", data_index);
+ #endif
+ data_index = 0;
+ data_received = false;
+ return false;
+ }
+ data_buf[data_index++] = data;
+ cnt++;
+ if (cnt >= length) { // Receive complete
+ tft_receive_steps = 0;
+ cnt = 0;
+ data_index = 0;
+ data_received = true;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ #if 0
+ {
+ //SERIAL_ECHOLNPGM("ReadTFTCommand: ", millis());
+ //return -1;
+
+ bool command_ready = false;
+ uint8_t data = 0;
+
+ while (TFTSer.available() > 0 && command_len < MAX_CMND_LEN) {
+ data = TFTSer.read();
+ if (0 == command_len) {
+ // if
+ }
+
+ panel_command[command_len] =
+ if (panel_command[command_len] == '\n') {
+ command_ready = true;
+ break;
+ }
+ command_len++;
+ }
+
+ if (command_ready) {
+ panel_command[command_len] = 0x00;
+ #if ACDEBUG(AC_ALL)
+ DEBUG_ECHOLNPGM("< panel_command ", panel_command);
+ #endif
+ #if ACDEBUG(AC_SOME)
+ // Ignore status request commands
+ uint8_t req = atoi(&panel_command[1]);
+ if (req > 7 && req != 20) {
+ DEBUG_ECHOLNPGM("> ", panel_command);
+ DEBUG_PRINT_PRINTER_STATE(F("printer_state: "), printer_state);
+ }
+ #endif
+ }
+ return command_ready;
+ }
+ #endif
+
+ int8_t DgusTFT::Findcmndpos(const char * buff, const char q) {
+ for (int8_t pos = 0; pos < MAX_CMND_LEN; ++pos)
+ if (buff[pos] == q) return pos;
+ return -1;
+ }
+
+ void DgusTFT::CheckHeaters() {
+ static uint32_t time_last = 0;
+ if (PENDING(millis(), time_last)) return;
+ time_last = millis() + 500;
+
+ float temp = 0;
+
+ #if HAS_HOTEND
+ // If the hotend temp is abnormal, confirm state before signalling panel
+ static uint8_t faultE0Duration = 0;
+ temp = getActualTemp_celsius(E0);
+ if (!WITHIN(temp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP)) {
+ faultE0Duration++;
+ if (faultE0Duration >= AC_HEATER_FAULT_VALIDATION_TIME) {
+ SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("Extruder temp abnormal! : ", temp);
+ #endif
+ faultE0Duration = 0;
+ }
+ }
+ #endif
+
+ #if HAS_HEATED_BED
+ static uint8_t faultBedDuration = 0;
+ temp = getActualTemp_celsius(BED);
+ if (!WITHIN(temp, BED_MINTEMP, BED_MAXTEMP)) {
+ faultBedDuration++;
+ if (faultBedDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
+ SendtoTFTLN(AC_msg_bed_temp_abnormal);
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("Bed temp abnormal! : ", temp);
+ #endif
+ faultBedDuration = 0;
+ }
+ }
+ #endif
+
+ #if 0
+ // Update panel with hotend heater status
+ if (hotend_state != AC_heater_temp_reached) {
+ if (WITHIN(getActualTemp_celsius(E0) - getTargetTemp_celsius(E0), -1, 1)) {
+ SendtoTFTLN(AC_msg_nozzle_heating_done);
+ hotend_state = AC_heater_temp_reached;
+ }
+ }
+
+ // Update panel with bed heater status
+ if (hotbed_state != AC_heater_temp_reached) {
+ if (WITHIN(getActualTemp_celsius(BED) - getTargetTemp_celsius(BED), -0.5, 0.5)) {
+ SendtoTFTLN(AC_msg_bed_heating_done);
+ hotbed_state = AC_heater_temp_reached;
+ }
+ }
+ #endif
+ }
+
+ void DgusTFT::SendFileList(int8_t startindex) {
+ // Respond to panel request for 4 files starting at index
+ #if ACDEBUG(AC_INFO)
+ DEBUG_ECHOLNPGM("## SendFileList ## ", startindex);
+ #endif
+ filenavigator.getFiles(startindex);
+ }
+
+ void DgusTFT::SelectFile() {
+ strncpy(selectedfile, panel_command + 4, command_len - 4);
+ selectedfile[command_len - 5] = '\0';
+ #if ACDEBUG(AC_FILE)
+ DEBUG_ECHOLNPGM(" Selected File: ", selectedfile);
+ #endif
+ switch (selectedfile[0]) {
+ case '/': // Valid file selected
+ SendtoTFTLN(AC_msg_sd_file_open_success);
+ break;
+ case '<': // .. (go up folder level)
+ filenavigator.upDIR();
+ SendtoTFTLN(AC_msg_sd_file_open_failed);
+ SendFileList(0);
+ break;
+ default: // enter sub folder
+ filenavigator.changeDIR(selectedfile);
+ SendtoTFTLN(AC_msg_sd_file_open_failed);
+ SendFileList(0);
+ break;
+ }
+ }
+
+ void DgusTFT::ProcessPanelRequest() {
+ uint16_t control_index = 0;
+ uint32_t control_value;
+ uint16_t temp;
+ char str_buf[20];
+
+ if (data_received) {
+ data_received = false;
+
+ if (0x83 == data_buf[0]) {
+ control_index = uint16_t(data_buf[1] << 8) | uint16_t(data_buf[2]);
+ if (control_index == KEY_ADDRESS) { // is KEY
+ //key_index = control_index;
+ key_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]);
+ }
+
+ #if HAS_HOTEND
+ else if (control_index == TXT_HOTEND_TARGET || control_index == TXT_ADJUST_HOTEND) { // hotend target temp
+ control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]);
+ temp = constrain(uint16_t(control_value), 0, HEATER_0_MAXTEMP);
+ setTargetTemp_celsius(temp, E0);
+ //sprintf(str_buf,"%u/%u", (uint16_t)thermalManager.degHotend(0), uint16_t(control_value));
+ //SendTxtToTFT(str_buf, TXT_PRINT_HOTEND);
+ }
+ #endif
+
+ #if HAS_HEATED_BED
+ else if (control_index == TXT_BED_TARGET || control_index == TXT_ADJUST_BED) {// bed target temp
+ control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]);
+ temp = constrain(uint16_t(control_value), 0, BED_MAXTEMP);
+ setTargetTemp_celsius(temp, BED);
+ //sprintf(str_buf,"%u/%u", uint16_t(thermalManager.degBed()), uint16_t(control_value));
+ //SendTxtToTFT(str_buf, TXT_PRINT_BED);
+ }
+ #endif
+
+ #if HAS_FAN
+ else if (control_index == TXT_FAN_SPEED_TARGET) { // fan speed
+ control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]);
+ temp = constrain(uint16_t(control_value), 0, 100);
+ SendValueToTFT(temp, TXT_FAN_SPEED_NOW);
+ SendValueToTFT(temp, TXT_FAN_SPEED_TARGET);
+ setTargetFan_percent(temp, FAN0);
+ }
+ #endif
+
+ else if (control_index == TXT_PRINT_SPEED_TARGET || control_index == TXT_ADJUST_SPEED) { // print speed
+ control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]);
+ const uint16_t feedrate = constrain(uint16_t(control_value), 40, 999);
+ //feedrate_percentage=constrain(control_value,40,999);
+ sprintf(str_buf, "%u", feedrate);
+ SendTxtToTFT(str_buf, TXT_PRINT_SPEED);
+ SendValueToTFT(feedrate, TXT_PRINT_SPEED_NOW);
+ SendValueToTFT(feedrate, TXT_PRINT_SPEED_TARGET);
+ setFeedrate_percent(feedrate);
+ }
+
+ else if (control_index == REG_LCD_READY) {
+ control_value = (uint32_t(data_buf[3]) << 16) | (uint32_t(data_buf[4]) << 8) | uint32_t(data_buf[5]);
+ if (control_value == 0x010072) { // startup last gif
+ LcdAudioSet(lcd_info.audio_on);
+
+ SendValueToTFT(2, ADDRESS_MOVE_DISTANCE);
+
+ #if ENABLED(CASE_LIGHT_ENABLE)
+ SendValueToTFT(getCaseLightState(), ADDRESS_SYSTEM_LED_STATUS);
+ SendValueToTFT(getCaseLightState(), ADDRESS_PRINT_SETTING_LED_STATUS);
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ const bool is_outage = AC_printer_resuming_from_power_outage == printer_state;
+ if (is_outage) {
+ ChangePageOfTFT(PAGE_OUTAGE_RECOVERY);
+ #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+ char filename[64] = { '\0' };
+ card.getLongPath(filename, recovery.info.sd_filename);
+ SendTxtToTFT(filename, TXT_OUTAGE_RECOVERY_FILE);
+ #else
+ SendTxtToTFT(recovery.info.sd_filename, TXT_OUTAGE_RECOVERY_FILE);
+ #endif
+ PlayTune(BEEPER_PIN, SOS, 1);
+ }
+ #else
+ constexpr bool is_outage = false;
+ #endif
+
+ if (!is_outage) ChangePageOfTFT(PAGE_MAIN);
+
+ }
+ else if (control_value == 0x010000) { // startup first gif
+ PlayTune(BEEPER_PIN, Anycubic_PowerOn, 1); // takes 3500 ms
+ }
+ }
+
+ /*
+ else if ((control_index & 0xF000) == 0x2000) { // is TXT ADDRESS
+ tft_txt_index = control_index;
+ j = 0;
+ for (i = 4; ;i++) {
+ tft_txt_buf[j] = data_buf[i];
+ if (tft_txt_buf[j] == 0xFF) {
+ tft_txt_buf[j] = 0;
+ break;
+ }
+ j++;
+ }
+ }
+ */
+ }
+ else if (data_buf[0] == 0x82) {
+ // send_cmd_to_pc(cmd ,start );
+ }
+ }
+ }
+
+ #if 0
+ {
+ // Break these up into logical blocks // as its easier to navigate than one huge switch case!
+ int8_t req = atoi(&panel_command[1]);
+
+ // Information requests A0 - A8 and A33
+ if (req <= 8 || req == 33) PanelInfo(req);
+
+ // Simple Actions A9 - A28
+ else if (req <= 28) PanelAction(req);
+
+ // Process Initiation
+ else if (req <= 34) PanelProcess(req);
+
+ else SendtoTFTLN();
+ }
+ #endif
+
+ void DgusTFT::set_language(language_t language) {
+ lcd_info.language = ui_language = lcd_info_back.language = language;
+ }
+
+ void DgusTFT::toggle_language() {
+ lcd_info.language = ui_language = (lcd_info.language == CHS ? ENG : CHS);
+ }
+
+ void DgusTFT::goto_system_page() {
+ ChangePageOfTFT(lcd_info.language == CHS
+ ? (lcd_info.audio_on ? PAGE_SYSTEM_CHS_AUDIO_ON : PAGE_SYSTEM_CHS_AUDIO_OFF)
+ : (lcd_info.audio_on ? 11 : 50) // PAGE_SYSTEM_ENG_AUDIO_ON/OFF - 120
+ );
+ }
+
+ void DgusTFT::toggle_audio() {
+ lcd_info.audio_on = !lcd_info.audio_on;
+ goto_system_page();
+ LcdAudioSet(lcd_info.audio_on);
+ }
+
+ void DgusTFT::store_changes() {
+ if (lcd_info_back.language != lcd_info.language || lcd_info_back.audio_on != lcd_info.audio_on) {
+ lcd_info_back = lcd_info;
+ injectCommands(F("M500"));
+ }
+ }
+
+ #if HAS_HOTEND
+ void DgusTFT::send_temperature_hotend(uint32_t addr) {
+ char str_buf[16];
+ sprintf(str_buf, "%u/%u", uint16_t(getActualTemp_celsius(E0)), uint16_t(getTargetTemp_celsius(E0)));
+ SendTxtToTFT(str_buf, addr);
+ }
+ #endif
+
+ #if HAS_HEATED_BED
+ void DgusTFT::send_temperature_bed(uint32_t addr) {
+ char str_buf[16];
+ sprintf(str_buf, "%u/%u", uint16_t(getActualTemp_celsius(BED)), uint16_t(getTargetTemp_celsius(BED)));
+ SendTxtToTFT(str_buf, addr);
+ }
+ #endif
+
+ void DgusTFT::page1() {
+ #if ACDEBUG(AC_ALL)
+ if (page_index_saved != page_index_now || key_value_saved != key_value) {
+ DEBUG_ECHOLNPGM("page1 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: { // main page, print
+ lcd_txtbox_page = 0;
+ if (lcd_txtbox_index) {
+ set_descript_color(COLOR_BLUE);
+ lcd_txtbox_index = 0;
+ }
+ ChangePageOfTFT(PAGE_FILE);
+ SendFileList(0);
+ } break;
+
+ case 2: { // tool
+ ChangePageOfTFT(PAGE_TOOL);
+ #if ENABLED(CASE_LIGHT_ENABLE)
+ SendValueToTFT(getCaseLightState(), ADDRESS_SYSTEM_LED_STATUS);
+ #endif
+ } break;
+
+ case 3: // prepare
+ ChangePageOfTFT(PAGE_PREPARE);
+ break;
+
+ case 4: // system
+ goto_system_page();
+ break;
+ }
+
+ #if 0
+ if (message_index < 30) {
+ SendTxtToTFT(p_mesage[message_index], TXT_MAIN_MESSAGE);
+ message_index = 30;
+ }
+ #endif
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PREHEAT_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PREHEAT_BED));
+ #endif
+ }
+
+ void DgusTFT::page2() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page2 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ char file_index = 0;
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_MAIN);
+ set_descript_color(COLOR_BLUE);
+ break;
+
+ case 2: // page up
+ if (lcd_txtbox_page > 0) {
+ lcd_txtbox_page--;
+
+ set_descript_color(COLOR_BLUE);
+ lcd_txtbox_index = 0;
+
+ SendFileList(lcd_txtbox_page * 5);
+ }
+ break;
+
+ case 3: // page down
+ if ((lcd_txtbox_page + 1) * 5 < filenavigator.getFileNum()) {
+ lcd_txtbox_page++;
+
+ set_descript_color(COLOR_BLUE);
+ lcd_txtbox_index = 0;
+
+ SendFileList(lcd_txtbox_page * 5);
+ }
+ break;
+
+ case 4: // page refresh
+ if (!isMediaInserted()) safe_delay(500);
+
+ filenavigator.reset();
+
+ lcd_txtbox_page = 0;
+ if (lcd_txtbox_index) {
+ set_descript_color(COLOR_BLUE);
+ lcd_txtbox_index = 0;
+ }
+ SendFileList(lcd_txtbox_index);
+ break;
+
+ case 5: // resume of outage(last power off)
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_PRINT_PRINTER_STATE(F("printer_state: "), printer_state);
+ #endif
+ if (lcd_txtbox_index > 0 && lcd_txtbox_index < 6) { // 1~5
+
+ if (filenavigator.filelist.seek(lcd_txtbox_page * 5 + (lcd_txtbox_index - 1))) {
+
+ set_descript_color(COLOR_BLUE);
+
+ TERN_(CASE_LIGHT_ENABLE, setCaseLightState(true));
+
+ char str_buf[20];
+ strncpy_P(str_buf, filenavigator.filelist.longFilename(), 17);
+ str_buf[17] = '\0';
+ SendTxtToTFT(str_buf, TXT_PRINT_NAME);
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ if (printer_state == AC_printer_resuming_from_power_outage) {
+ // Need to home here to restore the Z position
+ //injectCommands_P(AC_cmnd_power_loss_recovery);
+ //SERIAL_ECHOLNPGM("start resuming from power outage: ", AC_cmnd_power_loss_recovery);
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ injectCommands(F("M1000")); // home and start recovery
+ }
+ #endif
+ }
+ }
+ break;
+
+ case 6: // start print
+ if (lcd_txtbox_index > 0 && lcd_txtbox_index < 6) { // 1~5
+
+ if (filenavigator.filelist.seek(lcd_txtbox_page * 5 + lcd_txtbox_index - 1)) {
+ #if 0
+ SERIAL_ECHOLNPGM("start print: ", lcd_txtbox_page * 5 + (lcd_txtbox_index - 1));
+ SERIAL_ECHOLNPGM("start print: ", filenavigator.filelist.shortFilename());
+ SERIAL_ECHOLNPGM("start print: ", filenavigator.filelist.longFilename());
+ #endif
+
+ set_descript_color(COLOR_BLUE);
+
+ // Allows printer to restart the job if we don't want to recover
+ if (printer_state == AC_printer_resuming_from_power_outage) {
+ injectCommands(F("M1000 C")); // Cancel recovery
+ printer_state = AC_printer_idle;
+ }
+
+ TERN_(CASE_LIGHT_ENABLE, setCaseLightState(true));
+ printFile(filenavigator.filelist.shortFilename());
+
+ char str_buf[20];
+ strncpy_P(str_buf, filenavigator.filelist.longFilename(), 17);
+ str_buf[17] = '\0';
+ SendTxtToTFT(str_buf, TXT_PRINT_NAME);
+
+ sprintf(str_buf, "%5.2f", getFeedrate_percent());
+ SendTxtToTFT(str_buf, TXT_PRINT_SPEED);
+
+ sprintf(str_buf, "%u", uint16_t(getProgress_percent()));
+ SendTxtToTFT(str_buf, TXT_PRINT_PROGRESS);
+
+ uint32_t time = 0;
+ sprintf(str_buf, "%s H ", utostr3(time / 60));
+ sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60));
+ SendTxtToTFT(str_buf, TXT_PRINT_TIME);
+
+ ChangePageOfTFT(PAGE_STATUS2);
+ }
+ }
+ break;
+
+ case 7: // txtbox 1 click
+ case 8: // txtbox 2 click
+ case 9: // txtbox 3 click
+ case 10: // txtbox 4 click
+
+ case 11: { // txtbox 5 click
+ static uint8_t lcd_txtbox_index_last = 0;
+
+ lcd_txtbox_index = key_value - 6;
+
+ // lcd_txtbox_page 0~...
+ // lcd_txtbox_index 1~5
+ file_index = lcd_txtbox_page * 5 + (lcd_txtbox_index - 1);
+ if (file_index < filenavigator.getFileNum()) {
+
+ set_descript_color(COLOR_RED);
+
+ if (lcd_txtbox_index_last && lcd_txtbox_index_last != lcd_txtbox_index) // 1~5
+ set_descript_color(COLOR_BLUE, lcd_txtbox_index_last);
+ lcd_txtbox_index_last = lcd_txtbox_index;
+ }
+ } break;
+ }
+ }
+
+ void DgusTFT::page3() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page3 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ char str_buf[20];
+ static uint8_t progress_last = 0;
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ if (!isPrintingFromMedia()) // only idle status can return
+ ChangePageOfTFT(PAGE_FILE);
+ break;
+
+ case 2: // resume print
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_PRINT_PRINTER_STATE(F("printer_state: "), printer_state);
+ DEBUG_PRINT_PAUSED_STATE(F("pause_state :"), pause_state);
+ #endif
+ if ( pause_state == AC_paused_idle
+ || pause_state == AC_paused_filament_lack
+ || printer_state == AC_printer_resuming_from_power_outage
+ ) {
+ printer_state = AC_printer_idle;
+ pause_state = AC_paused_idle;
+ resumePrint();
+ ChangePageOfTFT(PAGE_STATUS2); // show pause print
+ flash_time = ms + 1500;
+ }
+ else
+ setUserConfirmed();
+ break;
+
+ case 3: // print stop
+ if (isPrintingFromMedia())
+ ChangePageOfTFT(PAGE_STOP_CONF);
+ break;
+
+ case 4: // print change param
+ ChangePageOfTFT(PAGE_ADJUST);
+ TERN_(CASE_LIGHT_ENABLE, SendValueToTFT(getCaseLightState(), ADDRESS_PRINT_SETTING_LED_STATUS));
+ TERN_(HAS_HOTEND, SendValueToTFT(uint16_t(getTargetTemp_celsius(E0)), TXT_ADJUST_HOTEND));
+ TERN_(HAS_HEATED_BED, SendValueToTFT(uint16_t(getTargetTemp_celsius(BED)), TXT_ADJUST_BED));
+ feedrate_back = getFeedrate_percent();
+ SendValueToTFT(uint16_t(feedrate_back), TXT_ADJUST_SPEED);
+ flash_time = ms + 1500;
+ break;
+ }
+
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ if (feedrate_back != getFeedrate_percent()) {
+ if (getFeedrate_percent() != 0)
+ sprintf(str_buf, "%5.2f", getFeedrate_percent());
+ else
+ sprintf(str_buf, "%d", feedrate_back);
+
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("print speed: ", str_buf);
+ DEBUG_ECHOLNPGM("feedrate_back: ", feedrate_back);
+ #endif
+ SendTxtToTFT(str_buf, TXT_PRINT_SPEED);
+ feedrate_back = getFeedrate_percent();
+ }
+
+ if (progress_last != getProgress_percent()) {
+ sprintf(str_buf, "%u", getProgress_percent());
+ SendTxtToTFT(str_buf, TXT_PRINT_PROGRESS);
+ progress_last = getProgress_percent();
+ }
+
+ // Get Printing Time
+ uint32_t time = getProgress_seconds_elapsed() / 60;
+ sprintf(str_buf, "%s H ", utostr3(time / 60));
+ sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60));
+ SendTxtToTFT(str_buf, TXT_PRINT_TIME);
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PRINT_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PRINT_BED));
+ }
+
+ void DgusTFT::page4() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page4 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ char str_buf[20];
+ static uint8_t progress_last = 0;
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ if (!isPrintingFromMedia()) // only is idle status can return
+ ChangePageOfTFT(PAGE_FILE);
+ break;
+
+ case 2: // print pause
+ if (isPrintingFromMedia()) {
+ pausePrint();
+ printer_state = AC_printer_pausing;
+ pause_state = AC_paused_idle;
+ ChangePageOfTFT(PAGE_WAIT_PAUSE);
+ //injectCommands(F("M108")); // stop waiting temperature M109
+ }
+ break;
+
+ case 3: // print stop
+ if (isPrintingFromMedia())
+ ChangePageOfTFT(PAGE_STOP_CONF);
+ break;
+
+ case 4: // print settings
+ ChangePageOfTFT(PAGE_ADJUST);
+ TERN_(CASE_LIGHT_ENABLE, SendValueToTFT(getCaseLightState(), ADDRESS_PRINT_SETTING_LED_STATUS));
+ TERN_(HAS_HOTEND, SendValueToTFT(uint16_t(getTargetTemp_celsius(E0)), TXT_ADJUST_HOTEND));
+ TERN_(HAS_HEATED_BED, SendValueToTFT(uint16_t(getTargetTemp_celsius(BED)), TXT_ADJUST_BED));
+ feedrate_back = getFeedrate_percent();
+ SendValueToTFT((uint16_t)feedrate_back, TXT_ADJUST_SPEED);
+ TERN_(HAS_FAN, SendValueToTFT(uint16_t(getActualFan_percent(FAN0)), TXT_FAN_SPEED_TARGET));
+ str_buf[0] = 0;
+ strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 3);
+ SendTxtToTFT(str_buf, TXT_LEVEL_OFFSET);
+ //SendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET);
+ RequestValueFromTFT(TXT_ADJUST_SPEED); // attempt to make feedrate visible on visit to this page
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ if (feedrate_back != getFeedrate_percent()) {
+ if (getFeedrate_percent() != 0)
+ sprintf(str_buf, "%5.2f", getFeedrate_percent());
+ else
+ sprintf(str_buf, "%d", feedrate_back);
+
+ SendTxtToTFT(str_buf, TXT_PRINT_SPEED);
+ feedrate_back = getFeedrate_percent();
+ }
+
+ if (progress_last != getProgress_percent()) {
+ sprintf(str_buf, "%u", getProgress_percent());
+ SendTxtToTFT(str_buf, TXT_PRINT_PROGRESS);
+ progress_last = getProgress_percent();
+ }
+
+ uint32_t time = getProgress_seconds_elapsed() / 60;
+ sprintf(str_buf, "%s H ", utostr3(time / 60));
+ sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60));
+ SendTxtToTFT(str_buf, TXT_PRINT_TIME);
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PRINT_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PRINT_BED));
+ }
+
+ void DgusTFT::page5() { // print settings
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page5 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ static bool z_change = false;
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ if (AC_printer_printing == printer_state)
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ else if (AC_printer_paused == printer_state)
+ ChangePageOfTFT(PAGE_STATUS1); // show print
+ break;
+
+ #if ENABLED(MESH_EDIT_MENU)
+
+ case 2: { // -
+ float z_off = getZOffset_mm();
+ //SERIAL_ECHOLNPGM("z_off: ", z_off);
+ //setSoftEndstopState(false);
+ if (z_off <= -5) return;
+ z_off -= 0.05f;
+ setZOffset_mm(z_off);
+
+ char str_buf[10];
+ str_buf[0] = 0;
+ strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2);
+ SendTxtToTFT(str_buf, TXT_LEVEL_OFFSET);
+ //SendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET);
+
+ //if (isAxisPositionKnown(Z)) { // Move Z axis
+ // SERIAL_ECHOLNPGM("Z now:", getAxisPosition_mm(Z));
+ // const float currZpos = getAxisPosition_mm(Z);
+ // setAxisPosition_mm(currZpos-0.05, Z);
+ // SERIAL_ECHOLNPGM("Z now:", getAxisPosition_mm(Z));
+ //}
+
+ #if ENABLED(BABYSTEPPING)
+ int16_t steps = mmToWholeSteps(-0.05, Z);
+ babystepAxis_steps(steps, Z);
+ #endif
+
+ GRID_LOOP(x, y) {
+ const xy_uint8_t pos { x, y };
+ const float currval = getMeshPoint(pos);
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("x: ", x, " y: ", y, " z: ", currval);
+ #endif
+ setMeshPoint(pos, constrain(currval - 0.05f, AC_LOWEST_MESHPOINT_VAL, 5));
+ }
+
+ z_change = true;
+
+ //setSoftEndstopState(true);
+ } break;
+
+ case 3: { // +
+ float z_off = getZOffset_mm();
+ //SERIAL_ECHOLNPGM("z_off: ", z_off);
+ //setSoftEndstopState(false);
+
+ if (z_off >= 5) return;
+ z_off += 0.05f;
+ setZOffset_mm(z_off);
+
+ char str_buf[10];
+ str_buf[0] = '\0';
+ strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2);
+ SendTxtToTFT(str_buf, TXT_LEVEL_OFFSET);
+ //SendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET);
+
+ //int16_t steps = mmToWholeSteps(constrain(Zshift,-0.05,0.05), Z);
+
+ /*
+ if (isAxisPositionKnown(Z)) { // Move Z axis
+ SERIAL_ECHOLNPGM("Z now:", getAxisPosition_mm(Z));
+ const float currZpos = getAxisPosition_mm(Z);
+ setAxisPosition_mm(currZpos-0.05, Z);
+ SERIAL_ECHOLNPGM("Z now:", getAxisPosition_mm(Z));
+ }
+ */
+
+ #if ENABLED(BABYSTEPPING)
+ int16_t steps = mmToWholeSteps(0.05, Z);
+ babystepAxis_steps(steps, Z);
+ #endif
+
+ GRID_LOOP(x, y) {
+ const xy_uint8_t pos { x, y };
+ const float currval = getMeshPoint(pos);
+ //SERIAL_ECHOLNPGM("x: ", x, " y: ", y, " z: ", currval);
+ setMeshPoint(pos, constrain(currval + 0.05f, AC_LOWEST_MESHPOINT_VAL, 5));
+ }
+
+ z_change = true;
+
+ //setSoftEndstopState(true);
+ } break;
+
+ #endif // MESH_EDIT_MENU
+
+ #if ENABLED(CASE_LIGHT_ENABLE)
+ case 4: { // light control
+ const bool cls = !getCaseLightState();
+ SendValueToTFT(cls, ADDRESS_PRINT_SETTING_LED_STATUS);
+ setCaseLightState(cls);
+ } break;
+ #endif
+
+ case 5:
+ ChangePageOfTFT(PAGE_DONE);
+ break;
+
+ case 6: break;
+
+ case 7:
+ TERN_(HAS_HEATED_BED, RequestValueFromTFT(TXT_ADJUST_BED));
+ RequestValueFromTFT(TXT_ADJUST_SPEED);
+ TERN_(HAS_HOTEND, RequestValueFromTFT(TXT_ADJUST_HOTEND));
+ TERN_(HAS_FAN, RequestValueFromTFT(TXT_FAN_SPEED_TARGET));
+
+ if (z_change == true) {
+ injectCommands(F("M500"));
+ z_change = false;
+ }
+
+ if (AC_printer_printing == printer_state)
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ else if (AC_printer_paused == printer_state)
+ ChangePageOfTFT(PAGE_STATUS1); // show print
+
+ break;
+ }
+ }
+
+ void DgusTFT::page6() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page6 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+ case 1: break;
+ }
+ }
+
+ void DgusTFT::page7() { // tools
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page7 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_MAIN);
+ break;
+
+ case 2:
+ ChangePageOfTFT(PAGE_MOVE);
+ break;
+
+ case 3: // set temperature
+ ChangePageOfTFT(PAGE_TEMP);
+ #if HAS_HOTEND
+ SendValueToTFT(uint16_t(getActualTemp_celsius(E0)), TXT_HOTEND_NOW);
+ SendValueToTFT(uint16_t(getTargetTemp_celsius(E0)), TXT_HOTEND_TARGET);
+ #endif
+ #if HAS_HEATED_BED
+ SendValueToTFT(uint16_t(getActualTemp_celsius(BED)), TXT_BED_NOW);
+ SendValueToTFT(uint16_t(getTargetTemp_celsius(BED)), TXT_BED_TARGET);
+ #endif
+ break;
+
+ case 4:
+ ChangePageOfTFT(PAGE_SPEED);
+ #if HAS_FAN
+ SendValueToTFT(uint16_t(getActualFan_percent(FAN0)), TXT_FAN_SPEED_NOW);
+ SendValueToTFT(uint16_t(getTargetFan_percent(FAN0)), TXT_FAN_SPEED_TARGET);
+ #endif
+ SendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW);
+ SendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_TARGET);
+ break;
+
+ case 5: // turn off the xyz motor
+ if (!isMoving())
+ stepper.disable_all_steppers();
+ break;
+
+ #if ENABLED(CASE_LIGHT_ENABLE)
+ case 6: { // light control
+ const bool cls = !getCaseLightState();
+ SendValueToTFT(cls, ADDRESS_SYSTEM_LED_STATUS);
+ setCaseLightState(cls);
+ } break;
+ #endif
+ }
+ }
+
+ void DgusTFT::page8() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page8 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ //static uint16_t movespeed = 50;
+ static float move_dis = 1.0f;
+
+ if (key_value == 2 || key_value == 4
+ || key_value == 6 || key_value == 8
+ || key_value == 10 || (key_value == 12 && !isMoving())
+ ) {
+ if (getAxisPosition_mm(Z) < 0) setAxisPosition_mm(0, Z, 8);
+ }
+
+ // if (!planner.movesplanned())return;
+ switch (key_value) {
+ case 0:
+ break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_TOOL);
+ break;
+
+ case 5:
+ if (!isMoving())
+ injectCommands(F("G28 X"));
+ break;
+
+ case 9:
+ if (!isMoving())
+ injectCommands(F("G28 Y"));
+ break;
+
+ case 13:
+ if (!isMoving())
+ injectCommands(F("G28 Z"));
+ break;
+
+ case 17:
+ if (!isMoving())
+ injectCommands(F("G28"));
+ break;
+
+ case 2: // X-
+ if (!isMoving())
+ setAxisPosition_mm(getAxisPosition_mm(X) - move_dis, X, 50);
+ break;
+
+ case 4: // X+
+ if (!isMoving())
+ setAxisPosition_mm(getAxisPosition_mm(X) + move_dis, X, 50);
+ break;
+
+ case 6: // Y+
+ if (!isMoving())
+ setAxisPosition_mm(getAxisPosition_mm(Y) - move_dis, Y, 50);
+ break;
+
+ case 8: // Y-
+ if (!isMoving())
+ setAxisPosition_mm(getAxisPosition_mm(Y) + move_dis, Y, 50);
+ break;
+
+ case 10: // Z-
+ if (!isMoving())
+ setAxisPosition_mm(getAxisPosition_mm(Z) - move_dis, Z, 8);
+ break;
+
+ case 12: // Z+
+ if (!isMoving())
+ setAxisPosition_mm(getAxisPosition_mm(Z) + move_dis, Z, 8);
+ break;
+
+ case 3:
+ move_dis = 0.1f;
+ SendValueToTFT(1, ADDRESS_MOVE_DISTANCE);
+ break;
+
+ case 7:
+ move_dis = 1.0f;
+ SendValueToTFT(2, ADDRESS_MOVE_DISTANCE);
+ break;
+
+ case 11:
+ move_dis = 10.0f;
+ SendValueToTFT(3, ADDRESS_MOVE_DISTANCE);
+ break;
+
+ //case 14:
+ // movespeed = 3000; //SERIAL_ECHOLN(movespeed);
+ // break;
+ //
+ //case 15:
+ // movespeed = 2000; //SERIAL_ECHOLN(movespeed);
+ // break;
+ //
+ //case 16:
+ // movespeed = 1000; //SERIAL_ECHOLN(movespeed);
+ // break;
+ }
+ }
+
+ void DgusTFT::page9() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page9 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_TOOL);
+ break;
+
+ case 2: break;
+ case 3: break;
+ case 4: break;
+ case 5: break;
+
+ case 6: // cooling
+ setTargetTemp_celsius(0, E0);
+ setTargetTemp_celsius(0, BED);
+ ChangePageOfTFT(PAGE_TOOL);
+ break;
+
+ case 7: // send target temp
+ RequestValueFromTFT(TXT_HOTEND_TARGET);
+ RequestValueFromTFT(TXT_BED_TARGET);
+ ChangePageOfTFT(PAGE_TOOL);
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ SendValueToTFT(uint16_t(getActualTemp_celsius(E0)), TXT_HOTEND_NOW);
+ SendValueToTFT(uint16_t(getActualTemp_celsius(BED)), TXT_BED_NOW);
+ }
+
+ void DgusTFT::page10() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page10 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: // return
+ ChangePageOfTFT(PAGE_TOOL);
+ break;
+
+ case 2: break;
+ case 3: break;
+ case 4: break;
+ case 5: break;
+
+ case 6: // ok
+ RequestValueFromTFT(TXT_FAN_SPEED_TARGET);
+ RequestValueFromTFT(TXT_PRINT_SPEED_TARGET);
+ ChangePageOfTFT(PAGE_TOOL);
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ SendValueToTFT(uint16_t(getActualFan_percent(FAN0)), TXT_FAN_SPEED_NOW);
+ SendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW);
+ }
+
+ void DgusTFT::page11() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page11 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_MAIN);
+ store_changes();
+ break;
+
+ case 2: // language
+ toggle_language();
+ goto_system_page();
+ break;
+
+ case 3: break;
+
+ case 4: // audio
+ toggle_audio();
+ break;
+
+ case 5: { // about
+ char str_ver[32];
+ //sprintf(str_ver, "%04d-%02d-%02d %02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC);
+ sprintf(str_ver, MAIN_BOARD_FIRMWARE_VER);
+ SendTxtToTFT(str_ver, TXT_VERSION);
+ ChangePageOfTFT(PAGE_ABOUT);
+ } break;
+
+ case 6:
+ ChangePageOfTFT(PAGE_RECORD);
+ break;
+ }
+ }
+
+ void DgusTFT::page12() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page12 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+ case 1: // return
+ ChangePageOfTFT(PAGE_SYSTEM_CHS_AUDIO_ON);
+ break;
+ }
+ }
+
+ void DgusTFT::page13() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page13 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ goto_system_page();
+ break;
+
+ case 2: break;
+ }
+ }
+
+ void DgusTFT::page14() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page14 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+ case 1: break; // return
+ case 2: break;
+ case 3: break;
+ case 4: break;
+ }
+ }
+
+ void DgusTFT::page15() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page15 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_MAIN);
+ break;
+
+ case 2:
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ break;
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+ case 3: {
+ ChangePageOfTFT(PAGE_PREHEAT);
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PREHEAT_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PREHEAT_BED));
+ } break;
+ #endif
+
+ #if HAS_EXTRUDERS
+ case 4: {
+ send_temperature_hotend(TXT_FILAMENT_TEMP);
+ ChangePageOfTFT(PAGE_FILAMENT);
+ } break;
+ #endif
+ }
+ }
+
+ void DgusTFT::page16() { // AUTO LEVELING
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page16 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+ case 1: // return
+ ChangePageOfTFT(PAGE_PREPARE);
+ break;
+
+ case 2:
+ if (!isPrinting()) {
+ //ChangePageOfTFT(PAGE_LEVEL_ENSURE);
+ ChangePageOfTFT(PAGE_CHS_PROBE_PRECHECK);
+ }
+ break;
+
+ case 3: {
+ char str_buf[10];
+ str_buf[0] = '\0';
+ strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2);
+ SendTxtToTFT(str_buf, TXT_LEVEL_OFFSET);
+ //SendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET);
+ ChangePageOfTFT(PAGE_LEVEL_ADVANCE);
+ } break;
+
+ case 4:
+ ChangePageOfTFT(PAGE_AUTO_OFFSET);
+ break;
+ }
+ }
+
+ void DgusTFT::page17() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page17 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ float z_off;
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ break;
+
+ case 2: {
+ setSoftEndstopState(false);
+ if (getZOffset_mm() <= -5) return;
+ z_off = getZOffset_mm() - 0.01f;
+ setZOffset_mm(z_off);
+
+ char str_buf[10];
+ strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2);
+ SendTxtToTFT(str_buf, TXT_LEVEL_OFFSET);
+ //SendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET);
+
+ if (isAxisPositionKnown(Z)) {
+ const float currZpos = getAxisPosition_mm(Z);
+ setAxisPosition_mm(currZpos - 0.01f, Z);
+ }
+
+ setSoftEndstopState(true);
+ } break;
+
+ case 3: {
+ setSoftEndstopState(false);
+ if (getZOffset_mm() >= 5) return;
+ z_off = getZOffset_mm() + 0.01f;
+ setZOffset_mm(z_off);
+
+ char str_buf[10];
+ strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2);
+ SendTxtToTFT(str_buf, TXT_LEVEL_OFFSET);
+ //SendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET);
+
+ if (isAxisPositionKnown(Z)) { // Move Z axis
+ const float currZpos = getAxisPosition_mm(Z);
+ setAxisPosition_mm(currZpos + 0.01f, Z);
+ }
+
+ setSoftEndstopState(true);
+ } break;
+
+ case 4:
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_ECHOLNPGM("z off: ", ftostr52sprj(getZOffset_mm()));
+ #endif
+ #if HAS_LEVELING
+ GRID_LOOP(x, y) {
+ const xy_uint8_t pos { x, y };
+ const float currval = getMeshPoint(pos);
+ setMeshPoint(pos, constrain(currval + getZOffset_mm(), AC_LOWEST_MESHPOINT_VAL, 5));
+ }
+ injectCommands(F("M500"));
+ #endif
+ ChangePageOfTFT(PAGE_PREPARE);
+ break;
+ }
+ }
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+
+ void DgusTFT::page18() { // preheat
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page18 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(PAGE_PREPARE);
+ break;
+
+ case 2: // PLA
+ TERN_(HAS_HOTEND, setTargetTemp_celsius(190, E0));
+ TERN_(HAS_HEATED_BED, setTargetTemp_celsius(60, BED));
+ ChangePageOfTFT(PAGE_PREHEAT);
+ break;
+
+ case 3: // ABS
+ TERN_(HAS_HOTEND, setTargetTemp_celsius(240, E0));
+ TERN_(HAS_HEATED_BED, setTargetTemp_celsius(100, BED));
+ ChangePageOfTFT(PAGE_PREHEAT);
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PREHEAT_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PREHEAT_BED));
+ }
+
+ #endif // HAS_HOTEND || HAS_HEATED_BED
+
+ #if HAS_EXTRUDERS
+
+ void DgusTFT::page19() { // Filament
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page19 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ static char filament_status = 0;
+ static millis_t flash_time = 0;
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ filament_status = 0;
+ injectCommands(F("G90"));
+ ChangePageOfTFT(PAGE_PREPARE);
+ break;
+
+ case 2: // Filament in
+ if (getActualTemp_celsius(E0) < 220) {
+ filament_status = 0;
+ ChangePageOfTFT(PAGE_FILAMENT_HEAT);
+ }
+ else {
+ filament_status = 1;
+ injectCommands(F("G91"));
+ }
+ break;
+
+ case 3: // filament out
+ if (getActualTemp_celsius(E0) < 220) {
+ filament_status = 0;
+ ChangePageOfTFT(PAGE_FILAMENT_HEAT);
+ }
+ else {
+ filament_status = 2;
+ injectCommands(F("G91"));
+ }
+ break;
+
+ case 4: // stop
+ filament_status = 0;
+ break;
+
+ }
+
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ send_temperature_hotend(TXT_FILAMENT_TEMP);
+
+ if (!isPrinting()) {
+ if (filament_status == 1) {
+ if (canMove(E0) && !commandsInQueue())
+ injectCommands_P(AC_cmnd_manual_load_filament);
+ }
+ else if (filament_status == 2) {
+ if (canMove(E0) && !commandsInQueue())
+ injectCommands_P(AC_cmnd_manual_unload_filament);
+ }
+ }
+ }
+
+ #endif // HAS_EXTRUDERS
+
+ void DgusTFT::page20() { // confirm
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page20 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: // return
+ ChangePageOfTFT(page_index_last);
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page21() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page21 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ ChangePageOfTFT(page_index_last);
+ break;
+
+ case 2: break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page22() { // print finish
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page22 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // OK to finish
+ TERN_(CASE_LIGHT_ENABLE, setCaseLightState(false));
+ ChangePageOfTFT(PAGE_MAIN);
+ break;
+
+ case 2: break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page23() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page23 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: ChangePageOfTFT(page_index_last); break; // return
+ case 2: ChangePageOfTFT(page_index_last); break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page24() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page24 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: ChangePageOfTFT(page_index_last); break; // return
+ case 2: ChangePageOfTFT(page_index_last); break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page25() { // lack filament
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page25 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ #if ACDEBUG(AC_MARLIN)
+ DEBUG_PRINT_PRINTER_STATE(F("printer_state: "), printer_state);
+ DEBUG_PRINT_PAUSED_STATE(F("pause_state: "), pause_state);
+ #endif
+ if (AC_printer_printing == printer_state)
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ else if (AC_printer_paused == printer_state) {
+ //injectCommands(F("M108"));
+ ChangePageOfTFT(PAGE_STATUS1); // show resume
+ }
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page26() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page26 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: ChangePageOfTFT(page_index_last); break; // return
+ case 2: break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page27() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page27 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // print stop confirmed
+ if (isPrintingFromMedia()) {
+ printer_state = AC_printer_stopping;
+ stopPrint();
+ message_index = 6;
+ ChangePageOfTFT(PAGE_MAIN);
+ }
+ else {
+ if (printer_state == AC_printer_resuming_from_power_outage)
+ injectCommands(F("M1000 C")); // Cancel recovery
+ printer_state = AC_printer_idle;
+ }
+ break;
+
+ case 2: // return
+ if (AC_printer_printing == printer_state)
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ else if (AC_printer_paused == printer_state)
+ ChangePageOfTFT(PAGE_STATUS1); // show print
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page28() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page28 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: ChangePageOfTFT(page_index_last); break; // return
+ case 2: break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page29() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page29 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ TERN_(CASE_LIGHT_ENABLE, setCaseLightState(false));
+ ChangePageOfTFT(PAGE_MAIN);
+ break;
+
+ case 2: break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page30() { // Auto heat filament
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page30 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // return
+ setTargetTemp_celsius(230, E0);
+ ChangePageOfTFT(PAGE_FILAMENT);
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page31() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page31 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+ case 1: break; // return
+ case 2: break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page32() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page32 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ #if HAS_LEVELING
+
+ void DgusTFT::page33() {
+ #if ACDEBUG(AC_ALL)
+ if (page_index_saved != page_index_now) {
+ DEBUG_ECHOLNPGM("page33 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ }
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: // auto leveling start
+ injectCommands(F("G28\nG29"));
+ printer_state = AC_printer_probing;
+
+ // this will cause leveling->preheating->leveling
+ #if 0
+ #if ENABLED(PREHEAT_BEFORE_LEVELING)
+ if (getTargetTemp_celsius(E0) < LEVELING_NOZZLE_TEMP
+ || getTargetTemp_celsius(BED) < LEVELING_BED_TEMP
+ ) {
+ setTargetTemp_celsius(LEVELING_NOZZLE_TEMP, E0);
+ setTargetTemp_celsius(LEVELING_BED_TEMP, BED);
+ ChangePageOfTFT(PAGE_CHS_PROBE_PREHEATING);
+ }
+ else
+ ChangePageOfTFT(PAGE_LEVELING);
+
+ #else
+ ChangePageOfTFT(PAGE_LEVELING);
+ #endif
+ #endif
+
+ ChangePageOfTFT(PAGE_LEVELING);
+ break;
+
+ case 2:
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ break;
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+ }
+
+ void DgusTFT::page34() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page34 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_MAIN_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_MAIN_BED));
+ #endif
+
+ if (pop_up_index == 25) {
+ pop_up_index = 100;
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ }
+ }
+
+ #endif // HAS_LEVELING
+
+ void DgusTFT::page115() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page115 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ switch (key_value) {
+
+ case 0: break;
+ case 1: ChangePageOfTFT(PAGE_PreLEVEL); break;
+
+ case 2: {
+ injectCommands(F("M1024 S3")); // -1
+ //char value[20]
+ //sprintf_P(value, PSTR("G1 Z%iF%i")); enqueue_and_echo_command_now(value); }
+ } break;
+
+ case 3: injectCommands(F("M1024 S4")); break; // 1
+ case 4: injectCommands(F("M1024 S1")); break; // -0.1
+ case 5: injectCommands(F("M1024 S2")); break; // 0.1
+ case 6: injectCommands(F("M1024 S0")); break; // prepare, move x y to center
+ case 7: injectCommands(F("M1024 S5")); break; // 0.1
+ }
+
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1000;
+ }
+
+ void DgusTFT::page117() { // Page CHS Mute handler
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page117 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+
+ case 1:
+ ChangePageOfTFT(PAGE_MAIN);
+ store_changes();
+ break;
+
+ case 2: // language
+ toggle_language();
+ goto_system_page();
+ break;
+
+ case 3: break;
+
+ case 4: // audio
+ toggle_audio();
+ break;
+
+ case 5: // about
+ char str_ver[32];
+ //sprintf(str_ver, "%04d-%02d-%02d %02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC);
+ sprintf(str_ver, MAIN_BOARD_FIRMWARE_VER);
+ SendTxtToTFT(str_ver, TXT_VERSION);
+ ChangePageOfTFT(PAGE_ABOUT);
+ break;
+
+ case 6:
+ ChangePageOfTFT(PAGE_RECORD);
+ break;
+ }
+ }
+
+ void DgusTFT::page124() { // first time into page 124 the feedrate percent is not set
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page124 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ //DEBUG_ECHOLNPGM("update feedrate percent");
+ }
+ #endif
+ SendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW);
+ }
+
+ void DgusTFT::page125() { // first time into page 125 the feedrate percent is not set
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page125 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ //DEBUG_ECHOLNPGM("update feedrate percent");
+ }
+ #endif
+ SendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW);
+ }
+
+ void DgusTFT::page170() { // ENG Mute handler
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page170 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 0: break;
+
+ case 1:
+ ChangePageOfTFT(PAGE_MAIN);
+ store_changes();
+ break;
+
+ case 2: // language
+ toggle_language();
+ goto_system_page();
+ break;
+
+ case 3: break;
+
+ case 4: // audio
+ toggle_audio();
+ break;
+
+ case 5: // about
+ char str_ver[32];
+ //sprintf(str_ver, "%04d-%02d-%02d %02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC);
+ sprintf(str_ver, MAIN_BOARD_FIRMWARE_VER);
+ SendTxtToTFT(str_ver, TXT_VERSION);
+ ChangePageOfTFT(PAGE_ABOUT);
+ break;
+
+ case 6:
+ ChangePageOfTFT(PAGE_RECORD);
+ break;
+ }
+ }
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+
+ void DgusTFT::page171() { // CHS power outage resume handler
+ #if ACDEBUG(AC_ALL)
+ if (page_index_saved != page_index_now) {
+ DEBUG_ECHOLNPGM("page171 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ }
+ #endif
+ #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+ char filename[64] = { '\0' };
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: { // resume
+ ChangePageOfTFT(PAGE_OUTAGE_RECOVERY);
+ #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+ card.getLongPath(filename, recovery.info.sd_filename);
+ filename[17] = '\0';
+ SendTxtToTFT(filename, TXT_OUTAGE_RECOVERY_FILE);
+ #else
+ SendTxtToTFT(recovery.info.sd_filename, TXT_OUTAGE_RECOVERY_FILE);
+ #endif
+
+ char str_buf[20] = { '\0' };
+ sprintf(str_buf, "%u", uint16_t(getFeedrate_percent()));
+ SendTxtToTFT(str_buf, TXT_PRINT_SPEED);
+
+ sprintf(str_buf, "%u", uint16_t(getProgress_percent()));
+ SendTxtToTFT(str_buf, TXT_PRINT_PROGRESS);
+
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ injectCommands(F("M355 S1\nM1000")); // case light on, home and start recovery
+ } break;
+
+ case 2: // cancel
+ printer_state = AC_printer_idle;
+ ChangePageOfTFT(PAGE_MAIN);
+ injectCommands(F("M355 S0\nM1000 C")); // cancel recovery
+ break;
+ }
+ }
+
+ void DgusTFT::page173() { // ENG power outage resume handler
+ #if ACDEBUG(AC_ALL)
+ if (page_index_saved != page_index_now) {
+ DEBUG_ECHOLNPGM("page173 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ }
+ #endif
+ #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+ char filename[64] = { '\0' };
+ #endif
+
+ switch (key_value) {
+ case 0: break;
+
+ case 1: { // resume
+ ChangePageOfTFT(PAGE_OUTAGE_RECOVERY);
+ #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+ card.getLongPath(filename, recovery.info.sd_filename);
+ filename[17] = '\0';
+ SendTxtToTFT(filename, TXT_OUTAGE_RECOVERY_FILE);
+ #else
+ SendTxtToTFT(recovery.info.sd_filename, TXT_OUTAGE_RECOVERY_FILE);
+ #endif
+
+ char str_buf[20] = { '\0' };
+ sprintf(str_buf, "%u", uint16_t(getFeedrate_percent()));
+ SendTxtToTFT(str_buf, TXT_PRINT_SPEED);
+
+ sprintf(str_buf, "%u", uint16_t(getProgress_percent()));
+ SendTxtToTFT(str_buf, TXT_PRINT_PROGRESS);
+
+ ChangePageOfTFT(PAGE_STATUS2); // show pause
+ injectCommands(F("M355 S1\nM1000")); // case light on, home and start recovery
+ } break;
+
+ case 2: // cancel
+ printer_state = AC_printer_idle;
+ ChangePageOfTFT(PAGE_MAIN);
+ injectCommands(F("M355 S0\nM1000 C")); // cancel recovery
+ break;
+ }
+ }
+
+ #endif // POWER_LOSS_RECOVERY
+
+ #if HAS_LEVELING
+
+ void DgusTFT::page175() { // CHS probe preheating handler
+ #if ACDEBUG(AC_ALL)
+ if (page_index_saved != page_index_now) {
+ DEBUG_ECHOLNPGM("page175 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ }
+ #endif
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_MAIN_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_MAIN_BED));
+ #endif
+ }
+
+ void DgusTFT::page176() { // ENG probe preheating handler
+ #if ACDEBUG(AC_ALL)
+ if (page_index_saved != page_index_now) {
+ DEBUG_ECHOLNPGM("page176 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ }
+ #endif
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_MAIN_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_MAIN_BED));
+ #endif
+ }
+
+ #endif // HAS_LEVELING
+
+ void DgusTFT::page177_to_198() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page177_to_198 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 1: // return
+ #if ACDEBUG(AC_MARLIN)
+ //DEBUG_ECHOLNPGM("page_index_now: ", page_index_now);
+ //DEBUG_ECHOLNPGM("page_index_last: ", page_index_last);
+ //DEBUG_ECHOLNPGM("page_index_last_2: ", page_index_last_2);
+ #endif
+
+ if ((WITHIN(page_index_now, PAGE_CHS_ABNORMAL_X_ENDSTOP, PAGE_CHS_ABNORMAL_Z_ENDSTOP))
+ || (WITHIN(page_index_now, PAGE_ENG_ABNORMAL_X_ENDSTOP, PAGE_ENG_ABNORMAL_Z_ENDSTOP))
+ ) {
+ if (lcd_info.language == ENG) {
+ if (page_index_last_2 > 120) page_index_last_2 -= 120;
+ if (page_index_last > 120) page_index_last -= 120;
+ }
+
+ if (PAGE_STATUS1 == page_index_last_2 || PAGE_STATUS2 == page_index_last_2 || PAGE_PRINT_FINISH == page_index_last)
+ ChangePageOfTFT(PAGE_MAIN);
+ else
+ ChangePageOfTFT(page_index_last_2);
+ }
+ else {
+ if (lcd_info.language == ENG && page_index_last > 120)
+ page_index_last -= 120;
+ ChangePageOfTFT(page_index_last);
+ }
+
+ onSurviveInKilled();
+ stepper.disable_all_steppers();
+ break;
+
+ default: break;
+ }
+ }
+
+ #if 0
+ void DgusTFT::page178_to_181_190_to_193() { // temperature abnormal
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page178_to_181_190_to_193 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 1: // return
+ SERIAL_ECHOLNPGM("page_index_now: ", page_index_now);
+ SERIAL_ECHOLNPGM("page_index_last: ", page_index_last);
+ SERIAL_ECHOLNPGM("page_index_last_2: ", page_index_last_2);
+
+ if (isPrinting() || isPrintingPaused() || isPrintingFromMedia()) {
+ printer_state = AC_printer_stopping;
+ stopPrint();
+ ChangePageOfTFT(PAGE_MAIN);
+ }
+ else
+ ChangePageOfTFT(page_index_last);
+
+ onSurviveInKilled();
+ break;
+
+ default: break;
+ }
+ }
+ #endif
+
+ void DgusTFT::page199_to_200() {
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page199_to_200 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ switch (key_value) {
+ case 1: // return
+ #if ACDEBUG(AC_MARLIN)
+ //DEBUG_ECHOLNPGM("page_index_now: ", page_index_now);
+ //DEBUG_ECHOLNPGM("page_index_last: ", page_index_last);
+ //DEBUG_ECHOLNPGM("page_index_last_2: ", page_index_last_2);
+ #endif
+ onSurviveInKilled();
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ break;
+
+ default: break;
+ }
+ }
+
+ inline void ProbeTare() {
+ #if PIN_EXISTS(AUTO_LEVEL_TX)
+ OUT_WRITE(AUTO_LEVEL_TX_PIN, LOW);
+ delay(300);
+ OUT_WRITE(AUTO_LEVEL_TX_PIN, HIGH);
+ delay(100);
+ #endif
+ }
+
+ inline bool getProbeState() { return PROBE_TRIGGERED(); }
+
+ void DgusTFT::page201() { // probe precheck
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page201 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ static millis_t probe_check_time = 0;
+ static millis_t temperature_time = 0;
+ static uint8_t probe_check_counter = 0;
+ static uint8_t probe_state_last = 0;
+ static bool probe_tare_flag = 0;
+
+ if (!probe_tare_flag) {
+ ProbeTare();
+
+ delay(100);
+
+ if (getProbeState()) { // triggered too early
+ probe_check_counter = 0;
+ probe_tare_flag = 0;
+ ChangePageOfTFT(PAGE_CHS_PROBE_PRECHECK_FAILED);
+ }
+ probe_tare_flag = 1;
+ }
+
+ switch (key_value) {
+ case 1: // cancel
+ probe_check_counter = 0;
+ probe_tare_flag = 0;
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ break;
+
+ default: break;
+ }
+
+ if (ELAPSED(millis(), probe_check_time)) {
+ probe_check_time = millis() + 300;
+
+ if (!probe_state_last && getProbeState()) {
+ probe_check_counter = 0;
+ probe_tare_flag = 0;
+ ChangePageOfTFT(PAGE_CHS_PROBE_PRECHECK_OK);
+ }
+
+ probe_state_last = getProbeState();
+
+ if (probe_check_counter++ >= 200) { // waiting for 1 min
+ probe_check_counter = 0;
+ probe_tare_flag = 0;
+ ChangePageOfTFT(PAGE_CHS_PROBE_PRECHECK_FAILED);
+ }
+ }
+
+ if (ELAPSED(millis(), temperature_time)) {
+ temperature_time = millis() + 1500;
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_MAIN_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_MAIN_BED));
+ }
+ }
+
+ void DgusTFT::page202() { // probe precheck ok
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page202 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+
+ //static millis_t flash_time = 0;
+ //static millis_t probe_check_counter = 0;
+ //static uint8_t probe_state_last = 0;
+
+ delay(3000);
+
+ injectCommands(F("G28\nG29"));
+ printer_state = AC_printer_probing;
+ ChangePageOfTFT(PAGE_LEVELING);
+ }
+
+ void DgusTFT::page203() { // probe precheck failed
+ #if ACDEBUG(AC_ALL)
+ if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) {
+ DEBUG_ECHOLNPGM("page203 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now);
+ page_index_saved = page_index_now;
+ key_value_saved = key_value;
+ }
+ #endif
+ //static millis_t probe_check_counter = 0;
+ //static uint8_t probe_state_last = 0;
+
+ #if HAS_HOTEND || HAS_HEATED_BED
+ static millis_t flash_time = 0;
+ const millis_t ms = millis();
+ if (PENDING(ms, flash_time)) return;
+ flash_time = ms + 1500;
+
+ TERN_(HAS_HOTEND, send_temperature_hotend(TXT_MAIN_HOTEND));
+ TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_MAIN_BED));
+ #endif
+ }
+
+ void DgusTFT::pop_up_manager() {
+ #if ACDEBUG(AC_ALL)
+ if (pop_up_index_saved != pop_up_index) {
+ DEBUG_ECHOLNPGM("pop_up_manager pop_up_index: ", pop_up_index);
+ pop_up_index_saved = pop_up_index;
+ }
+ #endif
+
+ switch (pop_up_index) {
+ case 10: // T0 error
+ if (page_index_now != PAGE_ABNORMAL)
+ ChangePageOfTFT(PAGE_ABNORMAL);
+ pop_up_index = 100;
+ break;
+
+ case 15: // filament lack
+ if (page_index_now != PAGE_FILAMENT_LACK)
+ ChangePageOfTFT(PAGE_FILAMENT_LACK);
+ pop_up_index = 100;
+ break;
+
+ case 16: // stop wait
+ ChangePageOfTFT(PAGE_WAIT_STOP);
+ pop_up_index = 100;
+ break;
+
+ case 18:
+ ChangePageOfTFT(PAGE_STATUS1);
+ pop_up_index = 100;
+ break;
+
+ case 23: //
+ if (page_index_now != PAGE_FILAMENT_LACK)
+ ChangePageOfTFT(PAGE_FILAMENT_LACK);
+ pop_up_index = 100;
+ break;
+
+ case 24: { //
+ uint32_t time = getProgress_seconds_elapsed() / 60;
+ char str_buf[20];
+ sprintf(str_buf, "%s H ", utostr3(time / 60));
+ sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60));
+ SendTxtToTFT(str_buf, TXT_FINISH_TIME);
+ ChangePageOfTFT(PAGE_PRINT_FINISH);
+ //SendtoTFTLN(AC_msg_print_complete); // no idea why this causes a compile error
+ pop_up_index = 100;
+ } break;
+
+ case 25: // LEVEL DONE
+ ChangePageOfTFT(PAGE_PreLEVEL);
+ pop_up_index = 100;
+ break;
+ }
+ }
+
+ void DEBUG_PRINT_PAUSED_STATE(FSTR_P const msg, paused_state_t state) {
+ DEBUG_ECHOPGM(msg, state);
+ switch (state) {
+ case AC_paused_heater_timed_out:
+ DEBUG_ECHOLNPGM(" AC_paused_heater_timed_out");
+ break;
+ case AC_paused_filament_lack:
+ DEBUG_ECHOLNPGM(" AC_paused_filament_lack");
+ break;
+ case AC_paused_purging_filament:
+ DEBUG_ECHOLNPGM(" AC_paused_purging_filament");
+ break;
+ case AC_paused_idle:
+ DEBUG_ECHOLNPGM(" AC_paused_idle");
+ break;
+ }
+ }
+
+// routines to make the debug outputs human readable
+
+ void DEBUG_PRINT_PRINTER_STATE(FSTR_P const msg, printer_state_t state) {
+ DEBUG_ECHOPGM(msg, state);
+ switch (state) {
+ case AC_printer_idle:
+ DEBUG_ECHOLNPGM(" AC_printer_idle");
+ break;
+ case AC_printer_probing:
+ DEBUG_ECHOLNPGM(" AC_printer_probing");
+ break;
+ case AC_printer_printing:
+ DEBUG_ECHOLNPGM(" AC_printer_printing");
+ break;
+ case AC_printer_pausing:
+ DEBUG_ECHOLNPGM(" AC_printer_pausing");
+ break;
+ case AC_printer_paused:
+ DEBUG_ECHOLNPGM(" AC_printer_paused");
+ break;
+ case AC_printer_stopping:
+ DEBUG_ECHOLNPGM(" AC_printer_stopping");
+ break;
+ case AC_printer_stopping_from_media_remove:
+ DEBUG_ECHOLNPGM(" AC_printer_stopping_from_media_remove");
+ break;
+ case AC_printer_resuming_from_power_outage:
+ DEBUG_ECHOLNPGM(" AC_printer_resuming_from_power_outage");
+ break;
+ }
+ }
+
+ void DEBUG_PRINT_TIMER_EVENT(FSTR_P const msg, timer_event_t event) {
+ DEBUG_ECHOPGM(msg, event);
+ switch (event) {
+ case AC_timer_started:
+ DEBUG_ECHOLNPGM(" AC_timer_started");
+ break;
+ case AC_timer_paused:
+ DEBUG_ECHOLNPGM(" AC_timer_paused");
+ break;
+ case AC_timer_stopped:
+ DEBUG_ECHOLNPGM(" AC_timer_stopped");
+ break;
+ }
+ }
+
+ void DEBUG_PRINT_MEDIA_EVENT(FSTR_P const msg, media_event_t event) {
+ DEBUG_ECHOPGM(msg, event);
+ switch (event) {
+ case AC_media_inserted:
+ DEBUG_ECHOLNPGM(" AC_media_inserted");
+ break;
+ case AC_media_removed:
+ DEBUG_ECHOLNPGM(" AC_media_removed");
+ break;
+ case AC_media_error:
+ DEBUG_ECHOLNPGM(" AC_media_error");
+ break;
+ }
+ }
+
+} // namespace
+
+#endif // ANYCUBIC_LCD_VYPER
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h
new file mode 100644
index 0000000000..1903fa1183
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h
@@ -0,0 +1,479 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * lcd/extui/anycubic_vyper/dgus_tft.h
+ */
+
+#include "dgus_tft_defs.h"
+#include "../../../inc/MarlinConfigPre.h"
+#include "../ui_api.h"
+
+#define MAIN_BOARD_FIRMWARE_VER "V2.4.5"
+
+#define DATA_BUF_SIZE 64
+
+/****************** PAGE INDEX***********************/
+#define PAGE_OFFSET 0
+#define PAGE_MAIN (1+PAGE_OFFSET)
+#define PAGE_FILE (2+PAGE_OFFSET)
+#define PAGE_STATUS1 (3+PAGE_OFFSET) // show resume
+#define PAGE_STATUS2 (4+PAGE_OFFSET) // show pause
+#define PAGE_ADJUST (5+PAGE_OFFSET)
+#define PAGE_KEYBPARD (6+PAGE_OFFSET)
+#define PAGE_TOOL (7+PAGE_OFFSET)
+#define PAGE_MOVE (8+PAGE_OFFSET)
+#define PAGE_TEMP (9+PAGE_OFFSET)
+#define PAGE_SPEED (10+PAGE_OFFSET)
+#define PAGE_SYSTEM_CHS_AUDIO_ON (11+PAGE_OFFSET)
+#define PAGE_WIFI (12+PAGE_OFFSET)
+#define PAGE_ABOUT (13+PAGE_OFFSET)
+#define PAGE_RECORD (14+PAGE_OFFSET)
+#define PAGE_PREPARE (15+PAGE_OFFSET)
+#define PAGE_PreLEVEL (16+PAGE_OFFSET)
+#define PAGE_LEVEL_ADVANCE (17+PAGE_OFFSET)
+#define PAGE_PREHEAT (18+PAGE_OFFSET)
+#define PAGE_FILAMENT (19+PAGE_OFFSET)
+
+#define PAGE_DONE (20+PAGE_OFFSET)
+#define PAGE_ABNORMAL (21+PAGE_OFFSET)
+#define PAGE_PRINT_FINISH (22+PAGE_OFFSET)
+#define PAGE_WAIT_STOP (23+PAGE_OFFSET)
+#define PAGE_FILAMENT_LACK (25+PAGE_OFFSET)
+#define PAGE_FORBIT (26+PAGE_OFFSET)
+#define PAGE_STOP_CONF (27+PAGE_OFFSET)
+#define PAGE_NO_SD (29+PAGE_OFFSET)
+#define PAGE_FILAMENT_HEAT (30+PAGE_OFFSET)
+#define PAGE_WAIT_PAUSE (32+PAGE_OFFSET)
+
+#define PAGE_LEVEL_ENSURE (33+PAGE_OFFSET)
+#define PAGE_LEVELING (34+PAGE_OFFSET)
+
+#define PAGE_AUTO_OFFSET (115+PAGE_OFFSET)
+
+#define PAGE_SYSTEM_CHS_AUDIO_OFF (117+PAGE_OFFSET)
+
+#define PAGE_SYSTEM_ENG_AUDIO_ON (131+PAGE_OFFSET)
+#define PAGE_SYSTEM_ENG_AUDIO_OFF (170+PAGE_OFFSET)
+
+#define PAGE_OUTAGE_RECOVERY (171+PAGE_OFFSET)
+#define PAGE_ENG_OUTAGE_RECOVERY (173+PAGE_OFFSET)
+
+#define PAGE_CHS_PROBE_PREHEATING (176+PAGE_OFFSET)
+#define PAGE_ENG_PROBE_PREHEATING (175+PAGE_OFFSET)
+
+#define PAGE_CHS_HOMING (177+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_BED_HEATER (178+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_BED_NTC (179+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_HOTEND_HEATER (180+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_HOTEND_NTC (181+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_ENDSTOP (182+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_X_ENDSTOP (182+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_Y_ENDSTOP (183+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_Z_ENDSTOP (184+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_ZL_ENDSTOP (185+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_ZR_ENDSTOP (186+PAGE_OFFSET)
+#define PAGE_CHS_ABNORMAL_LEVELING_SENSOR (187+PAGE_OFFSET)
+#define PAGE_CHS_LEVELING_FAILED (188+PAGE_OFFSET)
+
+#define PAGE_ENG_HOMING (189+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_BED_HEATER (190+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_BED_NTC (191+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_HOTEND_HEATER (192+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_HOTEND_NTC (193+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_ENDSTOP (194+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_X_ENDSTOP (194+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_Y_ENDSTOP (195+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_Z_ENDSTOP (196+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_ZL_ENDSTOP (197+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_ZR_ENDSTOP (198+PAGE_OFFSET)
+#define PAGE_ENG_ABNORMAL_LEVELING_SENSOR (199+PAGE_OFFSET)
+#define PAGE_ENG_LEVELING_FAILED (200+PAGE_OFFSET)
+
+#define PAGE_CHS_PROBE_PRECHECK (201+PAGE_OFFSET)
+#define PAGE_CHS_PROBE_PRECHECK_OK (202+PAGE_OFFSET)
+#define PAGE_CHS_PROBE_PRECHECK_FAILED (203+PAGE_OFFSET)
+
+#define PAGE_ENG_PROBE_PRECHECK (204+PAGE_OFFSET)
+#define PAGE_ENG_PROBE_PRECHECK_OK (205+PAGE_OFFSET)
+#define PAGE_ENG_PROBE_PRECHECK_FAILED (206+PAGE_OFFSET)
+
+/****************** Lcd control **************************/
+#define REG_LCD_READY 0x0014
+
+/****************** TXT **************************/
+
+// MAIN PAGE TXT
+#define TXT_MAIN_BED 0x2000
+#define TXT_MAIN_HOTEND 0x2030
+#define TXT_MAIN_MESSAGE 0x2060
+
+// FILE TXT
+#define TXT_FILE_0 (0x2000+3*0x30)
+#define TXT_DESCRIPT_0 0x5000 // DESCRIBE ADDRESS
+#define TXT_FILE_1 (0x2000+4*0x30)
+#define TXT_DESCRIPT_1 0x5030
+#define TXT_FILE_2 (0x2000+5*0x30)
+#define TXT_DESCRIPT_2 0x5060
+#define TXT_FILE_3 (0x2000+6*0x30)
+#define TXT_DESCRIPT_3 0x5090
+#define TXT_FILE_4 (0x2000+7*0x30)
+#define TXT_DESCRIPT_4 0x50C0
+
+// PRINT TXT
+#define TXT_PRINT_NAME 0x2000+8*0x30
+#define TXT_PRINT_SPEED 0x2000+9*0x30
+#define TXT_PRINT_TIME 0x2000+10*0x30
+#define TXT_PRINT_PROGRESS 0x2000+11*0x30
+#define TXT_PRINT_HOTEND 0x2000+12*0x30
+#define TXT_PRINT_BED 0x2000+13*0x30
+
+// PRINT ADJUST TXT
+
+#define TXT_ADJUST_HOTEND (0x2000+14*0x30)
+#define TXT_ADJUST_BED (0x2000+15*0x30)
+#define TXT_ADJUST_SPEED (0x2000+16*0x30)
+
+// TEMP SET TXT
+
+#define TXT_BED_NOW (0x2000+17*0x30)
+#define TXT_BED_TARGET (0x2000+18*0x30)
+#define TXT_HOTEND_NOW (0x2000+19*0x30)
+#define TXT_HOTEND_TARGET (0x2000+20*0x30)
+
+// SPEED SET TXT
+#define TXT_FAN_SPEED_NOW (0x2000+21*0x30)
+#define TXT_FAN_SPEED_TARGET (0x2000+22*0x30)
+#define TXT_PRINT_SPEED_NOW (0x2000+23*0x30)
+#define TXT_PRINT_SPEED_TARGET (0x2000+24*0x30)
+
+// ABOUT TXT
+#define TXT_ABOUT (0x2000+25*0x30)
+
+// RECORT TXT
+#define TXT_RECORT_0 (0x2000+26*0x30)
+#define TXT_RECORT_1 (0x2000+27*0x30)
+#define TXT_RECORT_2 (0x2000+28*0x30)
+#define TXT_RECORT_3 (0x2000+29*0x30)
+#define TXT_RECORT_4 (0x2000+30*0x30)
+#define TXT_RECORT_5 (0x2000+31*0x30)
+
+// ADVANCE LEVEL TXT
+#define TXT_LEVEL_OFFSET (0x2000+32*0x30)
+
+// FILAMENT TXT
+#define TXT_FILAMENT_TEMP (0x2000+33*0x30)
+
+#define TXT_FINISH_TIME (0x2000+34*0x30)
+#define TXT_VERSION (0x2000+35*0x30)
+#define TXT_PREHEAT_HOTEND (0x2000+36*0x30)
+#define TXT_PREHEAT_BED (0x2000+37*0x30)
+
+#define TXT_OUTAGE_RECOVERY_FILE 0x2180
+
+#define ADDRESS_SYSTEM_AUDIO 0x0080
+
+#define ADDRESS_MOVE_DISTANCE 0x4300
+#define ADDRESS_SYSTEM_LED_STATUS 0x4500
+#define ADDRESS_PRINT_SETTING_LED_STATUS 0x4550
+
+/*********************** KEY VALUE **************************/
+#define KEY_ADDRESS 0x1000
+
+// MAIN PAGE KEY
+
+#define KEY_MAIN_TO_FILE 1
+#define KEY_MAIN_TO_TOOL 2
+#define KEY_MAIN_TO_PREPARE 3
+#define KEY_MAIN_TO_SYSTEM 4
+
+// FILE PAGE KEY
+
+#define KEY_FILE_TO_MAIN 1
+#define KEY_PRINT 6
+#define KEY_RESUME 5
+#define KEY_PgUp 2
+#define KEY_pgDn 3
+#define KEY_FLASH 4
+#define KEY_FILE0 7
+#define KEY_FILE1 8
+#define KEY_FILE2 9
+#define KEY_FILE3 10
+#define KEY_FILE4 11
+
+#define KEY_CONTINUE 2
+#define KEY_PAUSE 2
+#define KEY_STOP 3
+#define KEY_TO_ADJUST 4
+#define KEY_ADJUST_TO_PRINT 1
+#define KEY_ADJUST_ENSURE 7
+#define KEY_CHECK_DOOR 2
+#define KEY_DONE_OFF 3
+
+// TOOL PAGE KEY
+
+#define KEY_TOOL_TO_MAIN 1
+#define KEY_TOOL_TO_MOVE 2
+#define KEY_TOOL_TO_TEMP 3
+#define KEY_TOOL_TO_SPEED 4
+#define KEY_TOOL_LIGHT 5
+
+#define KEY_MOVE_TO_TOLL 1// move page
+#define KEY_MOVE_X 2
+#define KEY_01 3
+#define KEY_MOVE_NX 4
+#define KEY_HOME_X 5
+#define KEY_MOVE_Y 6
+#define KEY_1 7
+#define KEY_MOVE_NY 8
+#define KEY_HOME_Y 9
+#define KEY_MOVE_Z 10
+#define KEY_10 11
+#define KEY_MOVE_NZ 12
+#define KEY_HOME_Z 13
+#define KEY_SPEED_LOW 14
+#define KEY_SPEED_MIDDLE 15
+#define KEY_SPEED_HIGHT 16
+#define KEY_HOME_ALL 17
+
+#define KEY_TEMP_TO_TOOL 1 //Temperature setting page
+#define KEY_BED_ADD 2
+#define KEY_BED_DEC 3
+#define KEY_HOTEND_ADD 4
+#define KEY_HOTEND_DEC 5
+#define KEY_COOL 6
+#define KEY_TEMP_ENSURE 7
+
+#define KEY_SPEED_TO_TOOL 1 //speed setting page
+#define KEY_FAN_SPEED_ADD 2
+#define KEY_FAN_SPEED_DEC 3
+#define KEY_PRINT_SPEED_ADD 4
+#define KEY_PRINT_SPEED_DEC 5
+#define KEY_SPEED_ENSURE 6
+
+#define KEY_PREPARE_TO_MAIN 1 //PREPARE PAGE TO MAIN
+#define KEY_PREPARE_TO_PreLEVE 2
+#define KEY_PreLEVE_TO_PREPARE 1
+#define KEY_PreLEVE_TO_LEVELING 2
+#define KEY_PreLEVE_TO_ADVANCE 3
+#define KEY_ADVANCE_TO_PreLEVE 1
+#define KEY_LEVEL_ADD 3
+#define KEY_LEVEL_DEC 2
+#define KEY_LEVEL_ENSURE 4
+
+
+#define KEY_PREPARE_TO_PREHEAT 3
+#define KEY_PREHEAT_TO_PREPARE 1
+#define KEY_PREHEAT_PLA 2
+#define KEY_PREHEAT_ABS 3
+
+#define KEY_PREPARE_TO_FILAMENT 4
+#define KEY_FILAMENT_TO_PREPARE 1
+#define KEY_RETREAT 3
+#define KEY_FORWARD 2
+#define KEY_FILAMENT_STOP 4
+
+// SYSTEM PAGE KEY
+
+#define KEY_SYS_TO_MAIN 1
+#define KEY_LANGUAGE 2
+#define KEY_SYS_TO_WIFI 3
+#define KEY_WIFI_TO_SYS 1
+
+#define KEY_BEEP 4
+#define KEY_SYS_TO_ABOUT 5
+#define KEY_ABOUT_TO_SYS 1
+
+#define KEY_SYS_TO_RECORD 6
+#define KEY_RECORD_TO_SYS 1
+#define KEY_RECORD_PaUp 2
+#define KEY_RECORD_PaDn 3
+#define KEY_RECORD_FLASH 4
+
+#define COLOR_RED 0xF800
+#define COLOR_BLUE 0x0210
+
+namespace Anycubic {
+
+ enum language_t : uint8_t { ENG, CHS };
+
+ class DgusTFT;
+ extern DgusTFT ui;
+
+ typedef struct _lcd_info_t {
+ language_t language;
+ bool audio_on;
+ } lcd_info_t;
+
+ class DgusTFT {
+ static printer_state_t printer_state;
+ static paused_state_t pause_state;
+ #if HAS_HOTEND
+ static heater_state_t hotend_state;
+ #endif
+ #if HAS_HEATED_BED
+ static heater_state_t hotbed_state;
+ #endif
+ static char panel_command[MAX_CMND_LEN];
+ static uint8_t command_len;
+ static char selectedfile[MAX_PATH_LEN];
+ static file_menu_t file_menu;
+ static bool data_received;
+ static uint8_t data_buf[DATA_BUF_SIZE];
+ static uint8_t data_index;
+ static uint16_t page_index_last, page_index_last_2;
+ static uint8_t message_index;
+ static uint8_t pop_up_index;
+ static uint32_t key_value;
+ static uint8_t lcd_txtbox_index;
+ static uint8_t lcd_txtbox_page;
+ static int16_t feedrate_back;
+ static language_t ui_language;
+
+ public:
+ DgusTFT();
+
+ static lcd_info_t lcd_info, lcd_info_back;
+ static uint16_t page_index_now;
+
+ static void Startup();
+ static void ParamInit();
+ static void IdleLoop();
+ static void PrinterKilled(FSTR_P,FSTR_P);
+ static void MediaEvent(media_event_t);
+ static void TimerEvent(timer_event_t);
+ static void FilamentRunout();
+ static void ConfirmationRequest(const char * const);
+ static void StatusChange(const char * const);
+ static void PowerLoss();
+ static void PowerLossRecovery();
+ static void HomingStart();
+ static void HomingComplete();
+
+ static void set_descript_color(const uint16_t color, const uint8_t index=lcd_txtbox_index);
+ static void set_language(language_t);
+ static void toggle_language();
+ static void goto_system_page();
+ static void toggle_audio();
+ static void store_changes();
+
+ #if HAS_HOTEND
+ static void send_temperature_hotend(uint32_t addr);
+ #endif
+ #if HAS_HEATED_BED
+ static void send_temperature_bed(uint32_t addr);
+ #endif
+
+ typedef void (*p_fun)();
+ static void page1();
+ static void page2();
+ static void page3();
+ static void page4();
+ static void page5();
+ static void page6();
+ static void page7(); // tool
+ static void page8();
+ static void page9();
+ static void page10(); // fan and print speed
+ static void page11(); // system
+ static void page12();
+ static void page13();
+ static void page14();
+ static void page15();
+ static void page16();
+ static void page17();
+ static void page18();
+ static void page19();
+ static void page20();
+ static void page21();
+ static void page22();
+ static void page23();
+ static void page24();
+ static void page25();
+ static void page26();
+ static void page27();
+ static void page28();
+ static void page29();
+ static void page30();
+ static void page31();
+ static void page32();
+
+ #if HAS_LEVELING
+ static void page33();
+ #endif
+ static void page34();
+ static void page115();
+ static void page117(); // CHS Mute handler
+ static void page124();
+ static void page125();
+ static void page170(); // ENG Mute handler
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ static void page171(); // CHS power outage resume handler
+ static void page173(); // ENG power outage resume handler
+ #endif
+ #if HAS_LEVELING
+ static void page175(); // ENG probe preheating handler
+ static void page176(); // CHS probe preheating handler
+ #endif
+
+ static void page177_to_198();
+ //static void page178_to_181_190_to_193();
+ static void page199_to_200();
+
+ static void page201();
+ static void page202();
+ static void page203();
+ static void page204();
+ static void page205();
+ static void page206();
+
+ static void pop_up_manager();
+
+ static void SendtoTFT(FSTR_P const=nullptr);
+ static void SendtoTFTLN(FSTR_P const=nullptr);
+ static bool ReadTFTCommand();
+ static int8_t Findcmndpos(const char *, const char);
+ static void CheckHeaters();
+ static void SendFileList(int8_t);
+ static void SelectFile();
+ static void ProcessPanelRequest();
+ static void PanelInfo(uint8_t);
+ static void PanelAction(uint8_t);
+ static void PanelProcess(uint8_t);
+
+ static void SendValueToTFT(const uint16_t value, const uint16_t address);
+ static void RequestValueFromTFT(const uint16_t address);
+ static void SendTxtToTFT(const char *pdata, const uint16_t address);
+ static void SendColorToTFT(const uint16_t color, const uint16_t address);
+ static void SendReadNumOfTxtToTFT(const uint8_t number, const uint16_t address);
+ static void ChangePageOfTFT(const uint16_t page_index, const bool no_send=false);
+ static void FakeChangePageOfTFT(const uint16_t page_index);
+ static void LcdAudioSet(const bool audio_on);
+
+ private:
+
+ };
+
+ extern DgusTFT Dgus;
+}
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft_defs.h b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft_defs.h
new file mode 100644
index 0000000000..dc187690e3
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft_defs.h
@@ -0,0 +1,157 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/anycubic_vyper/dgus_defs.h
+ */
+
+#pragma once
+#include "../../../inc/MarlinConfigPre.h"
+
+#define ACDEBUGLEVEL 0 // 0: off, 255: all levels enabled
+
+#if ACDEBUGLEVEL
+ // Bit-masks for selective debug:
+ enum ACDebugMask : uint8_t {
+ AC_INFO = 1,
+ AC_ACTION = 2,
+ AC_FILE = 4,
+ AC_PANEL = 8,
+ AC_MARLIN = 16,
+ AC_SOME = 32,
+ AC_ALL = 64
+ };
+ #define ACDEBUG(mask) ( ((mask) & ACDEBUGLEVEL) == mask ) // Debug flag macro
+#else
+ #define ACDEBUG(mask) false
+#endif
+
+#define TFTSer LCD_SERIAL // Serial interface for TFT panel now uses marlinserial
+#define MAX_FOLDER_DEPTH 4 // Limit folder depth TFT has a limit for the file path
+#define MAX_CMND_LEN 16 * MAX_FOLDER_DEPTH // Maximum Length for a Panel command
+#define MAX_PATH_LEN 16 * MAX_FOLDER_DEPTH // Maximum number of characters in a SD file path
+
+#define AC_HEATER_FAULT_VALIDATION_TIME 5 // number of 1/2 second loops before signalling a heater fault
+#define AC_LOWEST_MESHPOINT_VAL Z_PROBE_LOW_POINT // The lowest value you can set for a single mesh point offset
+
+ // TFT panel commands
+#define AC_msg_sd_card_inserted F("J00")
+#define AC_msg_sd_card_removed F("J01")
+#define AC_msg_no_sd_card F("J02")
+#define AC_msg_usb_connected F("J03")
+#define AC_msg_print_from_sd_card F("J04")
+#define AC_msg_pause F("J05")
+#define AC_msg_nozzle_heating F("J06")
+#define AC_msg_nozzle_heating_done F("J07")
+#define AC_msg_bed_heating F("J08")
+#define AC_msg_bed_heating_done F("J09")
+#define AC_msg_nozzle_temp_abnormal F("J10")
+#define AC_msg_kill_lcd F("J11")
+#define AC_msg_ready F("J12")
+#define AC_msg_low_nozzle_temp F("J13")
+#define AC_msg_print_complete F("J14")
+#define AC_msg_filament_out_alert F("J15")
+#define AC_msg_stop F("J16")
+#define AC_msg_main_board_has_reset F("J17")
+#define AC_msg_paused F("J18")
+#define AC_msg_j19_unknown F("J19")
+#define AC_msg_sd_file_open_success F("J20")
+#define AC_msg_sd_file_open_failed F("J21")
+#define AC_msg_level_monitor_finished F("J22")
+#define AC_msg_filament_out_block F("J23")
+#define AC_msg_probing_not_allowed F("J24")
+#define AC_msg_probing_complete F("J25")
+#define AC_msg_start_probing F("J26")
+#define AC_msg_version F("J27")
+#define AC_msg_bed_temp_abnormal F("J28")
+
+#define MARLIN_msg_probing_point PSTR("Probing Point ")
+#define MARLIN_msg_start_probing PSTR("Probing Point 1/25")
+#define MARLIN_msg_probing_failed PSTR("Probing Failed")
+#define MARLIN_msg_ready PSTR(" Ready.")
+#define MARLIN_msg_print_paused PSTR("Print Paused")
+#define MARLIN_msg_print_aborted PSTR("Print Aborted")
+#define MARLIN_msg_extruder_heating PSTR("E Heating...")
+#define MARLIN_msg_bed_heating PSTR("Bed Heating...")
+
+#define MARLIN_msg_probe_preheat_start PSTR("Probe preheat start")
+#define MARLIN_msg_probe_preheat_stop PSTR("Probe preheat stop")
+
+
+#define MARLIN_msg_nozzle_parked PSTR("Nozzle Parked")
+#define MARLIN_msg_heater_timeout PSTR("Heater Timeout")
+#define MARLIN_msg_reheating PSTR("Reheating...")
+#define MARLIN_msg_reheat_done PSTR("Reheat finished.")
+#define MARLIN_msg_filament_purging PSTR("Filament Purging...")
+#define MARLIN_msg_media_removed PSTR("Media Removed")
+#define MARLIN_msg_special_pause PSTR("PB")
+#define AC_cmnd_auto_unload_filament PSTR("M701") // Use Marlin unload routine
+#define AC_cmnd_auto_load_filament PSTR("M702 M0 PB") // Use Marlin load routing then pause for user to clean nozzle
+
+#define AC_cmnd_manual_load_filament PSTR("M83\nG1 E50 F700\nM82") // replace the manual panel commands with something a little faster
+#define AC_cmnd_manual_unload_filament PSTR("M83\nG1 E-50 F1200\nM82")
+#define AC_cmnd_enable_levelling PSTR("M420 S1 V1")
+#define AC_cmnd_power_loss_recovery PSTR("G28 R5 X Y\nG28 Z") // Lift, home X and Y then home Z when in 'safe' position
+
+namespace Anycubic {
+ enum heater_state_t : uint8_t {
+ AC_heater_off,
+ AC_heater_temp_set,
+ AC_heater_temp_reached
+ };
+
+ enum paused_state_t : uint8_t {
+ AC_paused_heater_timed_out,
+ AC_paused_filament_lack,
+ AC_paused_purging_filament,
+ AC_paused_idle
+ };
+
+ enum printer_state_t : uint8_t {
+ AC_printer_idle,
+ AC_printer_probing,
+ AC_printer_printing,
+ AC_printer_pausing,
+ AC_printer_paused,
+ AC_printer_stopping,
+ AC_printer_stopping_from_media_remove,
+ AC_printer_resuming_from_power_outage
+ };
+
+ enum timer_event_t : uint8_t {
+ AC_timer_started,
+ AC_timer_paused,
+ AC_timer_stopped
+ };
+
+ enum media_event_t : uint8_t {
+ AC_media_inserted,
+ AC_media_removed,
+ AC_media_error
+ };
+ enum file_menu_t : uint8_t {
+ AC_menu_file,
+ AC_menu_command,
+ AC_menu_change_to_file,
+ AC_menu_change_to_command
+ };
+}
diff --git a/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp b/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp
new file mode 100644
index 0000000000..142f438861
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp
@@ -0,0 +1,152 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/anycubic_vyper/vyper_extui.cpp
+ *
+ * Anycubic Dgus TFT support for Marlin
+ */
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_VYPER)
+
+#include "../ui_api.h"
+#include "dgus_tft.h"
+
+using namespace Anycubic;
+
+namespace ExtUI {
+
+ void onStartup() { Dgus.Startup(); }
+
+ void onIdle() { Dgus.IdleLoop(); }
+
+ void onPrinterKilled(FSTR_P const error, FSTR_P const component) {
+ Dgus.PrinterKilled(error, component);
+ }
+
+ void onMediaInserted() { Dgus.MediaEvent(AC_media_inserted); }
+ void onMediaError() { Dgus.MediaEvent(AC_media_error); }
+ void onMediaRemoved() { Dgus.MediaEvent(AC_media_removed); }
+
+ void onPlayTone(const uint16_t frequency, const uint16_t duration) {
+ #if ENABLED(SPEAKER)
+ ::tone(BEEPER_PIN, frequency, duration);
+ #endif
+ }
+
+ void onPrintTimerStarted() { Dgus.TimerEvent(AC_timer_started); }
+ void onPrintTimerPaused() { Dgus.TimerEvent(AC_timer_paused); }
+ void onPrintTimerStopped() { Dgus.TimerEvent(AC_timer_stopped); }
+ void onPrintDone() {}
+
+ void onFilamentRunout(const extruder_t) { Dgus.FilamentRunout(); }
+
+ void onUserConfirmRequired(const char * const msg) { Dgus.ConfirmationRequest(msg); }
+ void onStatusChanged(const char * const msg) { Dgus.StatusChange(msg); }
+
+ void onHomingStart() { Dgus.HomingStart(); }
+ void onHomingDone() { Dgus.HomingComplete(); }
+
+ void onFactoryReset() {
+ Dgus.page_index_now = 121;
+ Dgus.lcd_info.audio_on = DISABLED(SPEAKER);
+ }
+
+ void onStoreSettings(char *buff) {
+ // Called when saving to EEPROM (i.e. M500). If the ExtUI needs
+ // permanent data to be stored, it can write up to eeprom_data_size bytes
+ // into buff.
+
+ static_assert(sizeof(Dgus.lcd_info) <= ExtUI::eeprom_data_size);
+ memcpy(buff, &Dgus.lcd_info, sizeof(Dgus.lcd_info));
+ }
+
+ void onLoadSettings(const char *buff) {
+ // Called while loading settings from EEPROM. If the ExtUI
+ // needs to retrieve data, it should copy up to eeprom_data_size bytes
+ // from buff
+
+ static_assert(sizeof(Dgus.lcd_info) <= ExtUI::eeprom_data_size);
+ memcpy(&Dgus.lcd_info, buff, sizeof(Dgus.lcd_info));
+ memcpy(&Dgus.lcd_info_back, buff, sizeof(Dgus.lcd_info_back));
+ }
+
+ void onPostprocessSettings() {
+ // Called after loading or resetting stored settings
+ Dgus.ParamInit();
+ Dgus.PowerLoss();
+ }
+
+ void onSettingsStored(const bool success) {
+ // Called after the entire EEPROM has been written,
+ // whether successful or not.
+ }
+
+ void onSettingsLoaded(const bool success) {
+ // Called after the entire EEPROM has been read,
+ // whether successful or not.
+ }
+
+ #if HAS_MESH
+ void onLevelingStart() {}
+ void onLevelingDone() {}
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) {
+ // Called when any mesh points are updated
+ //SERIAL_ECHOLNPGM("onMeshUpdate() x:", xpos, " y:", ypos, " z:", zval);
+ }
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const probe_state_t state) {
+ // Called to indicate a special condition
+ //SERIAL_ECHOLNPGM("onMeshUpdate() x:", xpos, " y:", ypos, " state:", state);
+ }
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ // Called when power-loss is enabled/disabled
+ void onSetPowerLoss(const bool) { Dgus.PowerLoss(); }
+ // Called when power-loss state is detected
+ void onPowerLoss() { /* handled internally */ }
+ // Called on resume from power-loss
+ void onPowerLossResume() { Dgus.PowerLossRecovery(); }
+ #endif
+
+ #if HAS_PID_HEATING
+ void onPidTuning(const result_t rst) {
+ // Called for temperature PID tuning result
+ switch (rst) {
+ case PID_STARTED: break;
+ case PID_BAD_HEATER_ID: break;
+ case PID_TEMP_TOO_HIGH: break;
+ case PID_TUNING_TIMEOUT: break;
+ case PID_DONE: break;
+ }
+ }
+ #endif
+
+ void onSteppersDisabled() {}
+ void onSteppersEnabled() {}
+}
+
+#endif // ANYCUBIC_LCD_VYPER
diff --git a/Marlin/src/lcd/extui/ia_creality/creality_extui.cpp b/Marlin/src/lcd/extui/ia_creality/creality_extui.cpp
index d92517578f..1f40f2a037 100644
--- a/Marlin/src/lcd/extui/ia_creality/creality_extui.cpp
+++ b/Marlin/src/lcd/extui/ia_creality/creality_extui.cpp
@@ -1580,7 +1580,7 @@ namespace ExtUI {
else if (recdat.data[0] == 4) { // Page Up
injectCommands(F("M22\nM21"));
}
- else if (recdat.data[0] == 0) { // return to main page
+ else if (recdat.data[0] == 0) { // return to main page
InforShowStatus = true;
TPShowStatus = false;
}
diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp
index 1075816c43..5c27b345c4 100644
--- a/Marlin/src/lcd/extui/ui_api.cpp
+++ b/Marlin/src/lcd/extui/ui_api.cpp
@@ -112,9 +112,9 @@
namespace ExtUI {
static struct {
- uint8_t printer_killed : 1;
+ bool printer_killed : 1;
#if ENABLED(JOYSTICK)
- uint8_t jogging : 1;
+ bool jogging : 1;
#endif
} flags;
@@ -926,7 +926,7 @@ namespace ExtUI {
void setMeshPoint(const xy_uint8_t &pos, const_float_t zoff) {
if (WITHIN(pos.x, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(pos.y, 0, (GRID_MAX_POINTS_Y) - 1)) {
bedlevel.z_values[pos.x][pos.y] = zoff;
- TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
+ TERN_(ABL_BILINEAR_SUBDIVISION, bedlevel.refresh_bed_level());
}
}
@@ -1127,6 +1127,13 @@ namespace ExtUI {
#endif
}
+ void onSurviveInKilled() {
+ thermalManager.disable_all_heaters();
+ flags.printer_killed = 0;
+ marlin_state = MF_RUNNING;
+ //SERIAL_ECHOLNPGM("survived at: ", millis());
+ }
+
FileList::FileList() { refresh(); }
void FileList::refresh() { num_files = 0xFFFF; }
diff --git a/Marlin/src/lcd/extui/ui_api.h b/Marlin/src/lcd/extui/ui_api.h
index 98441ccdd9..d9594bace6 100644
--- a/Marlin/src/lcd/extui/ui_api.h
+++ b/Marlin/src/lcd/extui/ui_api.h
@@ -45,6 +45,7 @@
#include "../../inc/MarlinConfig.h"
#include "../marlinui.h"
#include "../../gcode/gcode.h"
+
#if M600_PURGE_MORE_RESUMABLE
#include "../../feature/pause.h"
#endif
@@ -406,6 +407,7 @@ namespace ExtUI {
void onMediaRemoved();
void onPlayTone(const uint16_t frequency, const uint16_t duration);
void onPrinterKilled(FSTR_P const error, FSTR_P const component);
+ void onSurviveInKilled();
void onPrintTimerStarted();
void onPrintTimerPaused();
void onPrintTimerStopped();
diff --git a/Marlin/src/lcd/tft/ui_320x240.cpp b/Marlin/src/lcd/tft/ui_320x240.cpp
index e8bec7e1a7..11e4730239 100644
--- a/Marlin/src/lcd/tft/ui_320x240.cpp
+++ b/Marlin/src/lcd/tft/ui_320x240.cpp
@@ -446,7 +446,7 @@ void MarlinUI::draw_status_screen() {
#else
256, 130
#endif
- , menu_main, imgSettings
+ , menu_main, imgSettings
);
#if ENABLED(SDSUPPORT)
const bool cm = card.isMounted(), pa = printingIsActive();
diff --git a/Marlin/src/libs/buzzer.h b/Marlin/src/libs/buzzer.h
index cd8e17d004..aa4d48ae5d 100644
--- a/Marlin/src/libs/buzzer.h
+++ b/Marlin/src/libs/buzzer.h
@@ -27,7 +27,9 @@
#include "circularqueue.h"
- #define TONE_QUEUE_LENGTH 4
+ #ifndef TONE_QUEUE_LENGTH
+ #define TONE_QUEUE_LENGTH 4
+ #endif
/**
* @brief Tone structure
diff --git a/Marlin/src/libs/numtostr.cpp b/Marlin/src/libs/numtostr.cpp
index 4cc40a96d1..2938229a7a 100644
--- a/Marlin/src/libs/numtostr.cpp
+++ b/Marlin/src/libs/numtostr.cpp
@@ -423,3 +423,34 @@ const char* ftostr52sp(const_float_t f) {
}
return &conv[1];
}
+
+// Convert unsigned 16bit int to string 1, 12, 123 format, capped at 999
+const char* utostr3(const uint16_t x) {
+ return i16tostr3left(_MIN(x, 999U));
+}
+
+// Convert signed float to space-padded string with 1.23, 12.34, 123.45 format
+const char* ftostr52sprj(const_float_t f) {
+ long i = INTFLOAT(f, 2);
+ LIMIT(i, -99999, 99999); // cap to -999.99 - 999.99 range
+ if (WITHIN(i, -999, 999)) { // -9.99 - 9.99 range
+ conv[1] = conv[2] = ' '; // default to ' ' for smaller numbers
+ conv[3] = MINUSOR(i, ' ');
+ }
+ else if (WITHIN(i, -9999, 9999)) { // -99.99 - 99.99 range
+ conv[1] = ' ';
+ conv[2] = MINUSOR(i, ' ');
+ conv[3] = DIGIMOD(i, 1000);
+ }
+ else { // -999.99 - 999.99 range
+ conv[1] = MINUSOR(i, ' ');
+ conv[2] = DIGIMOD(i, 10000);
+ conv[3] = DIGIMOD(i, 1000);
+ }
+ conv[4] = DIGIMOD(i, 100); // always convert last 3 digits
+ conv[5] = '.';
+ conv[6] = DIGIMOD(i, 10);
+ conv[7] = DIGIMOD(i, 1);
+
+ return &conv[1];
+}
diff --git a/Marlin/src/libs/numtostr.h b/Marlin/src/libs/numtostr.h
index 0c8ce0f79a..31e8db0048 100644
--- a/Marlin/src/libs/numtostr.h
+++ b/Marlin/src/libs/numtostr.h
@@ -129,3 +129,9 @@ FORCE_INLINE const char* ftostr3(const_float_t x) { return i16tostr3rj(int16_t(x
// Convert float to rj string with 1234, _123, -123, __12, _-12, ___1, or __-1 format
FORCE_INLINE const char* ftostr4sign(const_float_t x) { return i16tostr4signrj(int16_t(x + (x < 0 ? -0.5f : 0.5f))); }
#endif
+
+// Convert unsigned int to string 1, 12, 123 format, capped at 999
+const char* utostr3(const uint16_t x);
+
+// Convert signed float to space-padded string with 1.23, 12.34, 123.45 format
+const char* ftostr52sprj(const_float_t f);
diff --git a/Marlin/src/pins/gd32f1/env_validate.h b/Marlin/src/pins/gd32f1/env_validate.h
new file mode 100644
index 0000000000..4b07cce4e5
--- /dev/null
+++ b/Marlin/src/pins/gd32f1/env_validate.h
@@ -0,0 +1,32 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 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
+
+#if NOT_TARGET(__STM32F1__, STM32F1)
+ #if DISABLED(ALLOW_STM32F4)
+ #error "Oops! Select an STM32F1 board in 'Tools > Board.'"
+ #elif NOT_TARGET(STM32F4)
+ #error "Oops! Select an STM32F4 board in 'Tools > Board.'"
+ #endif
+#endif
+
+#undef ALLOW_STM32F4
diff --git a/Marlin/src/pins/gd32f1/pins_TRIGORILLA_V006.h b/Marlin/src/pins/gd32f1/pins_TRIGORILLA_V006.h
new file mode 100644
index 0000000000..7b8c412bed
--- /dev/null
+++ b/Marlin/src/pins/gd32f1/pins_TRIGORILLA_V006.h
@@ -0,0 +1,152 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2023 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 "env_validate.h"
+
+#define BOARD_INFO_NAME "TRIGORILLA_V006"
+#define DEFAULT_MACHINE_NAME "GD32F103"
+
+#define BOARD_NO_NATIVE_USB
+
+// Release PA13 from SWD for CASE_LIGHT_PIN
+#define DISABLE_DEBUG
+#define DISABLE_JTAG
+
+//
+// EEPROM
+//
+#define FLASH_EEPROM_EMULATION
+#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
+
+//
+// Limit Switches
+//
+#define X_MIN_PIN PA7
+#define X_MAX_PIN PC6
+#define Y_MIN_PIN PC5
+#define Y_MAX_PIN -1
+#define Z_MIN_PIN PB2
+#define Z_MAX_PIN -1
+
+//
+// Steppers
+//
+#define X_ENABLE_PIN PC3
+#define X_STEP_PIN PC2
+#define X_DIR_PIN PB9
+
+#define Y_ENABLE_PIN PC13
+#define Y_STEP_PIN PB8
+#define Y_DIR_PIN PB7
+
+#define Z_ENABLE_PIN PC14
+#define Z_STEP_PIN PB6
+#define Z_DIR_PIN PB5
+
+#define E0_ENABLE_PIN PA15
+#define E0_STEP_PIN PB4
+#define E0_DIR_PIN PB3
+
+#define E1_ENABLE_PIN PC15
+#define E1_STEP_PIN PC0
+#define E1_DIR_PIN PC1
+
+//
+// Temperature Sensors
+//
+#define TEMP_0_PIN PC4 // T0
+#define TEMP_1_PIN -1 // T1 PA6 used for power loss
+#define TEMP_BED_PIN PB0 // TB
+
+//
+// Heaters
+//
+#define HEATER_0_PIN PA1 // H0
+#define HEATER_1_PIN PA8 // H1
+#define HEATER_BED_PIN PA4 // HB
+
+//
+// Fans
+//
+#define FAN_PIN PA0 // FAN
+#define FAN1_PIN PA14 // Connected to +24V
+#define FAN2_PIN -1 // PB1, auto fan for E0
+#define CONTROLLER_FAN_PIN FAN1_PIN
+
+//
+// Misc
+//
+#define BEEPER_PIN PB15
+#define LED_PIN -1
+#define POWER_LOSS_PIN PA6
+#define FIL_RUNOUT_PIN PA5
+#define CASE_LIGHT_PIN PA13
+#define POWER_MONITOR_VOLTAGE_PIN PA6
+
+#define AUTO_LEVEL_TX_PIN PB13
+#define AUTO_LEVEL_RX_PIN PB12
+
+#ifndef Z_MIN_PROBE_PIN
+ #define Z_MIN_PROBE_PIN AUTO_LEVEL_RX_PIN
+#endif
+
+//
+// SD Card
+//
+#define SD_DETECT_PIN PC7
+
+#ifndef SDIO_SUPPORT
+ #define SDIO_SUPPORT
+#endif
+#if ENABLED(SDIO_SUPPORT)
+ //
+ // SPI
+ //
+ #define SPI_DEVICE -1
+ #define SCK_PIN -1
+ #define MISO_PIN -1
+ #define MOSI_PIN -1
+ #define SS_PIN -1
+
+ //
+ // SDIO
+ //
+ #define SDIO_READ_RETRIES 16
+ #define SDIO_D0_PIN PC8
+ #define SDIO_D1_PIN PC9
+ #define SDIO_D2_PIN PC10
+ #define SDIO_D3_PIN PC11
+ #define SDIO_CK_PIN PC12
+ #define SDIO_CMD_PIN PD2
+
+#else
+
+ #undef SDSS
+ #define SDSS PC11 // SDIO_D3_PIN
+ #define SS_PIN SDSS
+ #define SCK_PIN PC12 // SDIO_CK_PIN
+ #define MISO_PIN PC8 // SDIO_D0_PIN
+ #define MOSI_PIN PD2 // SDIO_CMD_PIN
+ #define SOFTWARE_SPI
+
+#endif
diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h
index 62ddba06f5..bead9d1f06 100644
--- a/Marlin/src/pins/pins.h
+++ b/Marlin/src/pins/pins.h
@@ -629,6 +629,8 @@
#include "stm32f1/pins_PANDA_PI_V29.h" // STM32F103RCT6 env:PANDA_PI_V29
#elif MB(SOVOL_V131)
#include "stm32f1/pins_SOVOL_V131.h" // GD32F1 env:GD32F103RET6_sovol_maple
+#elif MB(TRIGORILLA_V006)
+ #include "gd32f1/pins_TRIGORILLA_V006.h" // GD32F103 env:trigorilla_v006
//
// ARM Cortex-M4F
diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp
index fb2721a2b2..8a4fa743d4 100644
--- a/Marlin/src/sd/cardreader.cpp
+++ b/Marlin/src/sd/cardreader.cpp
@@ -420,6 +420,40 @@ void CardReader::ls(const uint8_t lsflags) {
SERIAL_EOL();
}
+ void CardReader::getLongPath(char * const pathLong, char * const pathShort) {
+
+ int i, pathLen = strlen(pathShort);
+ char bufShort[FILENAME_LENGTH] = { '\0' };
+ strcpy_P(bufShort, pathShort);
+
+ // Zero out slashes to make segments
+ for (i = 0; i < pathLen; i++) if (bufShort[i] == '/') bufShort[i] = '\0';
+
+ SdFile diveDir = root; // start from the root for segment 1
+ for (i = 0; i < pathLen;) {
+
+ if (bufShort[i] == '\0') i++; // move past a single nul
+
+ char *segment = &bufShort[i]; // The segment after most slashes
+
+ // If a segment is empty (extra-slash) then exit
+ if (!*segment) break;
+
+ //SERIAL_ECHOLNPGM("Looking for segment: ", segment);
+
+ // Find the item, setting the long filename
+ diveDir.rewind();
+ selectByName(diveDir, segment);
+ diveDir.close();
+
+ if (longFilename[0]) {
+ strncpy_P(pathLong, longFilename, 63);
+ pathLong[63] = '\0';
+ break;
+ }
+ }
+ }
+
#endif // LONG_FILENAME_HOST_SUPPORT
//
diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h
index 86acb1b862..47e3c66e47 100644
--- a/Marlin/src/sd/cardreader.h
+++ b/Marlin/src/sd/cardreader.h
@@ -146,6 +146,7 @@ public:
static char* longest_filename() { return longFilename[0] ? longFilename : filename; }
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
static void printLongPath(char * const path); // Used by M33
+ static void getLongPath(char * const pathLong, char * const pathShort); // Used by anycubic_vyper
#endif
// Working Directory for SD card menu
diff --git a/ini/features.ini b/ini/features.ini
index 35b6959fd9..11ffca6ba6 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -81,6 +81,7 @@ HAS_MENU_TOUCH_SCREEN = src_filter=+
HAS_MENU_UBL = src_filter=+
ANYCUBIC_LCD_CHIRON = src_filter=+
+ANYCUBIC_LCD_VYPER = src_filter=+
ANYCUBIC_LCD_I3MEGA = src_filter=+
HAS_DGUS_LCD_CLASSIC = src_filter=+
DGUS_LCD_UI_RELOADED = src_filter=+
diff --git a/ini/stm32f1.ini b/ini/stm32f1.ini
index 1adc83a8f9..783d05fab4 100644
--- a/ini/stm32f1.ini
+++ b/ini/stm32f1.ini
@@ -134,6 +134,16 @@ monitor_speed = 115200
debug_tool = jlink
upload_protocol = jlink
+#
+# Trigorilla V0.0.6 (GD32F103)
+# modified version of env:STM32F103RE_creality
+#
+[env:trigorilla_v006]
+extends = STM32F103Rx_creality
+board = genericSTM32F103RE
+board_build.offset = 0x8000
+board_upload.offset_address = 0x08008000
+
#
# Creality (STM32F103Rx)
# With custom upload to SD via Marlin with binary protocol.
diff --git a/platformio.ini b/platformio.ini
index f8a8988ef8..9fbc589d2e 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -81,6 +81,7 @@ default_src_filter = + - - + -
-
-
+ -
-
- - - - -
-