Subversion Repositories MK-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
/**
2
 * Marlin 3D Printer Firmware
3
 * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
 *
5
 * Based on Sprinter and grbl.
6
 * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
 
23
/**
24
 * planner.h
25
 *
26
 * Buffer movement commands and manage the acceleration profile plan
27
 *
28
 * Derived from Grbl
29
 * Copyright (c) 2009-2011 Simen Svale Skogsrud
30
 */
31
 
32
#ifndef PLANNER_H
33
#define PLANNER_H
34
 
35
#include "types.h"
36
#include "enum.h"
37
#include "Marlin.h"
38
 
39
#if ABL_PLANAR
40
  #include "vector_3.h"
41
#endif
42
 
43
enum BlockFlagBit : char {
44
  // Recalculate trapezoids on entry junction. For optimization.
45
  BLOCK_BIT_RECALCULATE,
46
 
47
  // Nominal speed always reached.
48
  // i.e., The segment is long enough, so the nominal speed is reachable if accelerating
49
  // from a safe speed (in consideration of jerking from zero speed).
50
  BLOCK_BIT_NOMINAL_LENGTH,
51
 
52
  // The block is segment 2+ of a longer move
53
  BLOCK_BIT_CONTINUED,
54
 
55
  // Sync the stepper counts from the block
56
  BLOCK_BIT_SYNC_POSITION
57
};
58
 
59
enum BlockFlag : char {
60
  BLOCK_FLAG_RECALCULATE          = _BV(BLOCK_BIT_RECALCULATE),
61
  BLOCK_FLAG_NOMINAL_LENGTH       = _BV(BLOCK_BIT_NOMINAL_LENGTH),
62
  BLOCK_FLAG_CONTINUED            = _BV(BLOCK_BIT_CONTINUED),
63
  BLOCK_FLAG_SYNC_POSITION        = _BV(BLOCK_BIT_SYNC_POSITION)
64
};
65
 
66
/**
67
 * struct block_t
68
 *
69
 * A single entry in the planner buffer.
70
 * Tracks linear movement over multiple axes.
71
 *
72
 * The "nominal" values are as-specified by gcode, and
73
 * may never actually be reached due to acceleration limits.
74
 */
75
typedef struct {
76
 
77
  volatile uint8_t flag;                    // Block flags (See BlockFlag enum above) - Modified by ISR and main thread!
78
 
79
  #if ENABLED(UNREGISTERED_MOVE_SUPPORT)
80
    bool count_it;
81
  #endif
82
 
83
  // Fields used by the motion planner to manage acceleration
84
  float nominal_speed_sqr,                  // The nominal speed for this block in (mm/sec)^2
85
        entry_speed_sqr,                    // Entry speed at previous-current junction in (mm/sec)^2
86
        max_entry_speed_sqr,                // Maximum allowable junction entry speed in (mm/sec)^2
87
        millimeters,                        // The total travel of this block in mm
88
        acceleration;                       // acceleration mm/sec^2
89
 
90
  union {
91
    // Data used by all move blocks
92
    struct {
93
      // Fields used by the Bresenham algorithm for tracing the line
94
      uint32_t steps[NUM_AXIS];             // Step count along each axis
95
    };
96
    // Data used by all sync blocks
97
    struct {
98
      int32_t position[NUM_AXIS];           // New position to force when this sync block is executed
99
    };
100
  };
101
  uint32_t step_event_count;                // The number of step events required to complete this block
102
 
103
  uint8_t active_extruder;                  // The extruder to move (if E move)
104
 
105
  #if ENABLED(MIXING_EXTRUDER)
106
    uint32_t mix_steps[MIXING_STEPPERS];    // Scaled steps[E_AXIS] for the mixing steppers
107
  #endif
108
 
109
  // Settings for the trapezoid generator
110
  uint32_t accelerate_until,                // The index of the step event on which to stop acceleration
111
           decelerate_after;                // The index of the step event on which to start decelerating
112
 
113
  #if ENABLED(S_CURVE_ACCELERATION)
114
    uint32_t cruise_rate,                   // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
115
             acceleration_time,             // Acceleration time and deceleration time in STEP timer counts
116
             deceleration_time,
117
             acceleration_time_inverse,     // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
118
             deceleration_time_inverse;
119
  #else
120
    uint32_t acceleration_rate;             // The acceleration rate used for acceleration calculation
121
  #endif
122
 
123
  uint8_t direction_bits;                   // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
124
 
125
  // Advance extrusion
126
  #if ENABLED(LIN_ADVANCE)
127
    bool use_advance_lead;
128
    uint16_t advance_speed,                 // STEP timer value for extruder speed offset ISR
129
             max_adv_steps,                 // max. advance steps to get cruising speed pressure (not always nominal_speed!)
130
             final_adv_steps;               // advance steps due to exit speed
131
    float e_D_ratio;
132
  #endif
133
 
134
  uint32_t nominal_rate,                    // The nominal step rate for this block in step_events/sec
135
           initial_rate,                    // The jerk-adjusted step rate at start of block
136
           final_rate,                      // The minimal rate at exit
137
           acceleration_steps_per_s2;       // acceleration steps/sec^2
138
 
139
  #if FAN_COUNT > 0
140
    uint16_t fan_speed[FAN_COUNT];
141
  #endif
142
 
143
  #if ENABLED(BARICUDA)
144
    uint8_t valve_pressure, e_to_p_pressure;
145
  #endif
146
 
147
  uint32_t segment_time_us;
148
 
149
} block_t;
150
 
