From e8701195e66f2d27ffe17fb514eae8173795aaf7 Mon Sep 17 00:00:00 2001
From: Georgiy Bondarenko <69736697+nehilo@users.noreply.github.com>
Date: Thu, 4 Mar 2021 22:54:23 +0500
Subject: Initial commit
---
.../extui/lib/anycubic_chiron/FileNavigator.cpp | 164 ++++
.../lcd/extui/lib/anycubic_chiron/FileNavigator.h | 56 ++
Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp | 62 ++
Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h | 224 ++++++
.../lcd/extui/lib/anycubic_chiron/chiron_tft.cpp | 885 +++++++++++++++++++++
.../src/lcd/extui/lib/anycubic_chiron/chiron_tft.h | 77 ++
.../extui/lib/anycubic_chiron/chiron_tft_defs.h | 151 ++++
7 files changed, 1619 insertions(+)
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
(limited to 'Marlin/src/lcd/extui/lib/anycubic_chiron')
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
new file mode 100644
index 0000000..19f8ec8
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
@@ -0,0 +1,164 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/FileNavigator.cpp
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+/***************************************************************************
+ * 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_CHIRON)
+
+#include "FileNavigator.h"
+#include "chiron_tft.h"
+
+using namespace ExtUI;
+
+namespace Anycubic {
+
+ FileNavigator filenavigator;
+
+ 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() { 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 = 4;
+ 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 < 4 ? 0 : currentindex - files;
+ }
+ lastindex = index;
+
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("index=", index, " currentindex=", currentindex);
+ #endif
+
+ if (currentindex == 0 && folderdepth > 0) { // Add a link to go up a folder
+ TFTSer.println("<<");
+ TFTSer.println("..");
+ files--;
+ }
+
+ for (uint16_t seek = currentindex; seek < currentindex + files; seek++) {
+ if (filelist.seek(seek)) {
+ sendFile();
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
+ #endif
+ }
+ }
+ }
+
+ 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()) {
+ //TFTSer.print(currentfoldername);
+ TFTSer.println(filelist.shortFilename());
+ TFTSer.print(filelist.shortFilename());
+ TFTSer.println("/");
+ }
+ else {
+ // Logical Name
+ TFTSer.print("/");
+ if (folderdepth > 0) TFTSer.print(currentfoldername);
+
+ TFTSer.println(filelist.shortFilename());
+
+ // Display Name
+ TFTSer.println(filelist.longFilename());
+ }
+ }
+ void FileNavigator::changeDIR(char *folder) {
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("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_ECHOLNPAIR("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
+ #endif
+ }
+
+ char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
+}
+
+#endif // ANYCUBIC_LCD_CHIRON
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
new file mode 100644
index 0000000..8e03614
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
@@ -0,0 +1,56 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/FileNavigator.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#include "chiron_tft_defs.h"
+#include "../../ui_api.h"
+
+using namespace ExtUI;
+
+namespace Anycubic {
+ class FileNavigator {
+ public:
+ FileNavigator();
+ void reset();
+ void getFiles(uint16_t);
+ void upDIR();
+ void changeDIR(char *);
+ void sendFile();
+ void refresh();
+ char * getCurrentFolderName();
+ private:
+ static FileList filelist;
+ 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/lib/anycubic_chiron/Tunes.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp
new file mode 100644
index 0000000..f09c4db
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp
@@ -0,0 +1,62 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/Tunes.cpp
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+/***********************************************************************
+ * 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_CHIRON)
+
+#include "Tunes.h"
+#include "../../ui_api.h"
+
+namespace Anycubic {
+
+ void PlayTune(uint8_t beeperPin, const uint16_t *tune, 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_CHIRON
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h
new file mode 100644
index 0000000..1bafec4
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h
@@ -0,0 +1,224 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/Tunes.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+/**************************************************************************
+ * 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(uint8_t beeperPin, const uint16_t *tune, 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/lib/anycubic_chiron/chiron_tft.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
new file mode 100644
index 0000000..61057b5
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
@@ -0,0 +1,885 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/chiron_tft.cpp
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+
+#include "chiron_tft.h"
+#include "Tunes.h"
+#include "FileNavigator.h"
+
+#include "../../../../gcode/queue.h"
+#include "../../../../sd/cardreader.h"
+#include "../../../../libs/numtostr.h"
+#include "../../../../MarlinCore.h"
+
+namespace Anycubic {
+
+ printer_state_t ChironTFT::printer_state;
+ paused_state_t ChironTFT::pause_state;
+ heater_state_t ChironTFT::hotend_state;
+ heater_state_t ChironTFT::hotbed_state;
+ xy_uint8_t ChironTFT::selectedmeshpoint;
+ char ChironTFT::selectedfile[MAX_PATH_LEN];
+ char ChironTFT::panel_command[MAX_CMND_LEN];
+ uint8_t ChironTFT::command_len;
+ float ChironTFT::live_Zoffset;
+ file_menu_t ChironTFT::file_menu;
+
+ ChironTFT Chiron;
+
+ ChironTFT::ChironTFT(){}
+
+ void ChironTFT::Startup() {
+ selectedfile[0] = '\0';
+ panel_command[0] = '\0';
+ command_len = 0;
+ printer_state = AC_printer_idle;
+ pause_state = AC_paused_idle;
+ hotend_state = AC_heater_off;
+ hotbed_state = AC_heater_off;
+ 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
+
+ TFTSer.begin(115200);
+
+ // Signal Board has reset
+ SendtoTFTLN(AC_msg_main_board_has_reset);
+
+ safe_delay(200);
+
+ // Enable leveling 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_leveling);
+
+ // Startup tunes are defined in Tunes.h
+ //PlayTune(BEEPER_PIN, Anycubic_PowerOn, 1);
+ PlayTune(BEEPER_PIN, GB_PowerOn, 1);
+ #if ACDEBUGLEVEL
+ SERIAL_ECHOLNPAIR("AC Debug Level ", ACDEBUGLEVEL);
+ #endif
+ SendtoTFTLN(AC_msg_ready);
+ }
+
+ void ChironTFT::IdleLoop() {
+ if (ReadTFTCommand()) {
+ ProcessPanelRequest();
+ command_len = 0;
+ }
+ CheckHeaters();
+ }
+
+ void ChironTFT::PrinterKilled(PGM_P error,PGM_P component) {
+ SendtoTFTLN(AC_msg_kill_lcd);
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("PrinterKilled()\nerror: ", error , "\ncomponent: ", component);
+ #endif
+ }
+
+ void ChironTFT::MediaEvent(media_event_t event) {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("ProcessMediaStatus() ", event);
+ #endif
+ switch (event) {
+ case AC_media_inserted:
+ SendtoTFTLN(AC_msg_sd_card_inserted);
+ break;
+
+ case AC_media_removed:
+ SendtoTFTLN(AC_msg_sd_card_removed);
+ break;
+
+ case AC_media_error:
+ SendtoTFTLN(AC_msg_no_sd_card);
+ break;
+ }
+ }
+
+ void ChironTFT::TimerEvent(timer_event_t event) {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("TimerEvent() ", event);
+ SERIAL_ECHOLNPAIR("Printer State: ", printer_state);
+ #endif
+
+ switch (event) {
+ case AC_timer_started: {
+ live_Zoffset = 0.0; // reset print offset
+ 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) {
+ printer_state = AC_printer_stopping;
+ SendtoTFTLN(AC_msg_print_complete);
+ }
+ setSoftEndstopState(true); // enable endstops
+ } break;
+ }
+ }
+
+ void ChironTFT::FilamentRunout() {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("FilamentRunout() printer_state ", printer_state);
+ #endif
+ // 1 Signal filament out
+ SendtoTFTLN(isPrintingFromMedia() ? AC_msg_filament_out_alert : AC_msg_filament_out_block);
+ //printer_state = AC_printer_filament_out;
+ PlayTune(BEEPER_PIN, FilamentOut, 1);
+ }
+
+ void ChironTFT::ConfirmationRequest(const char * const msg) {
+ // M108 continue
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("ConfirmationRequest() ", msg, " printer_state:", printer_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) {
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ printer_state = AC_printer_paused;
+ }
+ } break;
+
+ case AC_printer_resuming_from_power_outage:
+ 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) {
+ 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
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+
+ void ChironTFT::StatusChange(const char * const msg) {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("StatusChange() ", msg);
+ SERIAL_ECHOLNPAIR("printer_state:", printer_state);
+ #endif
+ bool msg_matched = false;
+ // The only way to get printer status is to parse messages
+ // Use the state to minimise the work we do here.
+ switch (printer_state) {
+ case AC_printer_probing: {
+ // If probing completes ok save the mesh and park
+ // Ignore the custom machine name
+ if (strcmp_P(msg + strlen(CUSTOM_MACHINE_NAME), MARLIN_msg_ready) == 0) {
+ injectCommands_P(PSTR("M500\nG27"));
+ SendtoTFTLN(AC_msg_probing_complete);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ // If probing fails dont 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_P(PSTR("G1 Z50 F500"));
+ SendtoTFTLN(AC_msg_probing_complete);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ } break;
+
+ case AC_printer_printing: {
+ if (strcmp_P(msg, MARLIN_msg_reheating) == 0) {
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ msg_matched = true;
+ }
+ } break;
+
+ case AC_printer_pausing: {
+ if (strcmp_P(msg, MARLIN_msg_print_paused) == 0) {
+ SendtoTFTLN(AC_msg_paused);
+ printer_state = AC_printer_paused;
+ pause_state = AC_paused_idle;
+ msg_matched = true;
+ }
+ } break;
+
+ case AC_printer_stopping: {
+ if (strcmp_P(msg, MARLIN_msg_print_aborted) == 0) {
+ SendtoTFTLN(AC_msg_stop);
+ 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 (strcmp_P(msg, MARLIN_msg_extruder_heating) == 0) {
+ SendtoTFTLN(AC_msg_nozzle_heating);
+ hotend_state = AC_heater_temp_set;
+ }
+ else if (strcmp_P(msg, MARLIN_msg_bed_heating) == 0) {
+ SendtoTFTLN(AC_msg_bed_heating);
+ hotbed_state = AC_heater_temp_set;
+ }
+ }
+ }
+
+ void ChironTFT::PowerLossRecovery() {
+ printer_state = AC_printer_resuming_from_power_outage; // Play tune to notify user we can recover.
+ PlayTune(BEEPER_PIN, SOS, 1);
+ SERIAL_ECHOLNPGM("Resuming from power outage...");
+ SERIAL_ECHOLNPGM("Select SD file then press resume");
+ }
+
+ void ChironTFT::SendtoTFT(PGM_P str) { // A helper to print PROGMEN string to the panel
+ #if ACDEBUG(AC_SOME)
+ serialprintPGM(str);
+ #endif
+ while (const char c = pgm_read_byte(str++)) TFTSer.print(c);
+ }
+
+ void ChironTFT::SendtoTFTLN(PGM_P str = nullptr) {
+ if (str) {
+ #if ACDEBUG(AC_SOME)
+ SERIAL_ECHOPGM("> ");
+ #endif
+ SendtoTFT(str);
+ #if ACDEBUG(AC_SOME)
+ SERIAL_EOL();
+ #endif
+ }
+ TFTSer.println("");
+ }
+
+ bool ChironTFT::ReadTFTCommand() {
+ bool command_ready = false;
+ while(TFTSer.available() > 0 && command_len < MAX_CMND_LEN) {
+ panel_command[command_len] = TFTSer.read();
+ if (panel_command[command_len] == '\n') {
+ command_ready = true;
+ break;
+ }
+ command_len++;
+ }
+
+ if (command_ready) {
+ panel_command[command_len] = 0x00;
+ #if ACDEBUG(AC_ALL)
+ SERIAL_ECHOLNPAIR("< ", panel_command);
+ #endif
+ #if ACDEBUG(AC_SOME)
+ // Ignore status request commands
+ uint8_t req = atoi(&panel_command[1]);
+ if (req > 7 && req != 20) {
+ SERIAL_ECHOLNPAIR("> ", panel_command);
+ SERIAL_ECHOLNPAIR("printer_state:", printer_state);
+ }
+ #endif
+ }
+ return command_ready;
+ }
+
+ int8_t ChironTFT::Findcmndpos(const char * buff, char q) {
+ int8_t pos = 0;
+ do { if (buff[pos] == q) return pos; } while(++pos < MAX_CMND_LEN);
+ return -1;
+ }
+
+ void ChironTFT::CheckHeaters() {
+ uint8_t faultDuration = 0;
+ float temp = 0;
+
+ // if the hotend temp is abnormal, confirm state before signalling panel
+ temp = getActualTemp_celsius(E0);
+ while (!WITHIN(temp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP)) {
+ faultDuration++;
+ if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
+ SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+ SERIAL_ECHOLNPAIR("Extruder temp abnormal! : ", temp);
+ break;
+ }
+ delay_ms(500);
+ temp = getActualTemp_celsius(E0);
+ }
+
+ // If the hotbed temp is abnormal, confirm state before signaling panel
+ faultDuration = 0;
+ temp = getActualTemp_celsius(BED);
+ while (!WITHIN(temp, BED_MINTEMP, BED_MAXTEMP)) {
+ faultDuration++;
+ if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
+ SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+ SERIAL_ECHOLNPAIR("Bed temp abnormal! : ", temp);
+ break;
+ }
+ delay_ms(500);
+ temp = getActualTemp_celsius(E0);
+ }
+
+ // 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;
+ }
+ }
+ }
+
+ void ChironTFT::SendFileList(int8_t startindex) {
+ // Respond to panel request for 4 files starting at index
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("## SendFileList ## ", startindex);
+ #endif
+ SendtoTFTLN(PSTR("FN "));
+ filenavigator.getFiles(startindex);
+ SendtoTFTLN(PSTR("END"));
+ }
+
+ void ChironTFT::SelectFile() {
+ strncpy(selectedfile, panel_command + 4, command_len - 4);
+ selectedfile[command_len - 5] = '\0';
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR_F(" 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 ChironTFT::InjectCommandandWait(PGM_P cmd) {
+ //injectCommands_P(cmnd); queue.enqueue_now_P(cmd);
+ //SERIAL_ECHOLN(PSTR("Inject>"));
+ }
+
+ void ChironTFT::ProcessPanelRequest() {
+ // 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();
+ }
+
+ void ChironTFT::PanelInfo(uint8_t req) {
+ // information requests A0-A8 and A33
+ switch (req) {
+ case 0: // A0 Get HOTEND Temp
+ SendtoTFT(PSTR("A0V "));
+ TFTSer.println(getActualTemp_celsius(E0));
+ break;
+
+ case 1: // A1 Get HOTEND Target Temp
+ SendtoTFT(PSTR("A1V "));
+ TFTSer.println(getTargetTemp_celsius(E0));
+ break;
+
+ case 2: // A2 Get BED Temp
+ SendtoTFT(PSTR("A2V "));
+ TFTSer.println(getActualTemp_celsius(BED));
+ break;
+
+ case 3: // A3 Get BED Target Temp
+ SendtoTFT(PSTR("A3V "));
+ TFTSer.println(getTargetTemp_celsius(BED));
+ break;
+
+ case 4: // A4 Get FAN Speed
+ SendtoTFT(PSTR("A4V "));
+ TFTSer.println(getActualFan_percent(FAN0));
+ break;
+
+ case 5: // A5 Get Current Coordinates
+ SendtoTFT(PSTR("A5V X: "));
+ TFTSer.print(getAxisPosition_mm(X));
+ SendtoTFT(PSTR(" Y: "));
+ TFTSer.print(getAxisPosition_mm(Y));
+ SendtoTFT(PSTR(" Z: "));
+ TFTSer.println(getAxisPosition_mm(Z));
+ break;
+
+ case 6: // A6 Get printing progress
+ if (isPrintingFromMedia()) {
+ SendtoTFT(PSTR("A6V "));
+ TFTSer.println(ui8tostr2(getProgress_percent()));
+ }
+ else
+ SendtoTFTLN(PSTR("A6V ---"));
+ break;
+
+ case 7: { // A7 Get Printing Time
+ uint32_t time = getProgress_seconds_elapsed() / 60;
+ SendtoTFT(PSTR("A7V "));
+ TFTSer.print(ui8tostr2(time / 60));
+ SendtoTFT(PSTR(" H "));
+ TFTSer.print(ui8tostr2(time % 60));
+ SendtoTFT(PSTR(" M"));
+ #if ACDEBUG(AC_ALL)
+ SERIAL_ECHOLNPAIR("Print time ", ui8tostr2(time / 60), ":", ui8tostr2(time % 60));
+ #endif
+ } break;
+
+ case 8: // A8 Get SD Card list A8 S0
+ if (!isMediaInserted()) safe_delay(500);
+ if (!isMediaInserted()) // Make sure the card is removed
+ SendtoTFTLN(AC_msg_no_sd_card);
+ else if (panel_command[3] == 'S')
+ SendFileList( atoi( &panel_command[4] ) );
+ break;
+
+ case 33: // A33 Get firmware info
+ SendtoTFT(PSTR("J33 "));
+ SendtoTFTLN(PSTR(SHORT_BUILD_VERSION));
+ break;
+ }
+ }
+
+ void ChironTFT::PanelAction(uint8_t req) {
+ switch (req) {
+ case 9: // A9 Pause SD print
+ if (isPrintingFromMedia()) {
+ SendtoTFTLN(AC_msg_pause);
+ pausePrint();
+ printer_state = AC_printer_pausing;
+ }
+ else
+ SendtoTFTLN(AC_msg_stop);
+ break;
+
+ case 10: // A10 Resume SD Print
+ if (pause_state == AC_paused_idle || printer_state == AC_printer_resuming_from_power_outage)
+ resumePrint();
+ else
+ setUserConfirmed();
+ break;
+
+ case 11: // A11 Stop SD print
+ if (isPrintingFromMedia()) {
+ printer_state = AC_printer_stopping;
+ stopPrint();
+ }
+ else {
+ if (printer_state == AC_printer_resuming_from_power_outage)
+ injectCommands_P(PSTR("M1000 C")); // Cancel recovery
+ SendtoTFTLN(AC_msg_stop);
+ printer_state = AC_printer_idle;
+ }
+ break;
+
+ case 12: // A12 Kill printer
+ kill(); // from marlincore.h
+ break;
+
+ case 13: // A13 Select file
+ SelectFile();
+ break;
+
+ case 14: { // A14 Start Printing
+ // Allows printer to restart the job if we dont want to recover
+ if (printer_state == AC_printer_resuming_from_power_outage) {
+ injectCommands_P(PSTR("M1000 C")); // Cancel recovery
+ printer_state = AC_printer_idle;
+ }
+ #if ACDebugLevel >= 1
+ SERIAL_ECHOLNPAIR_F("Print: ", selectedfile);
+ #endif
+ // the card library needs a path starting // but the File api doesn't...
+ char file[MAX_PATH_LEN];
+ file[0] = '/';
+ strcpy(file + 1, selectedfile);
+ printFile(file);
+ SendtoTFTLN(AC_msg_print_from_sd_card);
+ } break;
+
+ case 15: // A15 Resuming from outage
+ if (printer_state == AC_printer_resuming_from_power_outage) {
+ // Need to home here to restore the Z position
+ injectCommands(AC_cmnd_power_loss_recovery);
+ injectCommands("M1000"); // home and start recovery
+ }
+ break;
+
+ case 16: { // A16 Set HotEnd temp A17 S170
+ const float set_Htemp = atof(&panel_command[5]);
+ hotend_state = set_Htemp ? AC_heater_temp_set : AC_heater_off;
+ switch ((char)panel_command[4]) {
+ // Set Temp
+ case 'S': case 'C': setTargetTemp_celsius(set_Htemp, E0);
+ }
+ } break;
+
+ case 17: { // A17 Set bed temp
+ const float set_Btemp = atof(&panel_command[5]);
+ hotbed_state = set_Btemp ? AC_heater_temp_set : AC_heater_off;
+ if (panel_command[4] == 'S')
+ setTargetTemp_celsius(set_Btemp, BED);
+ } break;
+
+ case 18: // A18 Set Fan Speed
+ if (panel_command[4] == 'S')
+ setTargetFan_percent(atof(&panel_command[5]), FAN0);
+ break;
+
+ case 19: // A19 Motors off
+ if (!isPrinting()) {
+ disable_all_steppers(); // from marlincore.h
+ SendtoTFTLN(AC_msg_ready);
+ }
+ break;
+
+ case 20: // A20 Read/write print speed
+ if (panel_command[4] == 'S')
+ setFeedrate_percent(atoi(&panel_command[5]));
+ else {
+ SendtoTFT(PSTR("A20V "));
+ TFTSer.println(getFeedrate_percent());
+ }
+ break;
+
+ case 21: // A21 Home Axis A21 X
+ if (!isPrinting()) {
+ switch ((char)panel_command[4]) {
+ case 'X': injectCommands_P(PSTR("G28X")); break;
+ case 'Y': injectCommands_P(PSTR("G28Y")); break;
+ case 'Z': injectCommands_P(PSTR("G28Z")); break;
+ case 'C': injectCommands_P(G28_STR); break;
+ }
+ }
+ break;
+
+ case 22: // A22 Move Axis A22 Y +10F3000
+ // Ignore request if printing
+ if (!isPrinting()) {
+ // setAxisPosition_mm() uses pre defined manual feedrates so ignore the feedrate from the panel
+ setSoftEndstopState(true); // enable endstops
+ float newposition = atof(&panel_command[6]);
+
+ #if ACDEBUG(AC_ACTION)
+ SERIAL_ECHOLNPAIR("Nudge ", panel_command[4], " axis ", newposition);
+ #endif
+
+ switch (panel_command[4]) {
+ case 'X': setAxisPosition_mm(getAxisPosition_mm(X) + newposition, X); break;
+ case 'Y': setAxisPosition_mm(getAxisPosition_mm(Y) + newposition, Y); break;
+ case 'Z': setAxisPosition_mm(getAxisPosition_mm(Z) + newposition, Z); break;
+ case 'E': // The only time we get this command is from the filament load/unload menu
+ // the standard movement is too slow so we will use the load unlod GCode to speed it up a bit
+ if (canMove(E0) && !commandsInQueue())
+ injectCommands_P(newposition > 0 ? AC_cmnd_manual_load_filament : AC_cmnd_manual_unload_filament);
+ break;
+ }
+ }
+ break;
+
+ case 23: // A23 Preheat PLA
+ // Ignore request if printing
+ if (!isPrinting()) {
+ // Temps defined in configuration.h
+ setTargetTemp_celsius(PREHEAT_1_TEMP_BED, BED);
+ setTargetTemp_celsius(PREHEAT_1_TEMP_HOTEND, E0);
+ SendtoTFTLN();
+ hotbed_state = AC_heater_temp_set;
+ hotend_state = AC_heater_temp_set;
+ }
+ break;
+
+ case 24: // A24 Preheat ABS
+ // Ignore request if printing
+ if (!isPrinting()) {
+ setTargetTemp_celsius(PREHEAT_2_TEMP_BED, BED);
+ setTargetTemp_celsius(PREHEAT_2_TEMP_HOTEND, E0);
+ SendtoTFTLN();
+ hotbed_state = AC_heater_temp_set;
+ hotend_state = AC_heater_temp_set;
+ }
+ break;
+
+ case 25: // A25 Cool Down
+ // Ignore request if printing
+ if (!isPrinting()) {
+ setTargetTemp_celsius(0, E0);
+ setTargetTemp_celsius(0, BED);
+ SendtoTFTLN(AC_msg_ready);
+ hotbed_state = AC_heater_off;
+ hotend_state = AC_heater_off;
+ }
+ break;
+
+ case 26: // A26 Refresh SD
+ // M22 M21 maybe needed here to reset sd card
+ filenavigator.reset();
+ break;
+
+ case 27: // A27 Servo Angles adjust
+ break;
+
+ case 28: // A28 Filament set A28 O/C
+ // Ignore request if printing
+ if (isPrinting()) break;
+ SendtoTFTLN();
+ break;
+ }
+ }
+
+ void ChironTFT::PanelProcess(uint8_t req) {
+ switch (req) {
+ case 29: { // A29 Read Mesh Point A29 X1 Y1
+ xy_uint8_t pos;
+ float pos_z;
+ pos.x = atoi(&panel_command[5]);
+ pos.y = atoi(&panel_command[8]);
+ pos_z = getMeshPoint(pos);
+
+ SendtoTFT(PSTR("A29V "));
+ TFTSer.println(pos_z * 100);
+ if (!isPrinting()) {
+ setSoftEndstopState(true); // disable endstops
+ // If the same meshpoint is selected twice in a row, move the head to that ready for adjustment
+ if ((selectedmeshpoint.x == pos.x) && (selectedmeshpoint.y == pos.y)) {
+ if (!isPositionKnown())
+ injectCommands_P(G28_STR); // home
+
+ if (isPositionKnown()) {
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Moving to mesh point at x: ", pos.x, " y: ", pos.y, " z: ", pos_z);
+ #endif
+ // Go up before moving
+ setAxisPosition_mm(3.0,Z);
+
+ setAxisPosition_mm(17 + (93 * pos.x), X);
+ setAxisPosition_mm(20 + (93 * pos.y), Y);
+ setAxisPosition_mm(0.0, Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Current Z: ", getAxisPosition_mm(Z));
+ #endif
+ }
+ }
+ selectedmeshpoint.x = pos.x;
+ selectedmeshpoint.y = pos.y;
+ }
+ } break;
+
+ case 30: { // A30 Auto leveling
+ if (panel_command[3] == 'S') { // Start probing
+ // Ignore request if printing
+ if (isPrinting())
+ SendtoTFTLN(AC_msg_probing_not_allowed); // forbid auto leveling
+ else {
+ injectCommands_P(PSTR("G28O\nG29"));
+ printer_state = AC_printer_probing;
+ SendtoTFTLN(AC_msg_start_probing);
+ }
+ }
+ else SendtoTFTLN(AC_msg_start_probing);
+ } break;
+
+ case 31: { // A31 Adjust all Probe Points
+ switch (panel_command[3]) {
+ case 'C': // Restore and apply original offsets
+ if (!isPrinting()) {
+ injectCommands_P(PSTR("M501\nM420 S1"));
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ }
+ break;
+ case 'D': // Save Z Offset tables and restore leveling state
+ if (!isPrinting()) {
+ setAxisPosition_mm(1.0,Z);
+ injectCommands_P(PSTR("M500"));
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ }
+ break;
+ case 'G': // Get current offset
+ SendtoTFT(PSTR("A31V "));
+ // When printing use the live z Offset position
+ // we will use babystepping to move the print head
+ if (isPrinting())
+ TFTSer.println(live_Zoffset);
+ else {
+ TFTSer.println(getZOffset_mm());
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ }
+ break;
+ case 'S': { // Set offset (adjusts all points by value)
+ float Zshift = atof(&panel_command[4]);
+ setSoftEndstopState(false); // disable endstops
+ // Allow temporary Z position nudging during print
+ // From the leveling panel use the all points UI to adjust the print pos.
+ if (isPrinting()) {
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Change Zoffset from:", live_Zoffset, " to ", live_Zoffset + Zshift);
+ #endif
+ if (isAxisPositionKnown(Z)) {
+ #if ACDEBUG(AC_INFO)
+ const float currZpos = getAxisPosition_mm(Z);
+ SERIAL_ECHOLNPAIR("Nudge Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
+ #endif
+ // Use babystepping to adjust the head position
+ int16_t steps = mmToWholeSteps(constrain(Zshift,-0.05,0.05), Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Steps to move Z: ", steps);
+ #endif
+ babystepAxis_steps(steps, Z);
+ live_Zoffset += Zshift;
+ }
+ SendtoTFT(PSTR("A31V "));
+ TFTSer.println(live_Zoffset);
+ }
+ else {
+ GRID_LOOP(x, y) {
+ const xy_uint8_t pos { x, y };
+ const float currval = getMeshPoint(pos);
+ setMeshPoint(pos, constrain(currval + Zshift, AC_LOWEST_MESHPOINT_VAL, 2));
+ }
+ const float currZOffset = getZOffset_mm();
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Change probe offset from ", currZOffset, " to ", currZOffset + Zshift);
+ #endif
+
+ setZOffset_mm(currZOffset + Zshift);
+ SendtoTFT(PSTR("A31V "));
+ TFTSer.println(getZOffset_mm());
+
+ if (isAxisPositionKnown(Z)) {
+ // Move Z axis
+ const float currZpos = getAxisPosition_mm(Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Move Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
+ #endif
+ setAxisPosition_mm(currZpos+constrain(Zshift,-0.05,0.05),Z);
+ }
+ }
+ } break;
+ } // end switch
+ } break;
+
+ case 32: { // A32 clean leveling beep flag
+ // Ignore request if printing
+ //if (isPrinting()) break;
+ //injectCommands_P(PSTR("M500\nM420 S1\nG1 Z10 F240\nG1 X0 Y0 F6000"));
+ //TFTSer.println("");
+ } break;
+
+ // A33 firmware info request seet PanelInfo()
+
+ case 34: { // A34 Adjust single mesh point A34 C/S X1 Y1 V123
+ if (panel_command[3] == 'C') { // Restore original offsets
+ injectCommands_P(PSTR("M501\nM420 S1"));
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ //printer_state = AC_printer_idle;
+ }
+ else {
+ xy_uint8_t pos;
+ pos.x = atoi(&panel_command[5]);
+ pos.y = atoi(&panel_command[8]);
+
+ float currmesh = getMeshPoint(pos);
+ float newval = atof(&panel_command[11])/100;
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Change mesh point x:", pos.x, " y:", pos.y);
+ SERIAL_ECHOLNPAIR("from ", currmesh, " to ", newval);
+ #endif
+ // Update Meshpoint
+ setMeshPoint(pos,newval);
+ if (printer_state == AC_printer_idle || printer_state == AC_printer_probing /*!isPrinting()*/) {
+ // if we are at the current mesh point indicated on the panel Move Z pos +/- 0.05mm
+ // (The panel changes the mesh value by +/- 0.05mm on each button press)
+ if (selectedmeshpoint.x == pos.x && selectedmeshpoint.y == pos.y) {
+ setSoftEndstopState(false);
+ float currZpos = getAxisPosition_mm(Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Move Z pos from ", currZpos, " to ", currZpos + constrain(newval - currmesh, -0.05, 0.05));
+ #endif
+ setAxisPosition_mm(currZpos + constrain(newval - currmesh, -0.05, 0.05), Z);
+ }
+ }
+ }
+ } break;
+ }
+ }
+} // namespace
+
+#endif // ANYCUBIC_LCD_CHIRON
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
new file mode 100644
index 0000000..267f2fe
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
@@ -0,0 +1,77 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/chiron_tft.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#include "chiron_tft_defs.h"
+#include "../../../../inc/MarlinConfigPre.h"
+#include "../../ui_api.h"
+namespace Anycubic {
+
+ class ChironTFT {
+ static printer_state_t printer_state;
+ static paused_state_t pause_state;
+ static heater_state_t hotend_state;
+ static heater_state_t hotbed_state;
+ static xy_uint8_t selectedmeshpoint;
+ static char panel_command[MAX_CMND_LEN];
+ static uint8_t command_len;
+ static char selectedfile[MAX_PATH_LEN];
+ static float live_Zoffset;
+ static file_menu_t file_menu;
+ public:
+ ChironTFT();
+ void Startup();
+ void IdleLoop();
+ void PrinterKilled(PGM_P,PGM_P);
+ void MediaEvent(media_event_t);
+ void TimerEvent(timer_event_t);
+ void FilamentRunout();
+ void ConfirmationRequest(const char * const );
+ void StatusChange(const char * const );
+ void PowerLossRecovery();
+
+ private:
+ void SendtoTFT(PGM_P);
+ void SendtoTFTLN(PGM_P);
+ bool ReadTFTCommand();
+ int8_t Findcmndpos(const char *, char);
+ void CheckHeaters();
+ void SendFileList(int8_t);
+ void SelectFile();
+ void InjectCommandandWait(PGM_P);
+ void ProcessPanelRequest();
+ void PanelInfo(uint8_t);
+ void PanelAction(uint8_t);
+ void PanelProcess(uint8_t);
+ };
+
+ extern ChironTFT Chiron;
+
+}
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
new file mode 100644
index 0000000..7012e98
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
@@ -0,0 +1,151 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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/lib/chiron_defs.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#pragma once
+#include "../../../../inc/MarlinConfigPre.h"
+//#define ACDEBUGLEVEL 255
+
+#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 PSTR("J00")
+#define AC_msg_sd_card_removed PSTR("J01")
+#define AC_msg_no_sd_card PSTR("J02")
+#define AC_msg_usb_connected PSTR("J03")
+#define AC_msg_print_from_sd_card PSTR("J04")
+#define AC_msg_pause PSTR("J05")
+#define AC_msg_nozzle_heating PSTR("J06")
+#define AC_msg_nozzle_heating_done PSTR("J07")
+#define AC_msg_bed_heating PSTR("J08")
+#define AC_msg_bed_heating_done PSTR("J09")
+#define AC_msg_nozzle_temp_abnormal PSTR("J10")
+#define AC_msg_kill_lcd PSTR("J11")
+#define AC_msg_ready PSTR("J12")
+#define AC_msg_low_nozzle_temp PSTR("J13")
+#define AC_msg_print_complete PSTR("J14")
+#define AC_msg_filament_out_alert PSTR("J15")
+#define AC_msg_stop PSTR("J16")
+#define AC_msg_main_board_has_reset PSTR("J17")
+#define AC_msg_paused PSTR("J18")
+#define AC_msg_j19_unknown PSTR("J19")
+#define AC_msg_sd_file_open_success PSTR("J20")
+#define AC_msg_sd_file_open_failed PSTR("J21")
+#define AC_msg_level_monitor_finished PSTR("J22")
+#define AC_msg_filament_out_block PSTR("J23")
+#define AC_msg_probing_not_allowed PSTR("J24")
+#define AC_msg_probing_complete PSTR("J25")
+#define AC_msg_start_probing PSTR("J26")
+#define AC_msg_version PSTR("J27")
+
+#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_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_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_leveling PSTR("M420SV")
+#define AC_cmnd_power_loss_recovery PSTR("G28XYR5\nG28Z") // 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_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_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
+ };
+}
--
cgit v1.2.3