diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index bd4793c55cb..e41d5132a80 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -1617,6 +1617,31 @@
   #endif
 #endif // HAS_DGUS_LCD
 
+//
+// Additional options for AnyCubic Chiron TFT displays
+//
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+  // By default the type of panel is automatically detected.
+  // Enable one of these options if you know the panel type.
+  //#define CHIRON_TFT_STANDARD
+  //#define CHIRON_TFT_NEW
+
+  // Enable the longer Anycubic powerup startup tune
+  //#define AC_DEFAULT_STARTUP_TUNE
+
+  /**
+   * Display Folders
+   * By default the file browser lists all G-code files (including those in subfolders) in a flat list.
+   * Enable this option to display a hierarchical file browser.
+   *
+   * NOTES:
+   * - Without this option it helps to enable SDCARD_SORT_ALPHA so files are sorted before/after folders.
+   * - When used with the "new" panel, folder names will also have '.gcode' appended to their names.
+   *   This hack is currently required to force the panel to show folders.
+   */
+  #define AC_SD_FOLDER_VIEW
+#endif
+
 //
 // Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
 //
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 64fcc85aadc..58d52733e8b 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -2443,6 +2443,10 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
   #error "GRAPHICAL_TFT_UPSCALE must be 2, 3, or 4."
 #endif
 
+#if BOTH(CHIRON_TFT_STANDARD, CHIRON_TFT_NEW)
+  #error "Please select only one of CHIRON_TFT_STANDARD or CHIRON_TFT_NEW."
+#endif
+
 /**
  * Some boards forbid the use of -1 Native USB
  */
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
index 25847ae96ca..9975d0824f2 100644
--- a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
@@ -26,139 +26,233 @@
  * 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 or flat file display and supports both standerd and new style panels.
+ *
+ * ## Old Style TFT panel
+ * Supported chars	{}[]-+=_"$%^&*()~<>|
+ * Max display length 22 chars
+ * Max path len 29 chars
+ * (DOS 8.3 filepath max 29chars)
+ * (long filepath Max 22)
+ *
+ * ## New TFT Panel Format file display format
+ * Supported chars	{}[]-+=_!"$%^&*()~<>\|
+ * Max display length 26 chars
+ * Max path len 29 chars
+ * (DOS 8.3 filepath must end '.GCO')
+ * (long filepath must end '.gcode')
+ *
  */
 