151
#define HAS_POSITION_FLOAT (ENABLED(LIN_ADVANCE) || HAS_FEEDRATE_SCALING)
152
 
153
#define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
154
 
155
class Planner {
156
  public:
157
 
158
    /**
159
     * The move buffer, calculated in stepper steps
160
     *
161
     * block_buffer is a ring buffer...
162
     *
163
     *             head,tail : indexes for write,read
164
     *            head==tail : the buffer is empty
165
     *            head!=tail : blocks are in the buffer
166
     *   head==(tail-1)%size : the buffer is full
167
     *
168
     *  Writer of head is Planner::buffer_segment().
169
     *  Reader of tail is Stepper::isr(). Always consider tail busy / read-only
170
     */
171
    static block_t block_buffer[BLOCK_BUFFER_SIZE];
172
    static volatile uint8_t block_buffer_head,      // Index of the next block to be pushed
173
                            block_buffer_nonbusy,   // Index of the first non busy block
174
                            block_buffer_planned,   // Index of the optimally planned block
175
                            block_buffer_tail;      // Index of the busy block, if any
176
    static uint16_t cleaning_buffer_counter;        // A counter to disable queuing of blocks
177
    static uint8_t delay_before_delivering;         // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks
178
 
179
 
180
    #if ENABLED(DISTINCT_E_FACTORS)
181
      static uint8_t last_extruder;                 // Respond to extruder change
182
    #endif
183
 
184
    static int16_t flow_percentage[EXTRUDERS];      // Extrusion factor for each extruder
185
 
186
    static float e_factor[EXTRUDERS];               // The flow percentage and volumetric multiplier combine to scale E movement
187
 
188
    #if DISABLED(NO_VOLUMETRICS)
189
      static float filament_size[EXTRUDERS],          // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder
190
                   volumetric_area_nominal,           // Nominal cross-sectional area
191
                   volumetric_multiplier[EXTRUDERS];  // Reciprocal of cross-sectional area of filament (in mm^2). Pre-calculated to reduce computation in the planner
192
                                                      // May be auto-adjusted by a filament width sensor
193
    #endif
194
 
195
    static uint32_t max_acceleration_mm_per_s2[NUM_AXIS_N],    // (mm/s^2) M201 XYZE
196
                    max_acceleration_steps_per_s2[NUM_AXIS_N], // (steps/s^2) Derived from mm_per_s2
197
                    min_segment_time_us;                       // (µs) M205 Q
198
    static float max_feedrate_mm_s[NUM_AXIS_N], // (mm/s) M203 XYZE - Max speeds
199
                 axis_steps_per_mm[NUM_AXIS_N], // (steps) M92 XYZE - Steps per millimeter
200
                 steps_to_mm[NUM_AXIS_N],       // (mm) Millimeters per step
201
                 min_feedrate_mm_s,             // (mm/s) M205 S - Minimum linear feedrate
202
                 acceleration,                  // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
203
                 retract_acceleration,          // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
204
                 travel_acceleration,           // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
205
                 min_travel_feedrate_mm_s;      // (mm/s) M205 T - Minimum travel feedrate
206
 
207
    #if ENABLED(JUNCTION_DEVIATION)
208
      static float junction_deviation_mm;       // (mm) M205 J
209
      #if ENABLED(LIN_ADVANCE)
210
        #if ENABLED(DISTINCT_E_FACTORS)
211
          static float max_e_jerk[EXTRUDERS];   // Calculated from junction_deviation_mm
212
        #else
213
          static float max_e_jerk;
214
        #endif
215
      #endif
216
    #else
217
      static float max_jerk[NUM_AXIS];          // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration.
218
    #endif
219
 
220
    #if ENABLED(LINE_BUILDUP_COMPENSATION_FEATURE)
221
      /*
222
       * Parameters for calculating target[]
223
       * See buildup compensation theory:
224
       *   https://vitana.se/opr3d/tbear/2017.html#hangprinter_project_29
225
       */
226
      static float k0[MOV_AXIS],
227
                   k1[MOV_AXIS],
228
                   k2[MOV_AXIS],
229
                   sqrtk1[MOV_AXIS];
230
    #endif
231
 
232
    #if HAS_LEVELING
233
      static bool leveling_active;          // Flag that bed leveling is enabled
234
      #if ABL_PLANAR
235
        static matrix_3x3 bed_level_matrix; // Transform to compensate for bed level
236
      #endif
237
      #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
238
        static float z_fade_height, inverse_z_fade_height;
239
      #endif
240
    #else
241
      static constexpr bool leveling_active = false;
242
    #endif
243
 
244
    #if ENABLED(LIN_ADVANCE)
245
      static float extruder_advance_K;
246
    #endif
247
 
248
    #if HAS_POSITION_FLOAT
249
      static float position_float[NUM_AXIS];
250
    #endif
251
 
252
    #if ENABLED(SKEW_CORRECTION)
253
      #if ENABLED(SKEW_CORRECTION_GCODE)
254
        static float xy_skew_factor;
255
      #else
256
        static constexpr float xy_skew_factor = XY_SKEW_FACTOR;
257
      #endif
258
      #if ENABLED(SKEW_CORRECTION_FOR_Z)
259
        #if ENABLED(SKEW_CORRECTION_GCODE)
260
          static float xz_skew_factor, yz_skew_factor;
261
        #else
262
          static constexpr float xz_skew_factor = XZ_SKEW_FACTOR, yz_skew_factor = YZ_SKEW_FACTOR;
263
        #endif
264
      #else
265
        static constexpr float xz_skew_factor = 0, yz_skew_factor = 0;
266
      #endif
267
    #endif
268
 
269
    #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
270
      static bool abort_on_endstop_hit;
271
    #endif
272
 
273
  private:
274
 
275
    /**
276
     * The current position of the tool in absolute steps
277
     * Recalculated if any axis_steps_per_mm are changed by gcode
278
     */
279
    static int32_t position[NUM_AXIS];
280
 
281
    /**
282
     * Speed of previous path line segment
283
     */
284
    static float previous_speed[NUM_AXIS];
285
 
286
    /**
287
     * Nominal speed of previous path line segment (mm/s)^2
288
     */
289
    static float previous_nominal_speed_sqr;
290
 
291
    /**
292
     * Limit where 64bit math is necessary for acceleration calculation
293
     */
294
    static uint32_t cutoff_long;
295
 
296
    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
297
      static float last_fade_z;
298
    #endif
299
 
300
    #if ENABLED(DISABLE_INACTIVE_EXTRUDER)
301
      /**
302
       * Counters to manage disabling inactive extruders
303
       */
304
      static uint8_t g_uc_extruder_last_move[EXTRUDERS];
305
    #endif // DISABLE_INACTIVE_EXTRUDER
306
 
307
    #ifdef XY_FREQUENCY_LIMIT
308
      // Used for the frequency limit
309
      #define MAX_FREQ_TIME_US (uint32_t)(1000000.0 / XY_FREQUENCY_LIMIT)
310
      // Old direction bits. Used for speed calculations
311
      static unsigned char old_direction_bits;
312
      // Segment times (in µs). Used for speed calculations
313
      static uint32_t axis_segment_time_us[2][3];
314
    #endif
315
 
316
    #if ENABLED(ULTRA_LCD)
317
      volatile static uint32_t block_buffer_runtime_us; //Theoretical block buffer runtime in µs
318
    #endif
319
 
320
  public:
321
 
322
    /**
323
     * Instance Methods
324
     */
325
 
326
    Planner();
327
 
328
    void init();
329
 
330
    /**
331
     * Static (class) Methods
332
     */
333
 
334
    static void reset_acceleration_rates();
335
    static void refresh_positioning();
336
 
337
    FORCE_INLINE static void refresh_e_factor(const uint8_t e) {
338
      e_factor[e] = (flow_percentage[e] * 0.01f
339
        #if DISABLED(NO_VOLUMETRICS)
340
          * volumetric_multiplier[e]
341
        #endif
342
      );
343
    }
344
 
345
    // Manage fans, paste pressure, etc.
346
    static void check_axes_activity();
347
 
348
    // Update multipliers based on new diameter measurements
349
    static void calculate_volumetric_multipliers();
350
 
351
    #if ENABLED(FILAMENT_WIDTH_SENSOR)
352
      void calculate_volumetric_for_width_sensor(const int8_t encoded_ratio);
353
    #endif
354
 
355
    #if DISABLED(NO_VOLUMETRICS)
356
 
357
      FORCE_INLINE static void set_filament_size(const uint8_t e, const float &v) {
358
        filament_size[e] = v;
359
        // make sure all extruders have some sane value for the filament size
360
        for (uint8_t i = 0; i < COUNT(filament_size); i++)
361
          if (!filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
362
      }
363
 
364
    #endif
365
 
366
    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
367
 
368
      /**
369
       * Get the Z leveling fade factor based on the given Z height,
370
       * re-calculating only when needed.
371
       *
372
       *  Returns 1.0 if planner.z_fade_height is 0.0.
373
       *  Returns 0.0 if Z is past the specified 'Fade Height'.
374
       */
375
      inline static float fade_scaling_factor_for_z(const float &rz) {
376
        static float z_fade_factor = 1;
377
        if (z_fade_height) {
378
          if (rz >= z_fade_height) return 0;
379
          if (last_fade_z != rz) {
380
            last_fade_z = rz;
381
            z_fade_factor = 1 - rz * inverse_z_fade_height;
382
          }
383
          return z_fade_factor;
384
        }
385
        return 1;
386
      }
387
 
388
      FORCE_INLINE static void force_fade_recalc() { last_fade_z = -999.999f; }
389
 
390
      FORCE_INLINE static void set_z_fade_height(const float &zfh) {
391
        z_fade_height = zfh > 0 ? zfh : 0;
392
        inverse_z_fade_height = RECIPROCAL(z_fade_height);
393
        force_fade_recalc();
394
      }
395
 
396
      FORCE_INLINE static bool leveling_active_at_z(const float &rz) {
397
        return !z_fade_height || rz < z_fade_height;
398
      }
399
 
400
    #else
401
 
402
      FORCE_INLINE static float fade_scaling_factor_for_z(const float &rz) {
403
        UNUSED(rz);
404
        return 1;
405
      }
406
 
407
      FORCE_INLINE static bool leveling_active_at_z(const float &rz) { UNUSED(rz); return true; }
408
 
409
    #endif
410
 
411
    #if ENABLED(SKEW_CORRECTION)
412
 
413
      FORCE_INLINE static void skew(float &cx, float &cy, const float &cz) {
414
        if (WITHIN(cx, X_MIN_POS + 1, X_MAX_POS) && WITHIN(cy, Y_MIN_POS + 1, Y_MAX_POS)) {
415
          const float sx = cx - cy * xy_skew_factor - cz * (xz_skew_factor - (xy_skew_factor * yz_skew_factor)),
416
                      sy = cy - cz * yz_skew_factor;
417
          if (WITHIN(sx, X_MIN_POS, X_MAX_POS) && WITHIN(sy, Y_MIN_POS, Y_MAX_POS)) {
418
            cx = sx; cy = sy;
419
          }
420
        }
421
      }
422
 
423
      FORCE_INLINE static void unskew(float &cx, float &cy, const float &cz) {
424
        if (WITHIN(cx, X_MIN_POS, X_MAX_POS) && WITHIN(cy, Y_MIN_POS, Y_MAX_POS)) {
425
          const float sx = cx + cy * xy_skew_factor + cz * xz_skew_factor,
426
                      sy = cy + cz * yz_skew_factor;
427
          if (WITHIN(sx, X_MIN_POS, X_MAX_POS) && WITHIN(sy, Y_MIN_POS, Y_MAX_POS)) {
428
            cx = sx; cy = sy;
429
          }
430
        }
431
      }
432
 
433
    #endif // SKEW_CORRECTION
434
 
435
    #if PLANNER_LEVELING || HAS_UBL_AND_CURVES
436
      /**
437
       * Apply leveling to transform a cartesian position
438
       * as it will be given to the planner and steppers.
439
       */
440
      static void apply_leveling(float &rx, float &ry, float &rz);
441
      FORCE_INLINE static void apply_leveling(float (&raw)[XYZ]) { apply_leveling(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS]); }
442
    #endif
443
 
444
    #if PLANNER_LEVELING
445
      #define ARG_X float rx
446
      #define ARG_Y float ry
447
      #define ARG_Z float rz
448
      #if ENABLED(HANGPRINTER)
449
        #define ARG_E1 float re1
450
      #endif
451
      static void unapply_leveling(float raw[XYZ]);
452
    #else
453
      #define ARG_X const float &rx
454
      #define ARG_Y const float &ry
455
      #define ARG_Z const float &rz
456
      #if ENABLED(HANGPRINTER)
457
        #define ARG_E1 const float &re1
458
      #endif
459
    #endif
460
 
461
    // Number of moves currently in the planner including the busy block, if any
462
    FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail); }
