From 782b9ce69eba1b5360184c6914a2803031258ecd Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Mon, 28 Sep 2020 15:52:21 -0500
Subject: [PATCH] Improve Power-Loss Recovery (#19540)

---
 Marlin/src/feature/powerloss.cpp             | 28 +++++++++++++++++---
 Marlin/src/feature/powerloss.h               | 11 +++++++-
 Marlin/src/gcode/feature/powerloss/M1000.cpp |  2 ++
 Marlin/src/gcode/feature/powerloss/M413.cpp  |  1 +
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp
index ed3a4b9fade..faf6202dbd7 100644
--- a/Marlin/src/feature/powerloss.cpp
+++ b/Marlin/src/feature/powerloss.cpp
@@ -112,8 +112,7 @@ void PrintJobRecovery::check() {
   if (card.isMounted()) {
     load();
     if (!valid()) return cancel();
-    queue.inject_P(PSTR("M1000 S"));
-    TERN_(DWIN_CREALITY_LCD, dwin_flag = true);
+    queue.inject_P(PSTR("M1000S"));
   }
 }
 
@@ -227,6 +226,10 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/
     // Elapsed print job time
     info.print_job_elapsed = print_job_timer.duration();
 
+    // Misc. Marlin flags
+    info.flag.dryrun = !!(marlin_debug_flags & MARLIN_DEBUG_DRYRUN);
+    info.flag.allow_cold_extrusion = TERN0(PREVENT_COLD_EXTRUSION, thermalManager.allow_cold_extrude);
+
     write();
   }
 }
@@ -326,6 +329,12 @@ void PrintJobRecovery::resume() {
 
   const uint32_t resume_sdpos = info.sdpos; // Get here before the stepper ISR overwrites it
 
+  // Apply the dry-run flag if enabled
+  if (info.flag.dryrun) marlin_debug_flags |= MARLIN_DEBUG_DRYRUN;
+
+  // Restore cold extrusion permission
+  TERN_(PREVENT_COLD_EXTRUSION, thermalManager.allow_cold_extrude = info.flag.allow_cold_extrusion);
+
   #if HAS_LEVELING
     // Make sure leveling is off before any G92 and G28
     gcode.process_subcommands_now_P(PSTR("M420 S0 Z0"));
@@ -337,7 +346,7 @@ void PrintJobRecovery::resume() {
     // If Z homing goes to max, just reset E and home all
     gcode.process_subcommands_now_P(PSTR(
       "G92.9 E0\n"
-      "G28R0" TERN_(MARLIN_DEV_MODE, "S")
+      "G28R0"
     ));
 
   #else // "G92.9 E0 ..."
@@ -358,7 +367,6 @@ void PrintJobRecovery::resume() {
 
     gcode.process_subcommands_now_P(PSTR(
       "G28R0"                               // No raise during G28
-      TERN_(MARLIN_DEV_MODE, "S")           // Simulated Homing
       TERN_(IS_CARTESIAN, "XY")             // Don't home Z on Cartesian
     ));
 
@@ -498,6 +506,14 @@ void PrintJobRecovery::resume() {
     LOOP_XYZ(i) update_workspace_offset((AxisEnum)i);
   #endif
 
+  #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
+    const uint8_t old_flags = marlin_debug_flags;
+    marlin_debug_flags |= MARLIN_DEBUG_ECHO;
+  #endif
+
+  // Continue to apply PLR when a file is resumed!
+  enable(true);
+
   // Resume the SD file from the last position
   char *fn = info.sd_filename;
   extern const char M23_STR[];
@@ -505,6 +521,8 @@ void PrintJobRecovery::resume() {
   gcode.process_subcommands_now(cmd);
   sprintf_P(cmd, PSTR("M24 S%ld T%ld"), resume_sdpos, info.print_job_elapsed);
   gcode.process_subcommands_now(cmd);
+
+  TERN_(DEBUG_POWER_LOSS_RECOVERY, marlin_debug_flags = old_flags);
 }
 
 #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
@@ -584,6 +602,8 @@ void PrintJobRecovery::resume() {
         DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
         DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
         DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);
+        DEBUG_ECHOLNPAIR("dryrun: ", int(info.flag.dryrun));
+        DEBUG_ECHOLNPAIR("allow_cold_extrusion: ", int(info.flag.allow_cold_extrusion));
       }
       else
         DEBUG_ECHOLNPGM("INVALID DATA");
diff --git a/Marlin/src/feature/powerloss.h b/Marlin/src/feature/powerloss.h
index 1943175b056..e31b2ec915c 100644
--- a/Marlin/src/feature/powerloss.h
+++ b/Marlin/src/feature/powerloss.h
@@ -107,6 +107,12 @@ typedef struct {
   // Job elapsed time
   millis_t print_job_elapsed;
 
+  // Misc. Marlin flags
+  struct {
+    bool dryrun:1;                // M111 S8
+    bool allow_cold_extrusion:1;  // M302 P1
+  } flag;
+
   uint8_t valid_foot;
 
   bool valid() { return valid_head && valid_head == valid_foot; }
@@ -173,7 +179,10 @@ class PrintJobRecovery {
       }
     #endif
 
-    static inline bool valid() { return info.valid(); }
+    // The referenced file exists
+    static inline bool interrupted_file_exists() { return card.fileExists(info.sd_filename); }
+
+    static inline bool valid() { return info.valid() && interrupted_file_exists(); }
 
     #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
       static void debug(PGM_P const prefix);
diff --git a/Marlin/src/gcode/feature/powerloss/M1000.cpp b/Marlin/src/gcode/feature/powerloss/M1000.cpp
index 58e810e5d07..e9477dd2fbf 100644
--- a/Marlin/src/gcode/feature/powerloss/M1000.cpp
+++ b/Marlin/src/gcode/feature/powerloss/M1000.cpp
@@ -62,6 +62,8 @@ void GcodeSuite::M1000() {
     if (parser.seen('S')) {
       #if HAS_LCD_MENU
         ui.goto_screen(menu_job_recovery);
+      #elif ENABLED(DWIN_CREALITY_LCD)
+        recovery.dwin_flag = true;
       #elif ENABLED(EXTENSIBLE_UI)
         ExtUI::onPowerLossResume();
       #else
diff --git a/Marlin/src/gcode/feature/powerloss/M413.cpp b/Marlin/src/gcode/feature/powerloss/M413.cpp
index 5a08053e7c9..3538ccaa6e0 100644
--- a/Marlin/src/gcode/feature/powerloss/M413.cpp
+++ b/Marlin/src/gcode/feature/powerloss/M413.cpp
@@ -50,6 +50,7 @@ void GcodeSuite::M413() {
     if (parser.seen("RL")) recovery.load();
     if (parser.seen('W')) recovery.save(true);
     if (parser.seen('P')) recovery.purge();
+    if (parser.seen('D')) recovery.debug(PSTR("M413"));
     #if PIN_EXISTS(POWER_LOSS)
       if (parser.seen('O')) recovery._outage();
     #endif