Browse Source

[2.0.x] better reverse pass (#8722)

* repair reverse_pass()

And make it readeble.
This was broken a long time ago.
Not competely unfunctional but far from optimal.

* Minor speedup when calling calculate_trapezoid_for_block

2 float / to 1 foat / and 2 float *

* Various style changes
AnHardt 7 years ago
parent
commit
b3daf6b5db
2 changed files with 46 additions and 42 deletions
  1. 24
    29
      Marlin/src/module/planner.cpp
  2. 22
    13
      Marlin/src/module/planner.h

+ 24
- 29
Marlin/src/module/planner.cpp View File

258
 
258
 
259
 
259
 
260
 // The kernel called by recalculate() when scanning the plan from last to first entry.
260
 // The kernel called by recalculate() when scanning the plan from last to first entry.
261
-void Planner::reverse_pass_kernel(block_t* const current, const block_t *next) {
261
+void Planner::reverse_pass_kernel(block_t* const current, const block_t * const next) {
262
   if (!current || !next) return;
262
   if (!current || !next) return;
263
   // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
263
   // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
264
   // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and
264
   // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and
279
  * Once in reverse and once forward. This implements the reverse pass.
279
  * Once in reverse and once forward. This implements the reverse pass.
280
  */
280
  */
281
 void Planner::reverse_pass() {
281
 void Planner::reverse_pass() {
282
-
283
   if (movesplanned() > 3) {
282
   if (movesplanned() > 3) {
284
-
285
-    block_t* block[3] = { NULL, NULL, NULL };
286
-
287
-    // Make a local copy of block_buffer_tail, because the interrupt can alter it
288
-    // Is a critical section REALLY needed for a single byte change?
289
-    //CRITICAL_SECTION_START;
290
-    uint8_t tail = block_buffer_tail;
291
-    //CRITICAL_SECTION_END
292
-
293
-    uint8_t b = BLOCK_MOD(block_buffer_head - 3);
294
-    while (b != tail) {
295
-      if (block[0] && TEST(block[0]->flag, BLOCK_BIT_START_FROM_FULL_HALT)) break;
296
-      b = prev_block_index(b);
297
-      block[2] = block[1];
298
-      block[1] = block[0];
299
-      block[0] = &block_buffer[b];
300
-      reverse_pass_kernel(block[1], block[2]);
301
-    }
283
+    const uint8_t endnr = BLOCK_MOD(block_buffer_tail + 2); // tail is running. tail+1 shouldn't be altered because it's connected to the running block.
284
+                                                            // tail+2 because the index is not yet advanced when checked
285
+    uint8_t blocknr = prev_block_index(block_buffer_head);
286
+    block_t* current = &block_buffer[blocknr];
287
+
288
+    do {
289
+      const block_t * const next = current;
290
+      blocknr = prev_block_index(blocknr);
291
+      current = &block_buffer[blocknr];
292
+      if (TEST(current->flag, BLOCK_BIT_START_FROM_FULL_HALT)) // Up to this every block is already optimized.
293
+        break;
294
+      reverse_pass_kernel(current, next);
295
+    } while (blocknr != endnr);
302
   }
296
   }
303
 }
297
 }
304
 
298
 
305
 // The kernel called by recalculate() when scanning the plan from first to last entry.
299
 // The kernel called by recalculate() when scanning the plan from first to last entry.
306
-void Planner::forward_pass_kernel(const block_t* previous, block_t* const current) {
300
+void Planner::forward_pass_kernel(const block_t * const previous, block_t* const current) {
307
   if (!previous) return;
301
   if (!previous) return;
308
 
302
 
309
   // If the previous block is an acceleration block, but it is not long enough to complete the
303
   // If the previous block is an acceleration block, but it is not long enough to complete the
355
       // Recalculate if current block entry or exit junction speed has changed.
349
       // Recalculate if current block entry or exit junction speed has changed.
356
       if (TEST(current->flag, BLOCK_BIT_RECALCULATE) || TEST(next->flag, BLOCK_BIT_RECALCULATE)) {
350
       if (TEST(current->flag, BLOCK_BIT_RECALCULATE) || TEST(next->flag, BLOCK_BIT_RECALCULATE)) {
357
         // NOTE: Entry and exit factors always > 0 by all previous logic operations.
351
         // NOTE: Entry and exit factors always > 0 by all previous logic operations.
358
-        float nom = current->nominal_speed;
359
-        calculate_trapezoid_for_block(current, current->entry_speed / nom, next->entry_speed / nom);
352
+        const float nomr = 1.0 / current->nominal_speed;
353
+        calculate_trapezoid_for_block(current, current->entry_speed * nomr, next->entry_speed * nomr);
360
         CBI(current->flag, BLOCK_BIT_RECALCULATE); // Reset current only to ensure next trapezoid is computed
354
         CBI(current->flag, BLOCK_BIT_RECALCULATE); // Reset current only to ensure next trapezoid is computed
361
       }
355
       }
362
     }
356
     }
364
   }
358
   }
365
   // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.
359
   // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.
366
   if (next) {
360
   if (next) {
367
-    float nom = next->nominal_speed;
368
-    calculate_trapezoid_for_block(next, next->entry_speed / nom, (MINIMUM_PLANNER_SPEED) / nom);
361
+    const float nomr = 1.0 / next->nominal_speed;
362
+    calculate_trapezoid_for_block(next, next->entry_speed * nomr, (MINIMUM_PLANNER_SPEED) * nomr);
369
     CBI(next->flag, BLOCK_BIT_RECALCULATE);
363
     CBI(next->flag, BLOCK_BIT_RECALCULATE);
370
   }
364
   }
371
 }