463
 
464
    // Number of nonbusy moves currently in the planner
465
    FORCE_INLINE static uint8_t nonbusy_movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_nonbusy); }
466
 
467
    // Remove all blocks from the buffer
468
    FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail = 0; }
469
 
470
    // Check if movement queue is full
471
    FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
472
 
473
    // Get count of movement slots free
474
    FORCE_INLINE static uint8_t moves_free() { return BLOCK_BUFFER_SIZE - 1 - movesplanned(); }
475
 
476
    /**
477
     * Planner::get_next_free_block
478
     *
479
     * - Get the next head indices (passed by reference)
480
     * - Wait for the number of spaces to open up in the planner
481
     * - Return the first head block
482
     */
483
    FORCE_INLINE static block_t* get_next_free_block(uint8_t &next_buffer_head, const uint8_t count=1) {
484
 
485
      // Wait until there are enough slots free
486
      while (moves_free() < count) { idle(); }
487
 
488
      // Return the first available block
489
      next_buffer_head = next_block_index(block_buffer_head);
490
      return &block_buffer[block_buffer_head];
491
    }
492
 
493
    /**
494
     * Planner::_buffer_steps
495
     *
496
     * Add a new linear movement to the buffer (in terms of steps).
497
     *
498
     *  target      - target position in steps units
499
     *  fr_mm_s     - (target) speed of the move
500
     *  extruder    - target extruder
501
     *  millimeters - the length of the movement, if known
502
     *  count_it    - apply this move to the counters (UNREGISTERED_MOVE_SUPPORT)
503
     *
504
     * Returns true if movement was buffered, false otherwise
505
     */
