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 = + - - + - - - + - - - - - - - -