Browse Source

Alternative schedule for LA ticks

Remove most of the original complexity from advance_spread.

Instead of accumulating time to be scheduled, plan ahead of time each
eISR tick using the next main interval + an accumulator (eISR_Err),
which keeps everything much simpler.

The distribution of the advance ticks is now using the real LA
frequency, which leaves a bit more time between the last LA tick and
the main stepper isr.

We take advantage of the accumulator to force a LA tick right after the
first main tick, which removes a +/- 1 scheduling error at higher step
rates.

When decompressing, we force 2 steps instead, so that the direction
reversal happens immediately (first tick zeros esteps, second inverts
the sign), removing another +/- 1 error at higher step rates.
Yuri D'Elia 3 years ago
parent
commit
feafc5e5ab
1 changed files with 16 additions and 23 deletions
  1. 16 23
      Firmware/stepper.cpp

+ 16 - 23
Firmware/stepper.cpp

@@ -125,7 +125,7 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
 
   static uint16_t main_Rate;
   static uint16_t eISR_Rate;
-  static uint16_t eISR_Err;
+  static uint32_t eISR_Err;
 
   static uint16_t current_adv_steps;
   static uint16_t target_adv_steps;
@@ -733,38 +733,30 @@ FORCE_INLINE uint16_t fastdiv(uint16_t q, uint8_t d)
 
 FORCE_INLINE void advance_spread(uint16_t timer)
 {
-    if(eISR_Err > timer)
+    eISR_Err += timer;
+
+    uint8_t ticks = 0;
+    while(eISR_Err >= current_block->advance_rate)
+    {
+        ++ticks;
+        eISR_Err -= current_block->advance_rate;
+    }
+    if(!ticks)
     {
-        // advance-step skipped
-        eISR_Err -= timer;
         eISR_Rate = timer;
         nextAdvanceISR = timer;
         return;
     }
 
-    // at least one step
-    uint8_t ticks = 1;
-    uint32_t block = current_block->advance_rate;
-    uint16_t max_t = timer - eISR_Err;
-    while (block < max_t)
-    {
-        ++ticks;
-        block += current_block->advance_rate;
-    }
-    if (block > timer)
-        eISR_Err += block - timer;
-    else
-        eISR_Err -= timer - block;
-
-    if (ticks <= 4)
-        eISR_Rate = fastdiv(timer, ticks);
+    if (ticks <= 3)
+        eISR_Rate = fastdiv(timer, ticks + 1);
     else
     {
         // >4 ticks are still possible on slow moves
-        eISR_Rate = timer / ticks;
+        eISR_Rate = timer / (ticks + 1);
     }
 
-    nextAdvanceISR = eISR_Rate / 2;
+    nextAdvanceISR = eISR_Rate;
 }
 #endif
 
@@ -876,11 +868,12 @@ FORCE_INLINE void isr() {
         }
         else {
             // reset error and iterations per loop for this phase
-            eISR_Err = current_block->advance_rate / 4;
+            eISR_Err = current_block->advance_rate;
             e_step_loops = current_block->advance_step_loops;
 
             if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) {
                 // LA could reverse the direction of extrusion in this phase
+                eISR_Err += current_block->advance_rate;
                 LA_phase = 0;
             }
         }