506
    static bool _buffer_steps(const int32_t (&target)[NUM_AXIS]
507
      #if HAS_POSITION_FLOAT
508
        , const float (&target_float)[NUM_AXIS]
509
      #endif
510
      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
511
      #if ENABLED(UNREGISTERED_MOVE_SUPPORT)
512
        , const bool count_it=true
513
      #endif
514
    );
515
 
516
    /**
517
     * Planner::_populate_block
518
     *
519
     * Fills a new linear movement in the block (in terms of steps).
520
     *
521
     *  target      - target position in steps units
522
     *  fr_mm_s     - (target) speed of the move
523
     *  extruder    - target extruder
524
     *  millimeters - the length of the movement, if known
525
     *  count_it    - apply this move to the counters (UNREGISTERED_MOVE_SUPPORT)
526
     *
527
     * Returns true is movement is acceptable, false otherwise
528
     */
529
    static bool _populate_block(block_t * const block, bool split_move,
530
        const int32_t (&target)[NUM_AXIS]
531
      #if HAS_POSITION_FLOAT
532
        , const float (&target_float)[NUM_AXIS]
533
      #endif
534
      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
535
      #if ENABLED(UNREGISTERED_MOVE_SUPPORT)
536
        , const bool count_it=true
537
      #endif
538
    );