365
 }
1020
       #endif
1014
       #endif
1021
     );
1015
     );
1022
   }
1016
   }
1023
-  float inverse_millimeters = 1.0 / block->millimeters;  // Inverse millimeters to remove multiple divides
1017
+  const float inverse_millimeters = 1.0 / block->millimeters;  // Inverse millimeters to remove multiple divides
1024
 
1018
 
1025
   // Calculate inverse time for this move. No divide by zero due to previous checks.
1019
   // Calculate inverse time for this move. No divide by zero due to previous checks.
1026
   // Example: At 120mm/s a 60mm move takes 0.5s. So this will give 2.0.
1020
   // Example: At 120mm/s a 60mm move takes 0.5s. So this will give 2.0.
1059
     //FMM update ring buffer used for delay with filament measurements
1053
     //FMM update ring buffer used for delay with filament measurements
1060
     if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM && filwidth_delay_index[1] >= 0) {  //only for extruder with filament sensor and if ring buffer is initialized
1054
     if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM && filwidth_delay_index[1] >= 0) {  //only for extruder with filament sensor and if ring buffer is initialized
1061
 
1055
 
1062
-      const int MMD_CM = MAX_MEASUREMENT_DELAY + 1, MMD_MM = MMD_CM * 10;
1056
+      constexpr int MMD_CM = MAX_MEASUREMENT_DELAY + 1, MMD_MM = MMD_CM * 10;
1063
 
1057
 
1064
       // increment counters with next move in e axis
1058
       // increment counters with next move in e axis
1065
       filwidth_e_count += delta_mm[E_AXIS];
1059
       filwidth_e_count += delta_mm[E_AXIS];
1356
 
1350
 
1357
   #endif // LIN_ADVANCE
1351
   #endif // LIN_ADVANCE
1358
 
1352
 
1359
-  calculate_trapezoid_for_block(block, block->entry_speed / block->nominal_speed, safe_speed / block->nominal_speed);
1353
+  const float bnsr = 1.0 / block->nominal_speed;
1354
+  calculate_trapezoid_for_block(block, block->entry_speed * bnsr, safe_speed * bnsr);
1360
 
1355
 
1361
   // Move buffer head
1356
   // Move buffer head
1362
   block_buffer_head = next_buffer_head;
1357
   block_buffer_head = next_buffer_head;
1363
 
1358
 
1364
   // Update the position (only when a move was queued)
1359
   // Update the position (only when a move was queued)
1365
-  static_assert(COUNT(target) > 1, "array as function parameter should be declared as reference and with count");
1360
+  static_assert(COUNT(target) > 1, "Parameter to _buffer_steps must be (&target)[XYZE]!");
1366
   COPY(position, target);
1361
   COPY(position, target);
1367
 
1362
 
1368
   recalculate();
1363
   recalculate();

+ 22
- 13
Marlin/src/module/planner.h View File

134
 #define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
134
 #define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
135
 
135
 
136
 class Planner {
136
 class Planner {
137
-
138
   public:
137
   public:
139
 
138
 
140
     /**
139
     /**
141
-     * A ring buffer of moves described in steps
140
+     * The move buffer, calculated in stepper steps
141
+     *
142
+     * block_buffer is a ring buffer...
143
+     *
144
+     *             head,tail : indexes for write,read
145
+     *            head==tail : the buffer is empty
146
+     *            head!=tail : blocks are in the buffer
147
+     *   head==(tail-1)%size : the buffer is full
148
+     *
149
+     *  Writer of head is Planner::_buffer_line().
150
+     *  Reader of tail is Stepper::isr(). Always consider tail busy / read-only
142
      */
151
      */
143
     static block_t block_buffer[BLOCK_BUFFER_SIZE];
152
     static block_t block_buffer[BLOCK_BUFFER_SIZE];
144
-    static volatile uint8_t block_buffer_head,  // Index of the next block to be pushed
145
-                            block_buffer_tail;
153
+    static volatile uint8_t block_buffer_head,      // Index of the next block to be pushed
154
+                            block_buffer_tail;      // Index of the busy block, if any
146
 
155
 
147
     #if ENABLED(DISTINCT_E_FACTORS)
156
     #if ENABLED(DISTINCT_E_FACTORS)
148
-      static uint8_t last_extruder;             // Respond to extruder change
157
+      static uint8_t last_extruder;                 // Respond to extruder change
149
     #endif
158
     #endif
150
 
159
 
151
-    static int16_t flow_percentage[EXTRUDERS]; // Extrusion factor for each extruder
160
+    static int16_t flow_percentage[EXTRUDERS];      // Extrusion factor for each extruder
152
 
161
 
153
     static float e_factor[EXTRUDERS],               // The flow percentage and volumetric multiplier combine to scale E movement
162
     static float e_factor[EXTRUDERS],               // The flow percentage and volumetric multiplier combine to scale E movement
154
                  filament_size[EXTRUDERS],          // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder
163
                  filament_size[EXTRUDERS],          // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder
156
                  volumetric_multiplier[EXTRUDERS];  // Reciprocal of cross-sectional area of filament (in mm^2). Pre-calculated to reduce computation in the planner
165
                  volumetric_multiplier[EXTRUDERS];  // Reciprocal of cross-sectional area of filament (in mm^2). Pre-calculated to reduce computation in the planner
157
                                                     // May be auto-adjusted by a filament width sensor
166
                                                     // May be auto-adjusted by a filament width sensor
158
 
167
 
159
-    static float max_feedrate_mm_s[XYZE_N],     // Max speeds in mm per second
168
+    static float max_feedrate_mm_s[XYZE_N],         // Max speeds in mm per second
160
                  axis_steps_per_mm[XYZE_N],
169
                  axis_steps_per_mm[XYZE_N],
161
                  steps_to_mm[XYZE_N];
170
                  steps_to_mm[XYZE_N];
162
     static uint32_t max_acceleration_steps_per_s2[XYZE_N],
171
     static uint32_t max_acceleration_steps_per_s2[XYZE_N],
277
     /**
286
     /**
278
      * Number of moves currently in the planner
287
      * Number of moves currently in the planner
279
      */
288
      */
280
-    static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); }
289
+    FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); }
281
 