-/***************************************************************************
- * 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;
 
+#define DEBUG_OUT ACDEBUG(AC_FILE)
+#include "../../../../core/debug_out.h"
+
 namespace Anycubic {
 
-  FileNavigator filenavigator;
+FileNavigator filenavigator;
+FileList  FileNavigator::filelist;                          // Instance of the Marlin file API
+uint16_t  FileNavigator::lastpanelindex;
+uint16_t  FileNavigator::currentindex;                      // override the panel request
+uint8_t   FileNavigator::currentfolderdepth;
+uint16_t  FileNavigator::currentfolderindex[MAX_FOLDER_DEPTH];   // track folder pos for iteration
+char      FileNavigator::currentfoldername[MAX_PATH_LEN + 1];   // Current folder path
 
-  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(); }
 
-  FileNavigator::FileNavigator() { reset(); }
+void FileNavigator::reset() {
+  DEBUG_ECHOLNPGM("reset()");
+  currentfoldername[0] = '\0';
+  currentfolderdepth = 0;
+  currentindex = 0;
+  lastpanelindex = 0;
+  ZERO(currentfolderindex)
 
-  void FileNavigator::reset() {
-    currentfoldername[0] = '\0';
-    folderdepth  = 0;
-    currentindex = 0;
-    lastindex    = 0;
-    // Start at root folder
-    while (!filelist.isAtRootDir()) filelist.upDir();
-    refresh();
+  // Start at root folder
+  while (!filelist.isAtRootDir()) filelist.upDir();
+  refresh();
+}
+
+void FileNavigator::refresh() { filelist.refresh(); }
+
+void FileNavigator::changeDIR(const char *folder) {
+  if (currentfolderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
+  DEBUG_ECHOLNPAIR("FD:" , folderdepth, " FP:",currentindex, " currentfolder:", currentfoldername, " enter:", folder);
+  currentfolderindex[currentfolderdepth] = currentindex;
+  strcat(currentfoldername, folder);
+  strcat(currentfoldername, "/");
+  filelist.changeDir(folder);
+  currentfolderdepth++;
+  currentindex = 0;
+}
+
+void FileNavigator::upDIR() {
+  DEBUG_ECHOLNPAIR("upDIR() from D:", currentfolderdepth, " N:", currentfoldername);
+  if (!filelist.isAtRootDir()) {
+    filelist.upDir();
+    currentfolderdepth--;
+    currentindex = currentfolderindex[currentfolderdepth]; // restore last position in the folder
+    filelist.seek(currentindex); // restore file information
   }
 
-  void FileNavigator::refresh() { filelist.refresh(); }
+  // Remove the child folder from the stored path
+  if (currentfolderdepth == 0)
+    currentfoldername[0] = '\0';
+  else {
+    const char *pos = strchr(currentfoldername, '/');
+    *(pos + 1) = '\0';
+  }
+}
 
-  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 of the .. added to the root.
-      if (index > lastindex)
-        currentindex += files;
+void FileNavigator::skiptofileindex(uint16_t skip) {
+  if (skip == 0) return;
+  while (skip > 0) {
+    if (filelist.seek(currentindex)) {
+      DEBUG_ECHOLNPAIR("CI:", currentindex, " FD:", currentfolderdepth, " N:", skip, " ", filelist.longFilename());
+      if (!filelist.isDir()) {
+        skip--;
+        currentindex++;
+      }
       else
-        currentindex = currentindex < 4 ? 0 : currentindex - files;
+        changeDIR(filelist.shortFilename());
+    } // valid file
+    if (currentindex == filelist.count()) {
+      if (currentfolderdepth > 0) {
+        upDIR();
+        currentindex++;
+      }
+      else break; // end of root folder
+    } // end of folder
+  } // files needed
+  // No more files available.
+}
+
+#if ENABLED(AC_SD_FOLDER_VIEW) // SD Folder navigation
+
+  void FileNavigator::getFiles(uint16_t index, panel_type_t paneltype, uint8_t filesneeded) {
+    if (index == 0) currentindex = 0;
+    // Each time we change folder we reset the file index to 0 and keep track
+    // of the current position, since the TFT panel isn't aware of folder trees.
+    if (index > 0) {
+      --currentindex; // go back a file to take account of the .. we added to the root.
+      if (index > lastpanelindex)
+        currentindex += filesneeded;
+      else
+        currentindex = currentindex < 4 ? 0 : currentindex - filesneeded;
     }
-    lastindex = index;
+    lastpanelindex = index;
 
-    #if ACDEBUG(AC_FILE)
-      SERIAL_ECHOLNPAIR("index=", index, " currentindex=", currentindex);
-    #endif
+    DEBUG_ECHOLNPAIR("index=", index, " currentindex=", currentindex);
 
-    if (currentindex == 0 && folderdepth > 0) { // Add a link to go up a folder
-      TFTSer.println("<<");
-      TFTSer.println("..");
-      files--;
+    if (currentindex == 0 && currentfolderdepth > 0) { // Add a link to go up a folder
+      // The new panel ignores entries that don't end in .GCO or .gcode so add and pad them.
+      if (paneltype == AC_panel_new) {
+        TFTSer.println("<<.GCO");
+        Chiron.SendtoTFTLN(PSTR("..                  .gcode"));
+      }
+      else {
+        TFTSer.println("<<");
+        TFTSer.println("..");
+      }
+      filesneeded--;
     }
 
-    for (uint16_t seek = currentindex; seek < currentindex + files; seek++) {
+    for (uint16_t seek = currentindex; seek < currentindex + filesneeded; seek++) {
       if (filelist.seek(seek)) {
-        sendFile();
-        #if ACDEBUG(AC_FILE)
-          SERIAL_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
-        #endif
+        sendFile(paneltype);
+        DEBUG_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'");
       }
     }
   }
 
-  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
+  void FileNavigator::sendFile(panel_type_t paneltype) {
     if (filelist.isDir()) {
-      //TFTSer.print(currentfoldername);
-      TFTSer.println(filelist.shortFilename());
-      TFTSer.print(filelist.shortFilename());
-      TFTSer.println("/");
+      // Add mandatory tags for new panel otherwise lines are ignored.
+      if (paneltype == AC_panel_new) {
+        TFTSer.print(filelist.shortFilename());
+        TFTSer.println(".GCO");
+        TFTSer.print(filelist.shortFilename());
+        TFTSer.write('/');
+        // Make sure we fill all 29 chars of the display line to clear the text buffer otherwise the last line is still visible
+        for (int8_t i = strlen(filelist.shortFilename()); i < 19; i++)
+          TFTSer.write(' ');
+        TFTSer.println(".gcode");
+      }
+      else {
+        TFTSer.println(filelist.shortFilename());
+        TFTSer.print(filelist.shortFilename());
+        TFTSer.write('/');
+        TFTSer.println();
+      }
     }
-    else {
-      // Logical Name
+    else { // Not DIR
       TFTSer.write('/');
-      if (folderdepth > 0) TFTSer.print(currentfoldername);
-
+      if (currentfolderdepth > 0) TFTSer.print(currentfoldername);
       TFTSer.println(filelist.shortFilename());
+      TFTSer.print(filelist.longFilename());
 
-      // Display Name
-      TFTSer.println(filelist.longFilename());
+      // Make sure we fill all 29 chars of the display line to clear the text buffer otherwise the last line is still visible
+      if (paneltype == AC_panel_new)
+        for (int8_t i = strlen(filelist.longFilename()); i < 26; i++)
+          TFTSer.write(' ');
+
+      TFTSer.println();
     }
-  }
-  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;
-  }
+  }  // AC_SD_FOLDER_VIEW
 
-  void FileNavigator::upDIR() {
-    filelist.upDir();
-    refresh();
-    folderdepth--;
-    currentindex = 0;
-    // Remove the last child folder from the stored path
-    if (folderdepth == 0) {
-      currentfoldername[0] = '\0';
+#else // Flat file list
+
+  void FileNavigator::getFiles(uint16_t index, panel_type_t paneltype, uint8_t filesneeded) {
+    DEBUG_ECHOLNPAIR("getFiles() I:", index," L:", lastpanelindex);
+    // if we're searching backwards, jump back to start and search forward
+    if (index < lastpanelindex) {
       reset();
+      skiptofileindex(index);
     }
-    else {
-      char *pos = nullptr;
-      for (uint8_t f = 0; f < folderdepth; f++)
-        pos = strchr(currentfoldername, '/');
+    lastpanelindex = index;
 
-      *(pos + 1) = '\0';
-    }
-    #if ACDEBUG(AC_FILE)
-      SERIAL_ECHOLNPAIR("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
-    #endif
+    while (filesneeded > 0) {
+      if (filelist.seek(currentindex)) {
+        if (!filelist.isDir()) {
+          sendFile(paneltype);
+          filesneeded--;
+          currentindex++;
+        }
+        else
+          changeDIR(filelist.shortFilename());
+      } // valid file
+
+      if (currentindex == filelist.count()) {
+        if (currentfolderdepth > 0) {
+          upDIR();
+          currentindex++;
+        }
+        else break; // end of root folder
+      } // end of folder
+    } // files needed
+    // No more files available.
   }
 
-  char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
-}
+  void FileNavigator::sendFile(panel_type_t paneltype) {
+    TFTSer.write('/');
+    if (currentfolderdepth > 0) TFTSer.print(currentfoldername);
+    TFTSer.println(filelist.shortFilename());
+    if (currentfolderdepth > 0) TFTSer.print(currentfoldername);
+    TFTSer.println(filelist.longFilename());
+    DEBUG_ECHOLNPAIR("/", currentfoldername, "", filelist.shortFilename(), " ", filelist.longFilename());
+  }
+
+#endif // Flat file list
+
+} // Anycubic namespace
 
 #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
index c7094158790..253b8039e7d 100644
--- a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
@@ -38,14 +38,13 @@ namespace Anycubic {
 
 class FileNavigator {
   public:
-    FileNavigator();
-    void reset();
-    void getFiles(uint16_t, panel_type_t, uint8_t filesneeded=4);
-    void upDIR();
-    void changeDIR(const char *);
-    void sendFile(panel_type_t);
-    void refresh();
-    void skiptofileindex(uint16_t);
+    static void reset();
+    static void getFiles(uint16_t, panel_type_t, uint8_t filesneeded=4);
+    static void upDIR();
+    static void changeDIR(const char *);
+    static void sendFile(panel_type_t);
+    static void refresh();
+    static void skiptofileindex(uint16_t);
 
     static FileList filelist;
   private:
@@ -53,7 +52,7 @@ class FileNavigator {
     static uint16_t currentindex;
     static uint8_t  currentfolderdepth;
     static uint16_t currentfolderindex[MAX_FOLDER_DEPTH];
-    static char     currentfoldername[MAX_PATH_LEN];
+    static char     currentfoldername[MAX_PATH_LEN + 1];
 };
 
 extern FileNavigator filenavigator;
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
index 065e4e17896..b35d7927368 100644
--- a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
@@ -43,25 +43,27 @@
 
 namespace Anycubic {
 
+ChironTFT Chiron;
+#if AUTO_DETECT_CHIRON_TFT
+  panel_type_t   ChironTFT::panel_type = AC_panel_unknown;
+#endif
+last_error_t     ChironTFT::last_error;
 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];
+char             ChironTFT::selectedfile[MAX_PATH_LEN + 1];
+char             ChironTFT::panel_command[MAX_CMND_LEN + 1];
 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;
+  last_error        = AC_error_none;
   printer_state     = AC_printer_idle;
   pause_state       = AC_paused_idle;
   hotend_state      = AC_heater_off;
@@ -80,27 +82,41 @@ void ChironTFT::Startup() {
   // 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);
 
+  // wait for the TFT panel to initialise and finish the animation
+  delay_ms(250);
+
+  // There are different panels for the Chiron with slightly different commands
+  // So we need to know what we are working with.
+
+  // Panel type can be defined otherwise detect it automatically
+  if (panel_type == AC_panel_unknown) DetectPanelType();
+
   // 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);
+  PlayTune(BEEPER_PIN, TERN(AC_DEFAULT_STARTUP_TUNE, Anycubic_PowerOn, GB_PowerOn), 1);
+
   #if ACDEBUGLEVEL
     SERIAL_ECHOLNPAIR("AC Debug Level ", ACDEBUGLEVEL);
   #endif
   SendtoTFTLN(AC_msg_ready);
 }
 
+void ChironTFT::DetectPanelType() {
+  #if AUTO_DETECT_CHIRON_TFT
+    // Send a query to the TFT
+    SendtoTFTLN(AC_Test_for_OldPanel); // The panel will respond with 'SXY 480 320'
+    SendtoTFTLN(AC_Test_for_NewPanel); // the panel will respond with '[0]=0   ' to '[19]=0   '
+  #endif
+}
+
 void ChironTFT::IdleLoop()  {
   if (ReadTFTCommand()) {
     ProcessPanelRequest();
@@ -123,15 +139,16 @@ void ChironTFT::MediaEvent(media_event_t event)  {
   switch (event) {
     case AC_media_inserted:
       SendtoTFTLN(AC_msg_sd_card_inserted);
-    break;
+      break;
 
     case AC_media_removed:
       SendtoTFTLN(AC_msg_sd_card_removed);
-    break;
+      break;
 
     case AC_media_error:
+      last_error = AC_error_noSD;
       SendtoTFTLN(AC_msg_no_sd_card);
-    break;
+      break;
   }
 }
 
@@ -170,8 +187,8 @@ void ChironTFT::FilamentRunout()  {
     SERIAL_ECHOLNPAIR("FilamentRunout() printer_state ", printer_state);
   #endif
   // 1 Signal filament out
+  last_error = AC_error_filament_runout;
   SendtoTFTLN(isPrintingFromMedia() ? AC_msg_filament_out_alert : AC_msg_filament_out_block);
-  //printer_state = AC_printer_filament_out;
   PlayTune(BEEPER_PIN, FilamentOut, 1);
 }
 
@@ -278,14 +295,23 @@ void ChironTFT::StatusChange(const char * const msg)  {
       SendtoTFTLN(AC_msg_bed_heating);
       hotbed_state = AC_heater_temp_set;
     }
+    else if (strcmp_P(msg, MARLIN_msg_EEPROM_version) == 0) {
+      last_error = AC_error_EEPROM;
+    }
   }
 }
 
 void ChironTFT::PowerLossRecovery()  {
   printer_state = AC_printer_resuming_from_power_outage; // Play tune to notify user we can recover.
+  last_error = AC_error_powerloss;
   PlayTune(BEEPER_PIN, SOS, 1);
-  SERIAL_ECHOLNPGM("Resuming from power outage...");
-  SERIAL_ECHOLNPGM("Select SD file then press resume");
+  SERIAL_ECHOLNPGM_P(AC_msg_powerloss_recovery);
+}
+
+void ChironTFT::PrintComplete() {
+  SendtoTFT(AC_msg_print_complete);
+  printer_state = AC_printer_idle;
+  setSoftEndstopState(true); // enable endstops
 }
 
 void ChironTFT::SendtoTFT(PGM_P str) {  // A helper to print PROGMEM string to the panel
@@ -319,26 +345,29 @@ bool ChironTFT::ReadTFTCommand() {
     command_len++;
   }
 
-  if (command_ready) {
-    panel_command[command_len] = 0x00;
+  if (command_ready || command_len == MAX_CMND_LEN) {
+    panel_command[command_len] = '\0';
     #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);
-      }
+      SERIAL_ECHOLNPAIR("len(",command_len,") < ", panel_command);
     #endif
+    command_ready = true;
   }
   return command_ready;
 }
 
-int8_t ChironTFT::Findcmndpos(const char * buff, char q) {
+int8_t ChironTFT::FindToken(char c) {
   int8_t pos = 0;
-  do { if (buff[pos] == q) return pos; } while (++pos < MAX_CMND_LEN);
+  do {
+    if (panel_command[pos] == c) {
+      #if ACDEBUG(AC_INFO)
+        SERIAL_ECHOLNPAIR("Tpos:", pos, " ", c);
+      #endif
+      return pos;
+    }
+  } while(++pos < command_len);
+  #if ACDEBUG(AC_INFO)
+    SERIAL_ECHOLNPAIR("Not found: ", c);
+  #endif
   return -1;
 }
 
@@ -352,6 +381,7 @@ void ChironTFT::CheckHeaters() {
     faultDuration++;
     if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
       SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+      last_error = AC_error_abnormal_temp_t0;
       SERIAL_ECHOLNPAIR("Extruder temp abnormal! : ", temp);
       break;
     }
@@ -366,6 +396,7 @@ void ChironTFT::CheckHeaters() {
     faultDuration++;
     if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
       SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+      last_error = AC_error_abnormal_temp_bed;
       SERIAL_ECHOLNPAIR("Bed temp abnormal! : ", temp);
       break;
     }
@@ -396,15 +427,21 @@ void ChironTFT::SendFileList(int8_t startindex) {
     SERIAL_ECHOLNPAIR("## SendFileList ## ", startindex);
   #endif
   SendtoTFTLN(PSTR("FN "));
-  filenavigator.getFiles(startindex);
+  filenavigator.getFiles(startindex, panel_type, 4);
   SendtoTFTLN(PSTR("END"));
 }
 
 void ChironTFT::SelectFile() {
-  strncpy(selectedfile, panel_command + 4, command_len - 4);
-  selectedfile[command_len - 5] = '\0';
+  if (panel_type == AC_panel_new) {
+    strncpy(selectedfile, panel_command + 4, command_len - 3);
+    selectedfile[command_len - 4] = '\0';
+  }
+  else {
+    strncpy(selectedfile, panel_command + 4, command_len - 4);
+    selectedfile[command_len - 5] = '\0';
+  }
   #if ACDEBUG(AC_FILE)
-    SERIAL_ECHOLNPAIR_F(" Selected File: ",selectedfile);
+    SERIAL_ECHOLNPAIR(" Selected File: ",selectedfile);
   #endif
   switch (selectedfile[0]) {
     case '/':   // Valid file selected
@@ -417,6 +454,9 @@ void ChironTFT::SelectFile() {
       SendFileList( 0 );
       break;
     default:   // enter sub folder
+      // for new panel remove the '.GCO' tag that was added to the end of the path
+      if (panel_type == AC_panel_new)
+        selectedfile[strlen(selectedfile) - 4] = '\0';
       filenavigator.changeDIR(selectedfile);
       SendtoTFTLN(AC_msg_sd_file_open_failed);
       SendFileList( 0 );
@@ -424,25 +464,48 @@ void ChironTFT::SelectFile() {
   }
 }
 
-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]);
+  const int8_t tpos = FindToken('A');
+  // Panel request are 'A0' - 'A36'
+  if (tpos != -1) {
+    const int8_t req = atoi(&panel_command[tpos+1]);
 
-  // Information requests A0 - A8 and A33
-  if (req <= 8 || req == 33) PanelInfo(req);
+    // Information requests A0 - A8 and A33
+    if (req <= 8 || req == 33) PanelInfo(req);
 
-  // Simple Actions A9 - A28
-  else if ( req <= 28) PanelAction(req);
+    // Simple Actions A9 - A28
+    else if (req <= 28) PanelAction(req);
 
-  // Process Initiation
-  else if (req <= 34) PanelProcess(req);
+    // Process Initiation
+    else if (req <= 36) PanelProcess(req);
+  }
+  else {
+    #if AUTO_DETECT_CHIRON_TFT
+      // This may be a response to a panel type detection query
+      if (panel_type == AC_panel_unknown) {
+        tpos = FindToken('S'); // old panel will respond to 'SIZE' with 'SXY 480 320'
+        if (tpos != -1) {
+          if (panel_command[tpos+1]== 'X' && panel_command[tpos+2]=='Y') {
+            panel_type = AC_panel_standard;
+            SERIAL_ECHOLNPGM_P(AC_msg_old_panel_detected);
+          }
+        }
+        else {
+          tpos = FindToken('['); // new panel will respond to 'J200' with '[0]=0'
+          if (tpos != -1) {
+            if (panel_command[tpos+1]== '0' && panel_command[tpos+2]==']') {
+              panel_type = AC_panel_new;
+              SERIAL_ECHOLNPGM_P(AC_msg_new_panel_detected);
+            }
+          }
+        }
+        return;
+      }
+    #endif
 
-  else SendtoTFTLN();
+    SendtoTFTLN(); // Ignore unknown requests
+  }
 }
 
 void ChironTFT::PanelInfo(uint8_t req) {
@@ -513,7 +576,8 @@ void ChironTFT::PanelInfo(uint8_t req) {
 
     case 33:   // A33 Get firmware info
       SendtoTFT(PSTR("J33 "));
-      SendtoTFTLN(PSTR(SHORT_BUILD_VERSION));
+      // If there is an error recorded, show that instead of the FW version
+      if (!GetLastError()) SendtoTFTLN(PSTR(SHORT_BUILD_VERSION));
       break;
   }
 }
@@ -567,11 +631,7 @@ void ChironTFT::PanelAction(uint8_t req) {
       #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);
+      printFile(selectedfile);
       SendtoTFTLN(AC_msg_print_from_sd_card);
     } break;
 
@@ -631,29 +691,24 @@ void ChironTFT::PanelAction(uint8_t req) {
       }
       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]);
+    case 22: {   // A22 Move Axis
+      // The commands have changed on the new panel
+      // Old TFT A22 X -1F1500      A22 X +1F1500
+      // New TFT A22 X-1.0 F1500    A22 X1.0 F1500
 
+      // lets just wrap this in a gcode relative nonprint move and let the controller deal with it
+      // G91 G0 <panel command> G90
+
+      if (!isPrinting()) { // Ignore request if printing
+        char MoveCmnd[30];
+        sprintf_P(MoveCmnd, PSTR("G91\nG0 %s \nG90"), panel_command+3);
         #if ACDEBUG(AC_ACTION)
-          SERIAL_ECHOLNPAIR("Nudge ", AS_CHAR(panel_command[4]), " axis ", newposition);
+          SERIAL_ECHOLNPAIR("Move: ", MoveCmnd);
         #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;
-        }
+        setSoftEndstopState(true);  // enable endstops
+        injectCommands(MoveCmnd);
       }
-      break;
+    } break;
 
     case 23:   // A23 Preheat PLA
       // Ignore request if printing
@@ -690,7 +745,9 @@ void ChironTFT::PanelAction(uint8_t req) {
       break;
 
     case 26:   // A26 Refresh SD
-      // M22 M21 maybe needed here to reset sd card
+      if (card.isMounted())card.release();
+      card.mount();
+      safe_delay(500);
       filenavigator.reset();
       break;
 
@@ -710,8 +767,8 @@ void ChironTFT::PanelProcess(uint8_t 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.x = atoi(&panel_command[FindToken('X')+1]);
+      pos.y = atoi(&panel_command[FindToken('Y')+1]);
       pos_z = getMeshPoint(pos);
 
       SendtoTFT(PSTR("A29V "));
@@ -743,48 +800,60 @@ void ChironTFT::PanelProcess(uint8_t req) {
       }
     } break;
 
-    case 30: {  // A30 Auto leveling
-      if (panel_command[3] == 'S') { // Start probing
+    case 30: {   // A30 Auto leveling
+      if (FindToken('S') != -1) { // Start probing New panel adds spaces..
         // 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);
+          injectCommands_P(PSTR("G28\nG29"));
+          printer_state = AC_printer_probing;
         }
       }
-      else SendtoTFTLN(AC_msg_start_probing);
-    }  break;
+      else {
+        SendtoTFTLN(AC_msg_start_probing); // Just enter levelling menu
+      }
+    } 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]);
+      // The tokens can occur in different places on the new panel so we need to find it.
+
+      if (FindToken('C') != -1) { // Restore and apply original offsets
+        if (!isPrinting()) {
+          injectCommands_P(PSTR("M501\nM420 S1"));
+          selectedmeshpoint.x = selectedmeshpoint.y = 99;
+          SERIAL_ECHOLNPGM_P(AC_msg_mesh_changes_abandoned);
+        }
+      }
+
+      else if (FindToken('D') != -1) { // Save Z Offset tables and restore leveling state
+        if (!isPrinting()) {
+          setAxisPosition_mm(1.0,Z); // Lift nozzle before any further movements are made
+          injectCommands_P(PSTR("M500"));
+          SERIAL_ECHOLNPGM_P(AC_msg_mesh_changes_saved);
+          selectedmeshpoint.x = selectedmeshpoint.y = 99;
+        }
+      }
+
+      else if (FindToken('G') != -1) { // 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;
+        }
+      }
+
+      else {
+        int8_t tokenpos = FindToken('S');
+        if (tokenpos != -1) { // Set offset (adjusts all points by value)
+          float Zshift = atof(&panel_command[tokenpos+1]);
           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.
@@ -813,6 +882,9 @@ void ChironTFT::PanelProcess(uint8_t req) {
               const xy_uint8_t pos { x, y };
               const float currval = getMeshPoint(pos);
               setMeshPoint(pos, constrain(currval + Zshift, AC_LOWEST_MESHPOINT_VAL, 2));
+              #if ACDEBUG(AC_INFO)
+                SERIAL_ECHOLNPAIR("Change mesh point X", x," Y",y ," from ", currval, " to ", getMeshPoint(pos) );
+              #endif
             }
             const float currZOffset = getZOffset_mm();
             #if ACDEBUG(AC_INFO)
@@ -878,9 +950,27 @@ void ChironTFT::PanelProcess(uint8_t req) {
         }
       }
     }  break;
+
+    case 36:    // A36 Auto leveling for new TFT bet that was a typo in the panel code!
+      SendtoTFTLN(AC_msg_start_probing);
+      break;
   }
 }
 
-} // Anycubic
+bool ChironTFT::GetLastError() {
+  switch (last_error) {
+    case AC_error_abnormal_temp_bed: SendtoTFTLN(AC_msg_error_bed_temp);    break;
+    case AC_error_abnormal_temp_t0:  SendtoTFTLN(AC_msg_error_hotend_temp); break;
+    case AC_error_noSD:              SendtoTFTLN(AC_msg_error_sd_card);     break;
+    case AC_error_powerloss:         SendtoTFTLN(AC_msg_power_loss);        break;
+    case AC_error_EEPROM:            SendtoTFTLN(AC_msg_eeprom_version);    break;
+    case AC_error_filament_runout:   SendtoTFTLN(AC_msg_filament_out);      break;
+    default: return false;
+  }
+  last_error = AC_error_none;
+  return true;
+}
+
+} // Anycubic 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
index 3c26cc0aec5..aeef12afc61 100644
--- a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
@@ -33,23 +33,30 @@
 #include "../../../../inc/MarlinConfigPre.h"
 #include "../../ui_api.h"
 
+#if NONE(CHIRON_TFT_STANDARD, CHIRON_TFT_NEW)
+  #define AUTO_DETECT_CHIRON_TFT 1
+#endif
+
 namespace Anycubic {
 
 class ChironTFT {
-  private:
-    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;
-
+  #if AUTO_DETECT_CHIRON_TFT
+    static panel_type_t panel_type;
+  #else
+    static constexpr panel_type_t panel_type = TERN(CHIRON_TFT_NEW, AC_panel_new, AC_panel_standard);
+  #endif
+  static last_error_t last_error;
+  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 + 1];
+  static uint8_t          command_len;
+  static char             selectedfile[MAX_PATH_LEN + 1];
+  static float            live_Zoffset;
+  static file_menu_t      file_menu;
   public:
-    ChironTFT();
     static void Startup();
     static void IdleLoop();
     static void PrinterKilled(PGM_P,PGM_P);
@@ -59,12 +66,13 @@ class ChironTFT {
     static void ConfirmationRequest(const char * const );
     static void StatusChange(const char * const );
     static void PowerLossRecovery();
-
-  private:
+    static void PrintComplete();
     static void SendtoTFT(PGM_P);
     static void SendtoTFTLN(PGM_P);
+  private:
+    static void DetectPanelType();
     static bool ReadTFTCommand();
-    static int8_t Findcmndpos(const char *, char);
+    static int8_t FindToken(char);
     static void CheckHeaters();
     static void SendFileList(int8_t);
     static void SelectFile();
@@ -73,8 +81,9 @@ class ChironTFT {
     static void PanelInfo(uint8_t);
     static void PanelAction(uint8_t);
     static void PanelProcess(uint8_t);
+    static bool GetLastError();
 };
 
 extern ChironTFT Chiron;
 
-} // Anycubic
+} // Anycubic namespace
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
index a8ebe9c776f..83e64e7973c 100644
--- a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
@@ -30,7 +30,7 @@
 
 #pragma once
 #include "../../../../inc/MarlinConfigPre.h"
-//#define ACDEBUGLEVEL 255
+//#define ACDEBUGLEVEL 4
 
 #if ACDEBUGLEVEL
   // Bit-masks for selective debug:
@@ -54,7 +54,7 @@
 #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
+#define AC_LOWEST_MESHPOINT_VAL         -10  // The lowest value you can set for a single mesh point offset
 
  // TFT panel commands
 #define  AC_msg_sd_card_inserted       PSTR("J00")
@@ -85,6 +85,18 @@
 #define  AC_msg_probing_complete       PSTR("J25")
 #define  AC_msg_start_probing          PSTR("J26")
 #define  AC_msg_version                PSTR("J27")
+#define  AC_msg_mesh_changes_abandoned PSTR("Mesh changes abandoned, previous mesh restored.")
+#define  AC_msg_mesh_changes_saved     PSTR("Mesh changes saved.")
+#define  AC_msg_old_panel_detected     PSTR("Standard TFT panel detected!")
+#define  AC_msg_new_panel_detected     PSTR("New TFT panel detected!")
+#define  AC_msg_powerloss_recovery     PSTR("Resuming from power outage! select the same SD file then press resume")
+// Error messages must not contain spaces
+#define  AC_msg_error_bed_temp         PSTR("Abnormal_bed_temp")
+#define  AC_msg_error_hotend_temp      PSTR("Abnormal_hotend_temp")
+#define  AC_msg_error_sd_card          PSTR("SD_card_error")
+#define  AC_msg_filament_out           PSTR("Filament_runout")
+#define  AC_msg_power_loss             PSTR("Power_failure")
+#define  AC_msg_eeprom_version         PSTR("EEPROM_ver_wrong")
 
 #define MARLIN_msg_start_probing       PSTR("Probing Point 1/25")
 #define MARLIN_msg_probing_failed      PSTR("Probing Failed")
@@ -93,13 +105,14 @@
 #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_EEPROM_version      PSTR("EEPROM Version Error")
 #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
 
@@ -108,6 +121,9 @@
 #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
 
+#define AC_Test_for_OldPanel           PSTR("SIZE")                    // An old panel will respond with 'SXY 480 320' a new panel wont respond.
+#define AC_Test_for_NewPanel           PSTR("J200")                    // A new panel will respond with '[0]=0   [1]=0' to '[19]=0   '  an old panel wont respond
+
 namespace Anycubic {
   enum heater_state_t : uint8_t {
     AC_heater_off,
@@ -120,6 +136,7 @@ namespace Anycubic {
     AC_paused_idle
   };
   enum printer_state_t : uint8_t {
+    AC_printer_booting,
     AC_printer_idle,
     AC_printer_probing,
     AC_printer_printing,
@@ -144,4 +161,18 @@ namespace Anycubic {
     AC_menu_change_to_file,
     AC_menu_change_to_command
   };
-} // Anycubic
+  enum panel_type_t : uint8_t {
+    AC_panel_unknown,
+    AC_panel_standard,
+    AC_panel_new
+  };
+  enum last_error_t : uint8_t {
+    AC_error_none,
+    AC_error_abnormal_temp_t0,
+    AC_error_abnormal_temp_bed,
+    AC_error_noSD,
+    AC_error_powerloss,
+    AC_error_filament_runout,
+    AC_error_EEPROM
+  };
+}  // Anycubic namespace