539
 
540
    /**
541
     * Planner::buffer_sync_block
542
     * Add a block to the buffer that just updates the position
543
     */
544
    static void buffer_sync_block();
545
 
546
    /**
547
     * Planner::buffer_segment
548
     *
549
     * Add a new linear movement to the buffer in axis units.
550
     *
551
     * Leveling and kinematics should be applied ahead of calling this.
552
     *
553
     *  a,b,c,e     - target positions in mm and/or degrees
554
     *                (a, b, c, d, e for Hangprinter)
555
     *  fr_mm_s     - (target) speed of the move
556
     *  extruder    - target extruder
557
     *  millimeters - the length of the movement, if known
558
     *  count_it    - remember this move in its counters (UNREGISTERED_MOVE_SUPPORT)
559
     */
560
    static bool buffer_segment(const float &a, const float &b, const float &c,
561
      #if ENABLED(HANGPRINTER)
562
        const float &d,
563
      #endif
564
      const float &e, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
565
      #if ENABLED(UNREGISTERED_MOVE_SUPPORT)
566
        , bool count_it=true
567
      #endif
568
    );
569
 
570
    static void _set_position_mm(const float &a, const float &b, const float &c,
571
      #if ENABLED(HANGPRINTER)
572
        const float &d,
573
      #endif
574
      const float &e
575
    );
