From cfcd0695017193d34e307d59917c10de8a4fc3dd Mon Sep 17 00:00:00 2001
From: Ross Allan <ross@nallar.me>
Date: Mon, 19 Jun 2017 11:14:05 +0100
Subject: [PATCH] Fix #5699 - LIN_ADVANCE freeze when ADV_RATE returns 0

---
 Marlin/stepper.cpp | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index f3c2ff1d62..2f8fc6dfcf 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -110,9 +110,22 @@ volatile uint32_t Stepper::step_events_completed = 0; // The number of step even
          Stepper::advance;
   #endif
 
-  #define ADV_RATE(T, L) (e_steps[TOOL_E_INDEX] ? (T) * (L) / abs(e_steps[TOOL_E_INDEX]) : ADV_NEVER)
+  /**
+   * See https://github.com/MarlinFirmware/Marlin/issues/5699#issuecomment-309264382
+   *
+   * This fix isn't perfect and may lose steps - but better than locking up completely
+   * in future the planner should slow down if advance stepping rate would be too high
+   */
+  FORCE_INLINE uint16_t adv_rate(const int steps, const uint16_t timer, const uint8_t loops) {
+    if (steps) {
+      const uint16_t rate = (timer * loops) / abs(steps);
+      //return constrain(rate, 1, ADV_NEVER - 1)
+      return rate ? rate : 1;
+    }
+    return ADV_NEVER;
+  }
 
-#endif
+#endif // ADVANCE || LIN_ADVANCE
 
 long Stepper::acceleration_time, Stepper::deceleration_time;
 
@@ -743,7 +756,7 @@ void Stepper::isr() {
     #endif // ADVANCE or LIN_ADVANCE
 
     #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
-      eISR_Rate = ADV_RATE(timer, step_loops);
+      eISR_Rate = adv_rate(e_steps[TOOL_E_INDEX], timer, step_loops);
     #endif
   }
   else if (step_events_completed > (uint32_t)current_block->decelerate_after) {
@@ -797,7 +810,7 @@ void Stepper::isr() {
     #endif // ADVANCE or LIN_ADVANCE
 
     #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
-      eISR_Rate = ADV_RATE(timer, step_loops);
+      eISR_Rate = adv_rate(e_steps[TOOL_E_INDEX], timer, step_loops);
     #endif
   }
   else {
@@ -807,7 +820,7 @@ void Stepper::isr() {
       if (current_block->use_advance_lead)
         current_estep_rate[TOOL_E_INDEX] = final_estep_rate;
 
-      eISR_Rate = ADV_RATE(OCR1A_nominal, step_loops_nominal);
+      eISR_Rate = adv_rate(e_steps[TOOL_E_INDEX], OCR1A_nominal, step_loops_nominal);
 
     #endif