290
 
282
-    static bool is_full() { return (block_buffer_tail == BLOCK_MOD(block_buffer_head + 1)); }
291
+    FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
283
 
292
 
284
     // Update multipliers based on new diameter measurements
293
     // Update multipliers based on new diameter measurements
285
     static void calculate_volumetric_multipliers();
294
     static void calculate_volumetric_multipliers();
533
     /**
542
     /**
534
      * Get the index of the next / previous block in the ring buffer
543
      * Get the index of the next / previous block in the ring buffer
535
      */
544
      */
536
-    static int8_t next_block_index(const int8_t block_index) { return BLOCK_MOD(block_index + 1); }
537
-    static int8_t prev_block_index(const int8_t block_index) { return BLOCK_MOD(block_index - 1); }
545
+    static constexpr int8_t next_block_index(const int8_t block_index) { return BLOCK_MOD(block_index + 1); }
546
+    static constexpr int8_t prev_block_index(const int8_t block_index) { return BLOCK_MOD(block_index - 1); }
538
 
547
 
539
     /**
548
     /**
540
      * Calculate the distance (not time) it takes to accelerate
549
      * Calculate the distance (not time) it takes to accelerate
569
 
578
 
570
     static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
579
     static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
571
 
580
 
572
-    static void reverse_pass_kernel(block_t* const current, const block_t *next);
573
-    static void forward_pass_kernel(const block_t *previous, block_t* const current);
581
+    static void reverse_pass_kernel(block_t* const current, const block_t * const next);
582
+    static void forward_pass_kernel(const block_t * const previous, block_t* const current);
574
 
583
 
575
     static void reverse_pass();
584
     static void reverse_pass();
576
     static void forward_pass();
585
     static void forward_pass();

Loading…
Cancel
Save