576
 
577
    /**
578
     * Add a new linear movement to the buffer.
579
     * The target is NOT translated to delta/scara
580
     *
581
     * Leveling will be applied to input on cartesians.
582
     * Kinematic machines should call buffer_line_kinematic (for leveled moves).
583
     * (Cartesians may also call buffer_line_kinematic.)
584
     *
585
     *  rx,ry,rz,e   - target position in mm or degrees
586
     *                 (rx, ry, rz, re1 for Hangprinter)
587
     *  fr_mm_s      - (target) speed of the move (mm/s)
588
     *  extruder     - target extruder
589
     *  millimeters  - the length of the movement, if known
590
     */
591
    FORCE_INLINE static bool buffer_line(ARG_X, ARG_Y, ARG_Z,
592
      #if ENABLED(HANGPRINTER)
593
        ARG_E1,
594
      #endif
595
      const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0
596
    ) {
597
      #if PLANNER_LEVELING && IS_CARTESIAN
598
        apply_leveling(rx, ry, rz);
599
      #endif
600
      return buffer_segment(rx, ry, rz,
601
        #if ENABLED(HANGPRINTER)
602
          re1,
603
        #endif
604
        e, fr_mm_s, extruder, millimeters
605
      );
606
    }
607
 
608
    /**
609
     * Add a new linear movement to the buffer.
610
     * The target is cartesian, it's translated to delta/scara if
611
     * needed.
612
     *
613
     *  cart         - x,y,z,e CARTESIAN target in mm
614
     *  fr_mm_s      - (target) speed of the move (mm/s)
615
     *  extruder     - target extruder
616
     *  millimeters  - the length of the movement, if known
617
     */
618
    FORCE_INLINE static bool buffer_line_kinematic(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
619
      #if PLANNER_LEVELING
620
        float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
621
        apply_leveling(raw);
622
      #else
623
        const float (&raw)[XYZE] = cart;
624
      #endif
625
      #if IS_KINEMATIC
626
        inverse_kinematics(raw);
627
        return buffer_segment(
628
          #if ENABLED(HANGPRINTER)
629
            line_lengths[A_AXIS], line_lengths[B_AXIS], line_lengths[C_AXIS], line_lengths[D_AXIS]
630
          #else
631
            delta[A_AXIS], delta[B_AXIS], delta[C_AXIS]
632
          #endif
633
          , cart[E_CART], fr_mm_s, extruder, millimeters
634
        );
635
      #else
636
        return buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_CART], fr_mm_s, extruder, millimeters);
637
      #endif
638
    }
639
 
640
    /**
641
     * Set the planner.position and individual stepper positions.
642
     * Used by G92, G28, G29, and other procedures.
643
     *
644
     * Multiplies by axis_steps_per_mm[] and does necessary conversion
645
     * for COREXY / COREXZ / COREYZ to set the corresponding stepper positions.
646
     *
647
     * Clears previous speed values.
648
     */
649
    FORCE_INLINE static void set_position_mm(ARG_X, ARG_Y, ARG_Z,
650
      #if ENABLED(HANGPRINTER)
651
        ARG_E1,
652
      #endif
653
      const float &e
654
    ) {
655
      #if PLANNER_LEVELING && IS_CARTESIAN
656
        apply_leveling(rx, ry, rz);
657
      #endif
658
      _set_position_mm(rx, ry, rz,
659
        #if ENABLED(HANGPRINTER)
660
          re1,
661
        #endif
662
        e
663
      );
664
    }
665
    static void set_position_mm_kinematic(const float (&cart)[XYZE]);
666
    static void set_position_mm(const AxisEnum axis, const float &v);
667
    FORCE_INLINE static void set_z_position_mm(const float &z) { set_position_mm(Z_AXIS, z); }
668
    FORCE_INLINE static void set_e_position_mm(const float &e) { set_position_mm(E_AXIS, e); }
669
 
670
    /**
671
     * Get an axis position according to stepper position(s)
672
     * For CORE machines apply translation from ABC to XYZ.
673
     */
674
    static float get_axis_position_mm(const AxisEnum axis);
675
 
676
    // SCARA AB axes are in degrees, not mm
