From 1cb810ff1c04065daa29182a6c22ecf6b0c0098b Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Wed, 21 Mar 2018 19:30:06 -0500
Subject: [PATCH] [2.0.x] Automatically reset stepper timeout (#10179)

* Automatically reset stepper timeout in manage_inactivity

Any code that adds moves to the planner can skip resetting the stepper timeout. We can let `idle` / `manage_inactivity` reset the timer whenever it detects any moves in the planner.

* blocks_queued => has_blocks_queued
---
 Marlin/src/Marlin.cpp                       | 49 +++++++++++----------
 Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp |  2 +-
 Marlin/src/gcode/config/M43.cpp             |  5 +--
 Marlin/src/gcode/gcode.cpp                  |  7 +--
 Marlin/src/gcode/gcode.h                    |  4 +-
 Marlin/src/gcode/lcd/M0_M1.cpp              |  3 +-
 Marlin/src/gcode/motion/G2_G3.cpp           |  2 +-
 Marlin/src/gcode/queue.cpp                  |  1 -
 Marlin/src/gcode/temperature/M104_M109.cpp  |  2 +-
 Marlin/src/gcode/temperature/M140_M190.cpp  |  2 +-
 Marlin/src/lcd/ultralcd.cpp                 |  8 +---
 Marlin/src/module/motion.cpp                |  5 ---
 Marlin/src/module/planner.cpp               |  4 +-
 Marlin/src/module/planner.h                 |  8 ++--
 Marlin/src/module/probe.cpp                 |  3 --
 Marlin/src/module/stepper.cpp               |  4 +-
 16 files changed, 47 insertions(+), 62 deletions(-)

diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp
index c7ee0f407d..03ff2bac5c 100644
--- a/Marlin/src/Marlin.cpp
+++ b/Marlin/src/Marlin.cpp
@@ -336,7 +336,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
 
   const millis_t ms = millis();
 
-  if (max_inactive_time && ELAPSED(ms, gcode.previous_cmd_ms + max_inactive_time)) {
+  if (max_inactive_time && ELAPSED(ms, gcode.previous_move_ms + max_inactive_time)) {
     SERIAL_ERROR_START();
     SERIAL_ECHOLNPAIR(MSG_KILL_INACTIVE_TIME, parser.command_ptr);
     kill(PSTR(MSG_KILLED));
@@ -349,23 +349,26 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
     #define MOVE_AWAY_TEST true
   #endif
 
-  if (MOVE_AWAY_TEST && stepper_inactive_time && ELAPSED(ms, gcode.previous_cmd_ms + stepper_inactive_time)
-      && !ignore_stepper_queue && !planner.blocks_queued()) {
-    #if ENABLED(DISABLE_INACTIVE_X)
-      disable_X();
-    #endif
-    #if ENABLED(DISABLE_INACTIVE_Y)
-      disable_Y();
-    #endif
-    #if ENABLED(DISABLE_INACTIVE_Z)
-      disable_Z();
-    #endif
-    #if ENABLED(DISABLE_INACTIVE_E)
-      disable_e_steppers();
-    #endif
-    #if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTIPANEL)  // Only needed with an LCD
-      if (ubl.lcd_map_control) ubl.lcd_map_control = defer_return_to_status = false;
-    #endif
+  if (stepper_inactive_time) {
+    if (planner.has_blocks_queued())
+      gcode.previous_move_ms = ms; // reset_stepper_timeout to keep steppers powered
+    else if (MOVE_AWAY_TEST && !ignore_stepper_queue && ELAPSED(ms, gcode.previous_move_ms + stepper_inactive_time)) {
+      #if ENABLED(DISABLE_INACTIVE_X)
+        disable_X();
+      #endif
+      #if ENABLED(DISABLE_INACTIVE_Y)
+        disable_Y();
+      #endif
+      #if ENABLED(DISABLE_INACTIVE_Z)
+        disable_Z();
+      #endif
+      #if ENABLED(DISABLE_INACTIVE_E)
+        disable_e_steppers();
+      #endif
+      #if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTIPANEL)  // Only needed with an LCD
+        if (ubl.lcd_map_control) ubl.lcd_map_control = defer_return_to_status = false;
+      #endif
+    }
   }
 
   #ifdef CHDK // Check if pin should be set to LOW after M240 set it to HIGH
@@ -424,8 +427,8 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
 
   #if ENABLED(EXTRUDER_RUNOUT_PREVENT)
     if (thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP
-      && ELAPSED(ms, gcode.previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL)
-      && !planner.blocks_queued()
+      && ELAPSED(ms, gcode.previous_move_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL)
+      && !planner.has_blocks_queued()
     ) {
       #if ENABLED(SWITCHING_EXTRUDER)
         const bool oldstatus = E0_ENABLE_READ;
@@ -449,8 +452,6 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
         }
       #endif // !SWITCHING_EXTRUDER
 
-      gcode.refresh_cmd_timeout();
-
       const float olde = current_position[E_AXIS];
       current_position[E_AXIS] += EXTRUDER_RUNOUT_EXTRUDE;
       planner.buffer_line_kinematic(current_position, MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED), active_extruder);
@@ -476,6 +477,8 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
           #endif // E_STEPPERS > 1
         }
       #endif // !SWITCHING_EXTRUDER
+
+      gcode.previous_move_ms = ms; // reset_stepper_timeout to keep steppers powered
     }
   #endif // EXTRUDER_RUNOUT_PREVENT
 
@@ -541,7 +544,7 @@ void idle(
 
   #if ENABLED(I2C_POSITION_ENCODERS)
     static millis_t i2cpem_next_update_ms;
-    if (planner.blocks_queued() && ELAPSED(millis(), i2cpem_next_update_ms)) {
+    if (planner.has_blocks_queued() && ELAPSED(millis(), i2cpem_next_update_ms)) {
       I2CPEM.update();
       i2cpem_next_update_ms = millis() + I2CPE_MIN_UPD_TIME_MS;
     }
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index 686487f922..ceefbb1569 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -779,7 +779,7 @@
       wait_for_release();
       while (!is_lcd_clicked()) {
         idle();
-        gcode.refresh_cmd_timeout();
+        gcode.reset_stepper_timeout(); // Keep steppers powered
         if (encoder_diff) {
           do_blocking_move_to_z(current_position[Z_AXIS] + float(encoder_diff) * multiplier);
           encoder_diff = 0;
diff --git a/Marlin/src/gcode/config/M43.cpp b/Marlin/src/gcode/config/M43.cpp
index d9e78baa45..6247225738 100644
--- a/Marlin/src/gcode/config/M43.cpp
+++ b/Marlin/src/gcode/config/M43.cpp
@@ -155,8 +155,6 @@ inline void servo_probe_test() {
     } while (++i < 4);
     if (probe_inverting != deploy_state) SERIAL_PROTOCOLLNPGM("WARNING - INVERTING setting probably backwards");
 
-    gcode.refresh_cmd_timeout();
-
     if (deploy_state != stow_state) {
       SERIAL_PROTOCOLLNPGM("BLTouch clone detected");
       if (deploy_state) {
@@ -182,8 +180,7 @@ inline void servo_probe_test() {
 
         safe_delay(2);
 
-        if (0 == j % (500 * 1)) // keep cmd_timeout happy
-          gcode.refresh_cmd_timeout();
+        if (0 == j % (500 * 1)) gcode.reset_stepper_timeout(); // Keep steppers powered
 
         if (deploy_state != READ(PROBE_TEST_PIN)) { // probe triggered
 
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index deb3c09d44..a218baf864 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -43,7 +43,7 @@ GcodeSuite gcode;
 #include "../Marlin.h" // for idle() and suspend_auto_report
 
 uint8_t GcodeSuite::target_extruder;
-millis_t GcodeSuite::previous_cmd_ms;
+millis_t GcodeSuite::previous_move_ms;
 
 bool GcodeSuite::axis_relative_modes[] = AXIS_RELATIVE_MODES;
 
@@ -121,8 +121,7 @@ void GcodeSuite::get_destination_from_command() {
  * Dwell waits immediately. It does not synchronize. Use M400 instead of G4
  */
 void GcodeSuite::dwell(millis_t time) {
-  refresh_cmd_timeout();
-  time += previous_cmd_ms;
+  time += millis();
   while (PENDING(millis(), time)) idle();
 }
 
@@ -735,6 +734,8 @@ void GcodeSuite::process_next_command() {
     #endif
   }
 
+  reset_stepper_timeout(); // Keep steppers powered
+
   // Parse the next command in the queue
   parser.parse(current_command);
   process_parsed_command();
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 3fd16a95fc..a668c05f8d 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -280,8 +280,8 @@ public:
     static bool select_coordinate_system(const int8_t _new);
   #endif
 
-  static millis_t previous_cmd_ms;
-  FORCE_INLINE static void refresh_cmd_timeout() { previous_cmd_ms = millis(); }
+  static millis_t previous_move_ms;
+  FORCE_INLINE static void reset_stepper_timeout() { previous_move_ms = millis(); }
 
   static bool get_target_extruder_from_command();
   static void get_destination_from_command();
diff --git a/Marlin/src/gcode/lcd/M0_M1.cpp b/Marlin/src/gcode/lcd/M0_M1.cpp
index b09c2a9d55..4944cd11b6 100644
--- a/Marlin/src/gcode/lcd/M0_M1.cpp
+++ b/Marlin/src/gcode/lcd/M0_M1.cpp
@@ -75,10 +75,9 @@ void GcodeSuite::M0_M1() {
   wait_for_user = true;
 
   stepper.synchronize();
-  refresh_cmd_timeout();
 
   if (ms > 0) {
-    ms += previous_cmd_ms;  // wait until this time for a click
+    ms += previous_move_ms;  // wait until this time for a click
     while (PENDING(millis(), ms) && wait_for_user) idle();
   }
   else {
diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp
index 6ba2aa41a6..95ebba41eb 100644
--- a/Marlin/src/gcode/motion/G2_G3.cpp
+++ b/Marlin/src/gcode/motion/G2_G3.cpp
@@ -269,7 +269,7 @@ void GcodeSuite::G2_G3(const bool clockwise) {
 
       // Send the arc to the planner
       plan_arc(destination, arc_offset, clockwise);
-      refresh_cmd_timeout();
+      reset_stepper_timeout();
     }
     else {
       // Bad arguments
diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp
index e3f4b0bf7a..08ba22c43c 100644
--- a/Marlin/src/gcode/queue.cpp
+++ b/Marlin/src/gcode/queue.cpp
@@ -204,7 +204,6 @@ void ok_to_send() {
     const int16_t port = command_queue_port[cmd_queue_index_r];
     if (port < 0) return;
   #endif
-  gcode.refresh_cmd_timeout();
   if (!send_ok[cmd_queue_index_r]) return;
   SERIAL_PROTOCOLPGM_P(port, MSG_OK);
   #if ENABLED(ADVANCED_OK)
diff --git a/Marlin/src/gcode/temperature/M104_M109.cpp b/Marlin/src/gcode/temperature/M104_M109.cpp
index 2cd5f28768..e80541d20e 100644
--- a/Marlin/src/gcode/temperature/M104_M109.cpp
+++ b/Marlin/src/gcode/temperature/M104_M109.cpp
@@ -185,7 +185,7 @@ void GcodeSuite::M109() {
     }
 
     idle();
-    refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
+    reset_stepper_timeout(); // Keep steppers powered
 
     const float temp = thermalManager.degHotend(target_extruder);
 
diff --git a/Marlin/src/gcode/temperature/M140_M190.cpp b/Marlin/src/gcode/temperature/M140_M190.cpp
index 2acd930fd9..c0a7d7950a 100644
--- a/Marlin/src/gcode/temperature/M140_M190.cpp
+++ b/Marlin/src/gcode/temperature/M140_M190.cpp
@@ -122,7 +122,7 @@ void GcodeSuite::M190() {
     }
 
     idle();
-    refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
+    reset_stepper_timeout(); // Keep steppers powered
 
     const float temp = thermalManager.degBed();
 
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index 0564126410..a070467159 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -1885,7 +1885,6 @@ void kill_screen(const char* lcd_msg) {
       // Encoder knob or keypad buttons adjust the Z position
       //
       if (encoderPosition) {
-        gcode.refresh_cmd_timeout();
         const float z = current_position[Z_AXIS] + float((int32_t)encoderPosition) * (MBL_Z_STEP);
         line_to_z(constrain(z, -(LCD_PROBE_Z_RANGE) * 0.5, (LCD_PROBE_Z_RANGE) * 0.5));
         lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
@@ -2409,7 +2408,6 @@ void kill_screen(const char* lcd_msg) {
       stepper.cleaning_buffer_counter = 0;
       set_current_from_steppers_for_axis(ALL_AXES);
       sync_plan_position();
-      gcode.refresh_cmd_timeout();
     }
 
     void _lcd_ubl_output_map_lcd() {
@@ -2424,10 +2422,7 @@ void kill_screen(const char* lcd_msg) {
       if (encoderPosition) {
         step_scaler += (int32_t)encoderPosition;
         x_plot += step_scaler / (ENCODER_STEPS_PER_MENU_ITEM);
-        if (abs(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM)
-          step_scaler = 0;
-        gcode.refresh_cmd_timeout();
-
+        if (abs(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM) step_scaler = 0;
         encoderPosition = 0;
         lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
       }
@@ -2909,7 +2904,6 @@ void kill_screen(const char* lcd_msg) {
     if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
     ENCODER_DIRECTION_NORMAL();
     if (encoderPosition && !processing_manual_move) {
-      gcode.refresh_cmd_timeout();
 
       // Start with no limits to movement
       float min = current_position[axis] - 1000,
diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp
index 2f04af07bd..414c65e3ab 100644
--- a/Marlin/src/module/motion.cpp
+++ b/Marlin/src/module/motion.cpp
@@ -266,8 +266,6 @@ void buffer_line_to_destination(const float fr_mm_s) {
       if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_uninterpolated_move_to_destination", destination);
     #endif
 
-    gcode.refresh_cmd_timeout();
-
     #if UBL_SEGMENTED
       // ubl segmented line will do z-only moves in single segment
       ubl.prepare_segmented_line_to(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s));
@@ -435,12 +433,10 @@ void bracket_probe_move(const bool before) {
     saved_feedrate_mm_s = feedrate_mm_s;
     saved_feedrate_percentage = feedrate_percentage;
     feedrate_percentage = 100;
-    gcode.refresh_cmd_timeout();
   }
   else {
     feedrate_mm_s = saved_feedrate_mm_s;
     feedrate_percentage = saved_feedrate_percentage;
-    gcode.refresh_cmd_timeout();
   }
 }
 
@@ -859,7 +855,6 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
  */
 void prepare_move_to_destination() {
   clamp_to_software_endstops(destination);
-  gcode.refresh_cmd_timeout();
 
   #if ENABLED(PREVENT_COLD_EXTRUSION) || ENABLED(PREVENT_LENGTHY_EXTRUDE)
 
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 602e4691d1..f00798d992 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -468,7 +468,7 @@ void Planner::check_axes_activity() {
     #endif
   #endif
 
-  if (blocks_queued()) {
+  if (has_blocks_queued()) {
 
     #if FAN_COUNT > 0
       for (uint8_t i = 0; i < FAN_COUNT; i++)
@@ -1547,7 +1547,7 @@ void Planner::buffer_segment(const float &a, const float &b, const float &c, con
   //*/
 
   // Always split the first move into two (if not homing or probing)
-  if (!blocks_queued()) {
+  if (!has_blocks_queued()) {
 
     #define _BETWEEN(A) (position[A##_AXIS] + target[A##_AXIS]) >> 1
     const int32_t between[ABCE] = { _BETWEEN(A), _BETWEEN(B), _BETWEEN(C), _BETWEEN(E) };
diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h
index 4097c42b2e..da2cf36009 100644
--- a/Marlin/src/module/planner.h
+++ b/Marlin/src/module/planner.h
@@ -512,14 +512,14 @@ class Planner {
     /**
      * Does the buffer have any blocks queued?
      */
-    static bool blocks_queued() { return (block_buffer_head != block_buffer_tail); }
+    static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); }
 
     /**
      * "Discard" the block and "release" the memory.
      * Called when the current block is no longer needed.
      */
     FORCE_INLINE static void discard_current_block() {
-      if (blocks_queued())
+      if (has_blocks_queued())
         block_buffer_tail = BLOCK_MOD(block_buffer_tail + 1);
     }
 
@@ -528,7 +528,7 @@ class Planner {
      * Called after an interrupted move to throw away the rest of the move.
      */
     FORCE_INLINE static bool discard_continued_block() {
-      const bool discard = blocks_queued() && TEST(block_buffer[block_buffer_tail].flag, BLOCK_BIT_CONTINUED);
+      const bool discard = has_blocks_queued() && TEST(block_buffer[block_buffer_tail].flag, BLOCK_BIT_CONTINUED);
       if (discard) discard_current_block();
       return discard;
     }
@@ -539,7 +539,7 @@ class Planner {
      * WARNING: Called from Stepper ISR context!
      */
     static block_t* get_current_block() {
-      if (blocks_queued()) {
+      if (has_blocks_queued()) {
         block_t * const block = &block_buffer[block_buffer_tail];
 
         // If the block has no trapezoid calculated, it's unsafe to execute.
diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp
index 18e13fe318..2f70a28667 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -545,9 +545,6 @@ static float run_z_probe() {
     if (DEBUGGING(LEVELING)) DEBUG_POS(">>> run_z_probe", current_position);
   #endif
 
-  // Prevent stepper_inactive_time from running out and EXTRUDER_RUNOUT_PREVENT from extruding
-  gcode.refresh_cmd_timeout();
-
   // Double-probing does a fast probe followed by a slow probe
   #if MULTIPLE_PROBING == 2
 
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index bdb25bbf6a..d566f295ea 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -1091,7 +1091,7 @@ void Stepper::init() {
 /**
  * Block until all buffered steps are executed / cleaned
  */
-void Stepper::synchronize() { while (planner.blocks_queued() || cleaning_buffer_counter) idle(); }
+void Stepper::synchronize() { while (planner.has_blocks_queued() || cleaning_buffer_counter) idle(); }
 
 /**
  * Set the stepper positions directly in steps
@@ -1191,7 +1191,7 @@ void Stepper::finish_and_disable() {
 void Stepper::quick_stop() {
   cleaning_buffer_counter = 5000;
   DISABLE_STEPPER_DRIVER_INTERRUPT();
-  while (planner.blocks_queued()) planner.discard_current_block();
+  while (planner.has_blocks_queued()) planner.discard_current_block();
   current_block = NULL;
   ENABLE_STEPPER_DRIVER_INTERRUPT();
   #if ENABLED(ULTRA_LCD)