677
    #if IS_SCARA
678
      FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); }
679
    #endif
680
 
681
    // Called to force a quick stop of the machine (for example, when an emergency
682
    // stop is required, or when endstops are hit)
683
    static void quick_stop();
684
 
685
    // Called when an endstop is triggered. Causes the machine to stop inmediately
686
    static void endstop_triggered(const AxisEnum axis);
687
 
688
    // Triggered position of an axis in mm (not core-savvy)
689
    static float triggered_position_mm(const AxisEnum axis);
690
 
691
    // Block until all buffered steps are executed / cleaned
692
    static void synchronize();
693
 
694
    // Wait for moves to finish and disable all steppers
695
    static void finish_and_disable();
696
 
697
    // Periodic tick to handle cleaning timeouts
698
    // Called from the Temperature ISR at ~1kHz
699
    static void tick() {
700
      if (cleaning_buffer_counter) {
701
        --cleaning_buffer_counter;
702
        #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
703
          if (!cleaning_buffer_counter) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
704
        #endif
705
      }
706
    }
707
 
708
    /**
709
     * Does the buffer have any blocks queued?
710
     */
711
    FORCE_INLINE static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); }
712
 
713
    /**
714
     * The current block. NULL if the buffer is empty.
715
     * This also marks the block as busy.
716
     * WARNING: Called from Stepper ISR context!
717
     */
718
    static block_t* get_current_block() {
719
 
720
      // Get the number of moves in the planner queue so far
721
      const uint8_t nr_moves = movesplanned();
722
 
723
      // If there are any moves queued ...
724
      if (nr_moves) {
725
 
726
        // If there is still delay of delivery of blocks running, decrement it
727
        if (delay_before_delivering) {
728
          --delay_before_delivering;
729
          // If the number of movements queued is less than 3, and there is still time
730
          //  to wait, do not deliver anything
731
          if (nr_moves < 3 && delay_before_delivering) return NULL;
732
          delay_before_delivering = 0;
733
        }
734
 
735
        // If we are here, there is no excuse to deliver the block
736
        block_t * const block = &block_buffer[block_buffer_tail];
737
 
738
        // No trapezoid calculated? Don't execute yet.
739
        if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return NULL;
740
 
741
        #if ENABLED(ULTRA_LCD)
742
          block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it.
743
        #endif
744
 
745
        // As this block is busy, advance the nonbusy block pointer
746
        block_buffer_nonbusy = next_block_index(block_buffer_tail);
747
 
748
        // Push block_buffer_planned pointer, if encountered.
749
        if (block_buffer_tail == block_buffer_planned)
750
          block_buffer_planned = block_buffer_nonbusy;
751
 
752
        // Return the block
753
        return block;
754
      }
755
 
756
      // The queue became empty
757
      #if ENABLED(ULTRA_LCD)
758
        clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
759
      #endif
760
 
761
      return NULL;
762
    }
763
 
764
    /**
765
     * "Discard" the block and "release" the memory.
766
     * Called when the current block is no longer needed.
767
     * NB: There MUST be a current block to call this function!!
768
     */
769
    FORCE_INLINE static void discard_current_block() {
770
      if (has_blocks_queued())
771
        block_buffer_tail = next_block_index(block_buffer_tail);
772
    }
773
 
774
    #if ENABLED(ULTRA_LCD)
775
 
776
      static uint16_t block_buffer_runtime() {
777
        bool was_enabled = STEPPER_ISR_ENABLED();
778
        if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
779
 
780
        millis_t bbru = block_buffer_runtime_us;
781
 
782
        if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
783
 
784
        // To translate µs to ms a division by 1000 would be required.
785
        // We introduce 2.4% error here by dividing by 1024.
786
        // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
787
        bbru >>= 10;
788
        // limit to about a minute.
789
        NOMORE(bbru, 0xFFFFul);
790
        return bbru;
791
      }
792
 
793
      static void clear_block_buffer_runtime() {
794
        bool was_enabled = STEPPER_ISR_ENABLED();
795
        if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
796
 
797
        block_buffer_runtime_us = 0;
798
 
799
        if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
800
      }
801
 
802
    #endif
803
 
804
    #if ENABLED(AUTOTEMP)
805
      static float autotemp_min, autotemp_max, autotemp_factor;
806
      static bool autotemp_enabled;
807
      static void getHighESpeed();
808
      static void autotemp_M104_M109();
809
    #endif
810
 
811
    #if ENABLED(JUNCTION_DEVIATION)
812
      FORCE_INLINE static void recalculate_max_e_jerk() {
813
        #define GET_MAX_E_JERK(N) SQRT(SQRT(0.5) * junction_deviation_mm * (N) * RECIPROCAL(1.0 - SQRT(0.5)))
814
        #if ENABLED(LIN_ADVANCE)
815
          #if ENABLED(DISTINCT_E_FACTORS)
816
            for (uint8_t i = 0; i < EXTRUDERS; i++)
817
              max_e_jerk[i] = GET_MAX_E_JERK(max_acceleration_mm_per_s2[E_AXIS + i]);
818
          #else
819
            max_e_jerk = GET_MAX_E_JERK(max_acceleration_mm_per_s2[E_AXIS]);
820
          #endif
821
        #endif
822
      }
823
    #endif
824
 
825
  private:
826
 
827
    /**
828
     * Get the index of the next / previous block in the ring buffer
829
     */
830
    static constexpr uint8_t next_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index + 1); }
831
    static constexpr uint8_t prev_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index - 1); }
832
 
833
    /**
834
     * Calculate the distance (not time) it takes to accelerate
835
     * from initial_rate to target_rate using the given acceleration:
836
     */
837
    static float estimate_acceleration_distance(const float &initial_rate, const float &target_rate, const float &accel) {
838
      if (accel == 0) return 0; // accel was 0, set acceleration distance to 0
839
      return (sq(target_rate) - sq(initial_rate)) / (accel * 2);
840
    }
841
 
842
    /**
843
     * Return the point at which you must start braking (at the rate of -'accel') if
844
     * you start at 'initial_rate', accelerate (until reaching the point), and want to end at
845
     * 'final_rate' after traveling 'distance'.
846
     *
847
     * This is used to compute the intersection point between acceleration and deceleration
848
     * in cases where the "trapezoid" has no plateau (i.e., never reaches maximum speed)
849
     */
850
    static float intersection_distance(const float &initial_rate, const float &final_rate, const float &accel, const float &distance) {
851
      if (accel == 0) return 0; // accel was 0, set intersection distance to 0
852
      return (accel * 2 * distance - sq(initial_rate) + sq(final_rate)) / (accel * 4);
853
    }
854
 
855
    /**
856
     * Calculate the maximum allowable speed squared at this point, in order
857
     * to reach 'target_velocity_sqr' using 'acceleration' within a given
858
     * 'distance'.
859
     */
860
    static float max_allowable_speed_sqr(const float &accel, const float &target_velocity_sqr, const float &distance) {
861
      return target_velocity_sqr - 2 * accel * distance;
862
    }
863
 
864
    #if ENABLED(S_CURVE_ACCELERATION)
865
      /**
866
       * Calculate the speed reached given initial speed, acceleration and distance
867
       */
868
      static float final_speed(const float &initial_velocity, const float &accel, const float &distance) {
869
        return SQRT(sq(initial_velocity) + 2 * accel * distance);
870
      }
871
    #endif
872
 
873
    static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
874
 
875
    static void reverse_pass_kernel(block_t* const current, const block_t * const next);
876
    static void forward_pass_kernel(const block_t * const previous, block_t* const current, uint8_t block_index);
877
 
878
    static void reverse_pass();
879
    static void forward_pass();
880
 
881
    static void recalculate_trapezoids();
882
 
883
    static void recalculate();
884
 
885
    #if ENABLED(JUNCTION_DEVIATION)
886
 
887
      FORCE_INLINE static void normalize_junction_vector(float (&vector)[XYZE]) {
888
        float magnitude_sq = 0;
889
        LOOP_XYZE(idx) if (vector[idx]) magnitude_sq += sq(vector[idx]);
890
        const float inv_magnitude = RSQRT(magnitude_sq);
891
        LOOP_XYZE(idx) vector[idx] *= inv_magnitude;
892
      }
893
 
894
      FORCE_INLINE static float limit_value_by_axis_maximum(const float &max_value, float (&unit_vec)[XYZE]) {
895
        float limit_value = max_value;
896
        LOOP_XYZE(idx) if (unit_vec[idx]) // Avoid divide by zero
897
          NOMORE(limit_value, ABS(max_acceleration_mm_per_s2[idx] / unit_vec[idx]));
898
        return limit_value;
899
      }
900
 
901
    #endif // JUNCTION_DEVIATION
902
};
903
 
904
#define PLANNER_XY_FEEDRATE() (MIN(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]))
905
 
906
extern Planner planner;
907
 
908
#endif // PLANNER_H