Add a feedRate_t data type (#15349)
This commit is contained in:
		@@ -244,8 +244,11 @@
 | 
				
			|||||||
#define DECREMENT_(n) DEC_##n
 | 
					#define DECREMENT_(n) DEC_##n
 | 
				
			||||||
#define DECREMENT(n) DECREMENT_(n)
 | 
					#define DECREMENT(n) DECREMENT_(n)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Feedrate
 | 
				
			||||||
 | 
					typedef float feedRate_t;
 | 
				
			||||||
#define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
 | 
					#define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
 | 
				
			||||||
#define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
 | 
					#define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
 | 
				
			||||||
 | 
					#define MMS_SCALED(V)    ((V) * 0.01f * feedrate_percentage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NOOP (void(0))
 | 
					#define NOOP (void(0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -329,8 +329,8 @@ bool I2CPositionEncoder::test_axis() {
 | 
				
			|||||||
  float startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
 | 
					  float startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const float startPosition = soft_endstop[encoderAxis].min + 10,
 | 
					  const float startPosition = soft_endstop[encoderAxis].min + 10,
 | 
				
			||||||
              endPosition = soft_endstop[encoderAxis].max - 10,
 | 
					              endPosition = soft_endstop[encoderAxis].max - 10;
 | 
				
			||||||
              feedrate = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
 | 
					  const feedRate_t fr_mm_s = FLOOR(MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ec = false;
 | 
					  ec = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -344,7 +344,7 @@ bool I2CPositionEncoder::test_axis() {
 | 
				
			|||||||
  planner.synchronize();
 | 
					  planner.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
 | 
					  planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
 | 
				
			||||||
                      planner.get_axis_position_mm(E_AXIS), feedrate, 0);
 | 
					                      planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
 | 
				
			||||||
  planner.synchronize();
 | 
					  planner.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
 | 
					  // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
 | 
				
			||||||
@@ -356,7 +356,7 @@ bool I2CPositionEncoder::test_axis() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (trusted) { // if trusted, commence test
 | 
					  if (trusted) { // if trusted, commence test
 | 
				
			||||||
    planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
 | 
					    planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
 | 
				
			||||||
                        planner.get_axis_position_mm(E_AXIS), feedrate, 0);
 | 
					                        planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
 | 
				
			||||||
    planner.synchronize();
 | 
					    planner.synchronize();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -379,11 +379,9 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
 | 
				
			|||||||
        travelDistance, travelledDistance, total = 0,
 | 
					        travelDistance, travelledDistance, total = 0,
 | 
				
			||||||
        startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
 | 
					        startCoord[NUM_AXIS] = { 0 }, endCoord[NUM_AXIS] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float feedrate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int32_t startCount, stopCount;
 | 
					  int32_t startCount, stopCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  feedrate = MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY);
 | 
					  const feedRate_t fr_mm_s = MMM_TO_MMS((encoderAxis == Z_AXIS) ? HOMING_FEEDRATE_Z : HOMING_FEEDRATE_XY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool oldec = ec;
 | 
					  bool oldec = ec;
 | 
				
			||||||
  ec = false;
 | 
					  ec = false;
 | 
				
			||||||
@@ -404,7 +402,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  LOOP_L_N(i, iter) {
 | 
					  LOOP_L_N(i, iter) {
 | 
				
			||||||
    planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
 | 
					    planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
 | 
				
			||||||
                        planner.get_axis_position_mm(E_AXIS), feedrate, 0);
 | 
					                        planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
 | 
				
			||||||
    planner.synchronize();
 | 
					    planner.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delay(250);
 | 
					    delay(250);
 | 
				
			||||||
@@ -413,7 +411,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
 | 
				
			|||||||
    //do_blocking_move_to(endCoord[X_AXIS],endCoord[Y_AXIS],endCoord[Z_AXIS]);
 | 
					    //do_blocking_move_to(endCoord[X_AXIS],endCoord[Y_AXIS],endCoord[Z_AXIS]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
 | 
					    planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
 | 
				
			||||||
                        planner.get_axis_position_mm(E_AXIS), feedrate, 0);
 | 
					                        planner.get_axis_position_mm(E_AXIS), fr_mm_s, 0);
 | 
				
			||||||
    planner.synchronize();
 | 
					    planner.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Read encoder distance
 | 
					    //Read encoder distance
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -360,7 +360,7 @@ float bilinear_z_offset(const float raw[XYZ]) {
 | 
				
			|||||||
   * Prepare a bilinear-leveled linear move on Cartesian,
 | 
					   * Prepare a bilinear-leveled linear move on Cartesian,
 | 
				
			||||||
   * splitting the move where it crosses grid borders.
 | 
					   * splitting the move where it crosses grid borders.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  void bilinear_line_to_destination(const float fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
 | 
					  void bilinear_line_to_destination(const feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
 | 
				
			||||||
    // Get current and destination cells for this line
 | 
					    // Get current and destination cells for this line
 | 
				
			||||||
    int cx1 = CELL_INDEX(X, current_position[X_AXIS]),
 | 
					    int cx1 = CELL_INDEX(X, current_position[X_AXIS]),
 | 
				
			||||||
        cy1 = CELL_INDEX(Y, current_position[Y_AXIS]),
 | 
					        cy1 = CELL_INDEX(Y, current_position[Y_AXIS]),
 | 
				
			||||||
@@ -373,8 +373,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Start and end in the same cell? No split needed.
 | 
					    // Start and end in the same cell? No split needed.
 | 
				
			||||||
    if (cx1 == cx2 && cy1 == cy2) {
 | 
					    if (cx1 == cx2 && cy1 == cy2) {
 | 
				
			||||||
      buffer_line_to_destination(fr_mm_s);
 | 
					 | 
				
			||||||
      set_current_from_destination();
 | 
					      set_current_from_destination();
 | 
				
			||||||
 | 
					      line_to_current_position(scaled_fr_mm_s);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -405,8 +405,8 @@ float bilinear_z_offset(const float raw[XYZ]) {
 | 
				
			|||||||
    else {
 | 
					    else {
 | 
				
			||||||
      // Must already have been split on these border(s)
 | 
					      // Must already have been split on these border(s)
 | 
				
			||||||
      // This should be a rare case.
 | 
					      // This should be a rare case.
 | 
				
			||||||
      buffer_line_to_destination(fr_mm_s);
 | 
					 | 
				
			||||||
      set_current_from_destination();
 | 
					      set_current_from_destination();
 | 
				
			||||||
 | 
					      line_to_current_position(scaled_fr_mm_s);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -414,11 +414,11 @@ float bilinear_z_offset(const float raw[XYZ]) {
 | 
				
			|||||||
    destination[E_AXIS] = LINE_SEGMENT_END(E);
 | 
					    destination[E_AXIS] = LINE_SEGMENT_END(E);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Do the split and look for more borders
 | 
					    // Do the split and look for more borders
 | 
				
			||||||
    bilinear_line_to_destination(fr_mm_s, x_splits, y_splits);
 | 
					    bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Restore destination from stack
 | 
					    // Restore destination from stack
 | 
				
			||||||
    COPY(destination, end);
 | 
					    COPY(destination, end);
 | 
				
			||||||
    bilinear_line_to_destination(fr_mm_s, x_splits, y_splits);
 | 
					    bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
 | 
					#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ void refresh_bed_level();
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
 | 
					#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
 | 
				
			||||||
  void bilinear_line_to_destination(const float fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
 | 
					  void bilinear_line_to_destination(const feedRate_t &scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])
 | 
					#define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,7 @@
 | 
				
			|||||||
     * Prepare a mesh-leveled linear move in a Cartesian setup,
 | 
					     * Prepare a mesh-leveled linear move in a Cartesian setup,
 | 
				
			||||||
     * splitting the move where it crosses mesh borders.
 | 
					     * splitting the move where it crosses mesh borders.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void mesh_bed_leveling::line_to_destination(const float fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
 | 
					    void mesh_bed_leveling::line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
 | 
				
			||||||
      // Get current and destination cells for this line
 | 
					      // Get current and destination cells for this line
 | 
				
			||||||
      int cx1 = cell_index_x(current_position[X_AXIS]),
 | 
					      int cx1 = cell_index_x(current_position[X_AXIS]),
 | 
				
			||||||
          cy1 = cell_index_y(current_position[Y_AXIS]),
 | 
					          cy1 = cell_index_y(current_position[Y_AXIS]),
 | 
				
			||||||
@@ -77,7 +77,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      // Start and end in the same cell? No split needed.
 | 
					      // Start and end in the same cell? No split needed.
 | 
				
			||||||
      if (cx1 == cx2 && cy1 == cy2) {
 | 
					      if (cx1 == cx2 && cy1 == cy2) {
 | 
				
			||||||
        line_to_destination(fr_mm_s);
 | 
					        line_to_destination(scaled_fr_mm_s);
 | 
				
			||||||
        set_current_from_destination();
 | 
					        set_current_from_destination();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -109,7 +109,7 @@
 | 
				
			|||||||
      else {
 | 
					      else {
 | 
				
			||||||
        // Must already have been split on these border(s)
 | 
					        // Must already have been split on these border(s)
 | 
				
			||||||
        // This should be a rare case.
 | 
					        // This should be a rare case.
 | 
				
			||||||
        line_to_destination(fr_mm_s);
 | 
					        line_to_destination(scaled_fr_mm_s);
 | 
				
			||||||
        set_current_from_destination();
 | 
					        set_current_from_destination();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -118,11 +118,11 @@
 | 
				
			|||||||
      destination[E_AXIS] = MBL_SEGMENT_END(E);
 | 
					      destination[E_AXIS] = MBL_SEGMENT_END(E);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Do the split and look for more borders
 | 
					      // Do the split and look for more borders
 | 
				
			||||||
      line_to_destination(fr_mm_s, x_splits, y_splits);
 | 
					      line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Restore destination from stack
 | 
					      // Restore destination from stack
 | 
				
			||||||
      COPY(destination, end);
 | 
					      COPY(destination, end);
 | 
				
			||||||
      line_to_destination(fr_mm_s, x_splits, y_splits);
 | 
					      line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
 | 
					  #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,7 @@ public:
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
 | 
					  #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
 | 
				
			||||||
    static void line_to_destination(const float fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
 | 
					    static void line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -285,9 +285,9 @@ class unified_bed_leveling {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if UBL_SEGMENTED
 | 
					    #if UBL_SEGMENTED
 | 
				
			||||||
      static bool prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate);
 | 
					      static bool line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s);
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      static void line_to_destination_cartesian(const float &fr, const uint8_t e);
 | 
					      static void line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t e);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static inline bool mesh_is_valid() {
 | 
					    static inline bool mesh_is_valid() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if !UBL_SEGMENTED
 | 
					#if !UBL_SEGMENTED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void unified_bed_leveling::line_to_destination_cartesian(const float &feed_rate, const uint8_t extruder) {
 | 
					  void unified_bed_leveling::line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t extruder) {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Much of the nozzle movement will be within the same cell. So we will do as little computation
 | 
					     * Much of the nozzle movement will be within the same cell. So we will do as little computation
 | 
				
			||||||
     * as possible to determine if this is the case. If this move is within the same cell, we will
 | 
					     * as possible to determine if this is the case. If this move is within the same cell, we will
 | 
				
			||||||
@@ -79,9 +79,8 @@
 | 
				
			|||||||
            + UBL_Z_RAISE_WHEN_OFF_MESH
 | 
					            + UBL_Z_RAISE_WHEN_OFF_MESH
 | 
				
			||||||
          #endif
 | 
					          #endif
 | 
				
			||||||
        ;
 | 
					        ;
 | 
				
			||||||
        planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z_raise, end[E_AXIS], feed_rate, extruder);
 | 
					        planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + z_raise, end[E_AXIS], scaled_fr_mm_s, extruder);
 | 
				
			||||||
        set_current_from_destination();
 | 
					        set_current_from_destination();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -103,8 +102,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      // Undefined parts of the Mesh in z_values[][] are NAN.
 | 
					      // Undefined parts of the Mesh in z_values[][] are NAN.
 | 
				
			||||||
      // Replace NAN corrections with 0.0 to prevent NAN propagation.
 | 
					      // Replace NAN corrections with 0.0 to prevent NAN propagation.
 | 
				
			||||||
      planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + (isnan(z0) ? 0.0 : z0), end[E_AXIS], feed_rate, extruder);
 | 
					      planner.buffer_segment(end[X_AXIS], end[Y_AXIS], end[Z_AXIS] + (isnan(z0) ? 0.0 : z0), end[E_AXIS], scaled_fr_mm_s, extruder);
 | 
				
			||||||
 | 
					 | 
				
			||||||
      set_current_from_destination();
 | 
					      set_current_from_destination();
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -194,7 +192,7 @@
 | 
				
			|||||||
            z_position = end[Z_AXIS];
 | 
					            z_position = end[Z_AXIS];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder);
 | 
					          planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder);
 | 
				
			||||||
        } //else printf("FIRST MOVE PRUNED  ");
 | 
					        } //else printf("FIRST MOVE PRUNED  ");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -242,7 +240,7 @@
 | 
				
			|||||||
            z_position = end[Z_AXIS];
 | 
					            z_position = end[Z_AXIS];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder))
 | 
					          if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder))
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        } //else printf("FIRST MOVE PRUNED  ");
 | 
					        } //else printf("FIRST MOVE PRUNED  ");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -297,7 +295,7 @@
 | 
				
			|||||||
          e_position = end[E_AXIS];
 | 
					          e_position = end[E_AXIS];
 | 
				
			||||||
          z_position = end[Z_AXIS];
 | 
					          z_position = end[Z_AXIS];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder))
 | 
					        if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, scaled_fr_mm_s, extruder))
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        current_yi += dyi;
 | 
					        current_yi += dyi;
 | 
				
			||||||
        yi_cnt--;
 | 
					        yi_cnt--;
 | 
				
			||||||
@@ -321,7 +319,7 @@
 | 
				
			|||||||
          z_position = end[Z_AXIS];
 | 
					          z_position = end[Z_AXIS];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder))
 | 
					        if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder))
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        current_xi += dxi;
 | 
					        current_xi += dxi;
 | 
				
			||||||
        xi_cnt--;
 | 
					        xi_cnt--;
 | 
				
			||||||
@@ -356,25 +354,25 @@
 | 
				
			|||||||
   * Returns true if did NOT move, false if moved (requires current_position update).
 | 
					   * Returns true if did NOT move, false if moved (requires current_position update).
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool _O2 unified_bed_leveling::prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate) {
 | 
					  bool _O2 unified_bed_leveling::line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS]))  // fail if moving outside reachable boundary
 | 
					    if (!position_is_reachable(destination[X_AXIS], destination[Y_AXIS]))  // fail if moving outside reachable boundary
 | 
				
			||||||
      return true; // did not move, so current_position still accurate
 | 
					      return true; // did not move, so current_position still accurate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const float total[XYZE] = {
 | 
					    const float total[XYZE] = {
 | 
				
			||||||
      rtarget[X_AXIS] - current_position[X_AXIS],
 | 
					      destination[X_AXIS] - current_position[X_AXIS],
 | 
				
			||||||
      rtarget[Y_AXIS] - current_position[Y_AXIS],
 | 
					      destination[Y_AXIS] - current_position[Y_AXIS],
 | 
				
			||||||
      rtarget[Z_AXIS] - current_position[Z_AXIS],
 | 
					      destination[Z_AXIS] - current_position[Z_AXIS],
 | 
				
			||||||
      rtarget[E_AXIS] - current_position[E_AXIS]
 | 
					      destination[E_AXIS] - current_position[E_AXIS]
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]);  // total horizontal xy distance
 | 
					    const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]);  // total horizontal xy distance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if IS_KINEMATIC
 | 
					    #if IS_KINEMATIC
 | 
				
			||||||
      const float seconds = cartesian_xy_mm / feedrate;                                  // seconds to move xy distance at requested rate
 | 
					      const float seconds = cartesian_xy_mm / scaled_fr_mm_s;                             // Duration of XY move at requested rate
 | 
				
			||||||
      uint16_t segments = LROUND(delta_segments_per_second * seconds),                  // preferred number of segments for distance @ feedrate
 | 
					      uint16_t segments = LROUND(delta_segments_per_second * seconds),                    // Preferred number of segments for distance @ feedrate
 | 
				
			||||||
               seglimit = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // number of segments at minimum segment length
 | 
					               seglimit = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length
 | 
				
			||||||
      NOMORE(segments, seglimit);                                                        // limit to minimum segment length (fewer segments)
 | 
					      NOMORE(segments, seglimit);                                                         // Limit to minimum segment length (fewer segments)
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      uint16_t segments = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // cartesian fixed segment length
 | 
					      uint16_t segments = LROUND(cartesian_xy_mm * RECIPROCAL(DELTA_SEGMENT_MIN_LENGTH)); // cartesian fixed segment length
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
@@ -384,7 +382,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const float segment_xyz_mm = HYPOT(cartesian_xy_mm, total[Z_AXIS]) * inv_segments;   // length of each segment
 | 
					    const float segment_xyz_mm = HYPOT(cartesian_xy_mm, total[Z_AXIS]) * inv_segments;   // length of each segment
 | 
				
			||||||
    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
      const float inv_duration = feedrate / segment_xyz_mm;
 | 
					      const float inv_duration = scaled_fr_mm_s / segment_xyz_mm;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const float diff[XYZE] = {
 | 
					    const float diff[XYZE] = {
 | 
				
			||||||
@@ -404,17 +402,17 @@
 | 
				
			|||||||
      current_position[E_AXIS]
 | 
					      current_position[E_AXIS]
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Only compute leveling per segment if ubl active and target below z_fade_height.
 | 
					    // Just do plain segmentation if UBL is inactive or the target is above the fade height
 | 
				
			||||||
    if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) {   // no mesh leveling
 | 
					    if (!planner.leveling_active || !planner.leveling_active_at_z(destination[Z_AXIS])) {
 | 
				
			||||||
      while (--segments) {
 | 
					      while (--segments) {
 | 
				
			||||||
        LOOP_XYZE(i) raw[i] += diff[i];
 | 
					        LOOP_XYZE(i) raw[i] += diff[i];
 | 
				
			||||||
        planner.buffer_line(raw, feedrate, active_extruder, segment_xyz_mm
 | 
					        planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
 | 
				
			||||||
          #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					          #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
            , inv_duration
 | 
					            , inv_duration
 | 
				
			||||||
          #endif
 | 
					          #endif
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      planner.buffer_line(rtarget, feedrate, active_extruder, segment_xyz_mm
 | 
					      planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
 | 
				
			||||||
        #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					        #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
          , inv_duration
 | 
					          , inv_duration
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
@@ -425,7 +423,7 @@
 | 
				
			|||||||
    // Otherwise perform per-segment leveling
 | 
					    // Otherwise perform per-segment leveling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 | 
					    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 | 
				
			||||||
      const float fade_scaling_factor = planner.fade_scaling_factor_for_z(rtarget[Z_AXIS]);
 | 
					      const float fade_scaling_factor = planner.fade_scaling_factor_for_z(destination[Z_AXIS]);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // increment to first segment destination
 | 
					    // increment to first segment destination
 | 
				
			||||||
@@ -483,8 +481,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      for (;;) {  // for all segments within this mesh cell
 | 
					      for (;;) {  // for all segments within this mesh cell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (--segments == 0)                      // if this is last segment, use rtarget for exact
 | 
					        if (--segments == 0) COPY(raw, destination); // if this is last segment, use destination for exact
 | 
				
			||||||
          COPY(raw, rtarget);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
 | 
					        const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
 | 
				
			||||||
          #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 | 
					          #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 | 
				
			||||||
@@ -494,7 +491,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const float z = raw[Z_AXIS];
 | 
					        const float z = raw[Z_AXIS];
 | 
				
			||||||
        raw[Z_AXIS] += z_cxcy;
 | 
					        raw[Z_AXIS] += z_cxcy;
 | 
				
			||||||
        planner.buffer_line(raw, feedrate, active_extruder, segment_xyz_mm
 | 
					        planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
 | 
				
			||||||
          #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					          #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
            , inv_duration
 | 
					            , inv_duration
 | 
				
			||||||
          #endif
 | 
					          #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,10 +128,7 @@ void FWRetract::retract(const bool retracting
 | 
				
			|||||||
    SERIAL_ECHOLNPAIR("current_hop ", current_hop);
 | 
					    SERIAL_ECHOLNPAIR("current_hop ", current_hop);
 | 
				
			||||||
  //*/
 | 
					  //*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const float old_feedrate_mm_s = feedrate_mm_s,
 | 
					  const float base_retract = (
 | 
				
			||||||
              unscale_e = RECIPROCAL(planner.e_factor[active_extruder]),
 | 
					 | 
				
			||||||
              unscale_fr = 100.0 / feedrate_percentage, // Disable feedrate scaling for retract moves
 | 
					 | 
				
			||||||
              base_retract = (
 | 
					 | 
				
			||||||
                (swapping ? settings.swap_retract_length : settings.retract_length)
 | 
					                (swapping ? settings.swap_retract_length : settings.retract_length)
 | 
				
			||||||
                #if ENABLED(RETRACT_SYNC_MIXING)
 | 
					                #if ENABLED(RETRACT_SYNC_MIXING)
 | 
				
			||||||
                  * (MIXING_STEPPERS)
 | 
					                  * (MIXING_STEPPERS)
 | 
				
			||||||
@@ -146,53 +143,53 @@ void FWRetract::retract(const bool retracting
 | 
				
			|||||||
    mixer.T(MIXER_AUTORETRACT_TOOL);
 | 
					    mixer.T(MIXER_AUTORETRACT_TOOL);
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const feedRate_t fr_max_z = planner.settings.max_feedrate_mm_s[Z_AXIS];
 | 
				
			||||||
  if (retracting) {
 | 
					  if (retracting) {
 | 
				
			||||||
    // Retract by moving from a faux E position back to the current E position
 | 
					    // Retract by moving from a faux E position back to the current E position
 | 
				
			||||||
    feedrate_mm_s = (
 | 
					    current_retract[active_extruder] = base_retract;
 | 
				
			||||||
      settings.retract_feedrate_mm_s * unscale_fr
 | 
					    prepare_internal_move_to_destination(  // set_current_to_destination
 | 
				
			||||||
 | 
					      settings.retract_feedrate_mm_s
 | 
				
			||||||
      #if ENABLED(RETRACT_SYNC_MIXING)
 | 
					      #if ENABLED(RETRACT_SYNC_MIXING)
 | 
				
			||||||
        * (MIXING_STEPPERS)
 | 
					        * (MIXING_STEPPERS)
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    current_retract[active_extruder] = base_retract * unscale_e;
 | 
					 | 
				
			||||||
    prepare_move_to_destination();                        // set_current_to_destination
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Is a Z hop set, and has the hop not yet been done?
 | 
					    // Is a Z hop set, and has the hop not yet been done?
 | 
				
			||||||
    if (settings.retract_zraise > 0.01 && !current_hop) {           // Apply hop only once
 | 
					    if (!current_hop && settings.retract_zraise > 0.01f) {  // Apply hop only once
 | 
				
			||||||
      current_hop += settings.retract_zraise;               // Add to the hop total (again, only once)
 | 
					      current_hop += settings.retract_zraise;               // Add to the hop total (again, only once)
 | 
				
			||||||
      feedrate_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * unscale_fr;  // Maximum Z feedrate
 | 
					      // Raise up, set_current_to_destination. Maximum Z feedrate
 | 
				
			||||||
      prepare_move_to_destination();                      // Raise up, set_current_to_destination
 | 
					      prepare_internal_move_to_destination(fr_max_z);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    // If a hop was done and Z hasn't changed, undo the Z hop
 | 
					    // If a hop was done and Z hasn't changed, undo the Z hop
 | 
				
			||||||
    if (current_hop) {
 | 
					    if (current_hop) {
 | 
				
			||||||
      current_hop = 0.0;
 | 
					      current_hop = 0;
 | 
				
			||||||
      feedrate_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * unscale_fr;  // Z feedrate to max
 | 
					      // Lower Z, set_current_to_destination. Maximum Z feedrate
 | 
				
			||||||
      prepare_move_to_destination();                      // Lower Z, set_current_to_destination
 | 
					      prepare_internal_move_to_destination(fr_max_z);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra;
 | 
					    const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra;
 | 
				
			||||||
    if (extra_recover != 0.0) {
 | 
					    if (extra_recover) {
 | 
				
			||||||
      current_position[E_AXIS] -= extra_recover;          // Adjust the current E position by the extra amount to recover
 | 
					      current_position[E_AXIS] -= extra_recover;          // Adjust the current E position by the extra amount to recover
 | 
				
			||||||
      sync_plan_position_e();                             // Sync the planner position so the extra amount is recovered
 | 
					      sync_plan_position_e();                             // Sync the planner position so the extra amount is recovered
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    current_retract[active_extruder] = 0.0;
 | 
					    current_retract[active_extruder] = 0;
 | 
				
			||||||
    feedrate_mm_s = (
 | 
					
 | 
				
			||||||
      (swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s) * unscale_fr
 | 
					    const feedRate_t fr_mm_s = (
 | 
				
			||||||
 | 
					      (swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s)
 | 
				
			||||||
      #if ENABLED(RETRACT_SYNC_MIXING)
 | 
					      #if ENABLED(RETRACT_SYNC_MIXING)
 | 
				
			||||||
        * (MIXING_STEPPERS)
 | 
					        * (MIXING_STEPPERS)
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    prepare_move_to_destination();                        // Recover E, set_current_to_destination
 | 
					    prepare_internal_move_to_destination(fr_mm_s);        // Recover E, set_current_to_destination
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ENABLED(RETRACT_SYNC_MIXING)
 | 
					  #if ENABLED(RETRACT_SYNC_MIXING)
 | 
				
			||||||
    mixer.T(old_mixing_tool);                             // Restore original mixing tool
 | 
					    mixer.T(old_mixing_tool);                             // Restore original mixing tool
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  feedrate_mm_s = old_feedrate_mm_s;                      // Restore original feedrate
 | 
					 | 
				
			||||||
  retracted[active_extruder] = retracting;                // Active extruder now retracted / recovered
 | 
					  retracted[active_extruder] = retracting;                // Active extruder now retracted / recovered
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If swap retract/recover update the retracted_swap flag too
 | 
					  // If swap retract/recover update the retracted_swap flag too
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,14 +28,14 @@
 | 
				
			|||||||
#include "../inc/MarlinConfigPre.h"
 | 
					#include "../inc/MarlinConfigPre.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
  float retract_length,                     // M207 S - G10 Retract length
 | 
					       float retract_length;                      // M207 S - G10 Retract length
 | 
				
			||||||
        retract_feedrate_mm_s,              // M207 F - G10 Retract feedrate
 | 
					  feedRate_t retract_feedrate_mm_s;               // M207 F - G10 Retract feedrate
 | 
				
			||||||
        retract_zraise,                     // M207 Z - G10 Retract hop size
 | 
					       float retract_zraise,                      // M207 Z - G10 Retract hop size
 | 
				
			||||||
        retract_recover_extra,              // M208 S - G11 Recover length
 | 
					             retract_recover_extra;               // M208 S - G11 Recover length
 | 
				
			||||||
        retract_recover_feedrate_mm_s,      // M208 F - G11 Recover feedrate
 | 
					  feedRate_t retract_recover_feedrate_mm_s;       // M208 F - G11 Recover feedrate
 | 
				
			||||||
        swap_retract_length,                // M207 W - G10 Swap Retract length
 | 
					       float swap_retract_length,                 // M207 W - G10 Swap Retract length
 | 
				
			||||||
        swap_retract_recover_extra,         // M208 W - G11 Swap Recover length
 | 
					             swap_retract_recover_extra;          // M208 W - G11 Swap Recover length
 | 
				
			||||||
        swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
 | 
					  feedRate_t swap_retract_recover_feedrate_mm_s;  // M208 R - G11 Swap Recover feedrate
 | 
				
			||||||
} fwretract_settings_t;
 | 
					} fwretract_settings_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if ENABLED(FWRETRACT)
 | 
					#if ENABLED(FWRETRACT)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,7 +122,7 @@ static bool ensure_safe_temperature(const PauseMode mode=PAUSE_MODE_SAME) {
 | 
				
			|||||||
  return thermalManager.wait_for_hotend(active_extruder);
 | 
					  return thermalManager.wait_for_hotend(active_extruder);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_pause_e_move(const float &length, const float &fr_mm_s) {
 | 
					void do_pause_e_move(const float &length, const feedRate_t &fr_mm_s) {
 | 
				
			||||||
  #if HAS_FILAMENT_SENSOR
 | 
					  #if HAS_FILAMENT_SENSOR
 | 
				
			||||||
    runout.reset();
 | 
					    runout.reset();
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
@@ -648,16 +648,16 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
 | 
				
			|||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If resume_position is negative
 | 
					  // If resume_position is negative
 | 
				
			||||||
  if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], PAUSE_PARK_RETRACT_FEEDRATE);
 | 
					  if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Move XY to starting position, then Z
 | 
					  // Move XY to starting position, then Z
 | 
				
			||||||
  do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE);
 | 
					  do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Move Z_AXIS to saved position
 | 
					  // Move Z_AXIS to saved position
 | 
				
			||||||
  do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE);
 | 
					  do_blocking_move_to_z(resume_position[Z_AXIS], feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ADVANCED_PAUSE_RESUME_PRIME != 0
 | 
					  #if ADVANCED_PAUSE_RESUME_PRIME != 0
 | 
				
			||||||
    do_pause_e_move(ADVANCED_PAUSE_RESUME_PRIME, ADVANCED_PAUSE_PURGE_FEEDRATE);
 | 
					    do_pause_e_move(ADVANCED_PAUSE_RESUME_PRIME, feedRate_t(ADVANCED_PAUSE_PURGE_FEEDRATE));
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Now all extrusion positions are resumed and ready to be confirmed
 | 
					  // Now all extrusion positions are resumed and ready to be confirmed
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,7 @@ extern uint8_t did_pause_print;
 | 
				
			|||||||
  #define DXC_PASS
 | 
					  #define DXC_PASS
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_pause_e_move(const float &length, const float &fr_mm_s);
 | 
					void do_pause_e_move(const float &length, const feedRate_t &fr_mm_s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool pause_print(const float &retract, const point_t &park_point, const float &unload_length=0, const bool show_lcd=false DXC_PARAMS);
 | 
					bool pause_print(const float &retract, const point_t &park_point, const float &unload_length=0, const bool show_lcd=false DXC_PARAMS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,7 @@ char MMU2::rx_buffer[16], MMU2::tx_buffer[16];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  struct E_Step {
 | 
					  struct E_Step {
 | 
				
			||||||
    float extrude;        //!< extrude distance in mm
 | 
					    float extrude;        //!< extrude distance in mm
 | 
				
			||||||
    float feedRate;   //!< feed rate in mm/s
 | 
					    feedRate_t feedRate;  //!< feed rate in mm/s
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE };
 | 
					  static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE };
 | 
				
			||||||
@@ -606,10 +606,10 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
 | 
				
			|||||||
        BUZZ(200, 404);
 | 
					        BUZZ(200, 404);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Move XY to starting position, then Z
 | 
					        // Move XY to starting position, then Z
 | 
				
			||||||
        do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], NOZZLE_PARK_XY_FEEDRATE);
 | 
					        do_blocking_move_to_xy(resume_position[X_AXIS], resume_position[Y_AXIS], feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Move Z_AXIS to saved position
 | 
					        // Move Z_AXIS to saved position
 | 
				
			||||||
        do_blocking_move_to_z(resume_position[Z_AXIS], NOZZLE_PARK_Z_FEEDRATE);
 | 
					        do_blocking_move_to_z(resume_position[Z_AXIS], feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
        BUZZ(200, 404);
 | 
					        BUZZ(200, 404);
 | 
				
			||||||
@@ -783,15 +783,14 @@ void MMU2::filament_runout() {
 | 
				
			|||||||
    const E_Step* step = sequence;
 | 
					    const E_Step* step = sequence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint8_t i = 0; i < steps; i++) {
 | 
					    for (uint8_t i = 0; i < steps; i++) {
 | 
				
			||||||
      const float es = pgm_read_float(&(step->extrude)),
 | 
					      const float es = pgm_read_float(&(step->extrude));
 | 
				
			||||||
                  fr = pgm_read_float(&(step->feedRate));
 | 
					      const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      DEBUG_ECHO_START();
 | 
					      DEBUG_ECHO_START();
 | 
				
			||||||
      DEBUG_ECHOLNPAIR("E step ", es, "/", fr);
 | 
					      DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      current_position[E_AXIS] += es;
 | 
					      current_position[E_AXIS] += es;
 | 
				
			||||||
      planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
 | 
					      line_to_current_position(MMM_TO_MMS(fr_mm_m));
 | 
				
			||||||
                          current_position[E_AXIS], MMM_TO_MMS(fr), active_extruder);
 | 
					 | 
				
			||||||
      planner.synchronize();
 | 
					      planner.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      step++;
 | 
					      step++;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -216,41 +216,32 @@ mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
 | 
				
			|||||||
  return return_val;
 | 
					  return return_val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void G26_line_to_destination(const float &feed_rate) {
 | 
					 | 
				
			||||||
  const float save_feedrate = feedrate_mm_s;
 | 
					 | 
				
			||||||
  feedrate_mm_s = feed_rate;
 | 
					 | 
				
			||||||
  prepare_move_to_destination();  // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
 | 
					 | 
				
			||||||
  feedrate_mm_s = save_feedrate;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
 | 
					void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
 | 
				
			||||||
  float feed_value;
 | 
					 | 
				
			||||||
  static float last_z = -999.99;
 | 
					  static float last_z = -999.99;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
 | 
					  bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (z != last_z) {
 | 
					  if (z != last_z) {
 | 
				
			||||||
    last_z = z;
 | 
					    last_z = z;
 | 
				
			||||||
    feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS]/(2.0);  // Base the feed rate off of the configured Z_AXIS feed rate
 | 
					    const feedRate_t feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS] * 0.5f; // Use half of the Z_AXIS max feed rate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    destination[X_AXIS] = current_position[X_AXIS];
 | 
					    destination[X_AXIS] = current_position[X_AXIS];
 | 
				
			||||||
    destination[Y_AXIS] = current_position[Y_AXIS];
 | 
					    destination[Y_AXIS] = current_position[Y_AXIS];
 | 
				
			||||||
    destination[Z_AXIS] = z;                          // We know the last_z!=z or we wouldn't be in this block of code.
 | 
					    destination[Z_AXIS] = z;                          // We know the last_z!=z or we wouldn't be in this block of code.
 | 
				
			||||||
    destination[E_AXIS] = current_position[E_AXIS];
 | 
					    destination[E_AXIS] = current_position[E_AXIS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    G26_line_to_destination(feed_value);
 | 
					    prepare_internal_move_to_destination(feed_value);
 | 
				
			||||||
    set_destination_from_current();
 | 
					    set_destination_from_current();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Check if X or Y is involved in the movement.
 | 
					  // If X or Y is involved do a 'normal' move. Otherwise retract/recover/hop.
 | 
				
			||||||
  // Yes: a 'normal' movement. No: a retract() or recover()
 | 
					  const feedRate_t feed_value = has_xy_component ? feedRate_t(G26_XY_FEEDRATE) : planner.settings.max_feedrate_mm_s[E_AXIS] * 0.666f;
 | 
				
			||||||
  feed_value = has_xy_component ? G26_XY_FEEDRATE : planner.settings.max_feedrate_mm_s[E_AXIS] / 1.5;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  destination[X_AXIS] = rx;
 | 
					  destination[X_AXIS] = rx;
 | 
				
			||||||
  destination[Y_AXIS] = ry;
 | 
					  destination[Y_AXIS] = ry;
 | 
				
			||||||
  destination[E_AXIS] += e_delta;
 | 
					  destination[E_AXIS] += e_delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  G26_line_to_destination(feed_value);
 | 
					  prepare_internal_move_to_destination(feed_value);
 | 
				
			||||||
  set_destination_from_current();
 | 
					  set_destination_from_current();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -433,6 +424,7 @@ inline bool turn_on_heaters() {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
inline bool prime_nozzle() {
 | 
					inline bool prime_nozzle() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
 | 
				
			||||||
  #if HAS_LCD_MENU
 | 
					  #if HAS_LCD_MENU
 | 
				
			||||||
    #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
 | 
					    #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
 | 
				
			||||||
      float Total_Prime = 0.0;
 | 
					      float Total_Prime = 0.0;
 | 
				
			||||||
@@ -455,7 +447,7 @@ inline bool prime_nozzle() {
 | 
				
			|||||||
          Total_Prime += 0.25;
 | 
					          Total_Prime += 0.25;
 | 
				
			||||||
          if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
 | 
					          if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
        G26_line_to_destination(planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0);
 | 
					        prepare_internal_move_to_destination(fr_slow_e);
 | 
				
			||||||
        set_destination_from_current();
 | 
					        set_destination_from_current();
 | 
				
			||||||
        planner.synchronize();    // Without this synchronize, the purge is more consistent,
 | 
					        planner.synchronize();    // Without this synchronize, the purge is more consistent,
 | 
				
			||||||
                                  // but because the planner has a buffer, we won't be able
 | 
					                                  // but because the planner has a buffer, we won't be able
 | 
				
			||||||
@@ -478,7 +470,7 @@ inline bool prime_nozzle() {
 | 
				
			|||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
    set_destination_from_current();
 | 
					    set_destination_from_current();
 | 
				
			||||||
    destination[E_AXIS] += g26_prime_length;
 | 
					    destination[E_AXIS] += g26_prime_length;
 | 
				
			||||||
    G26_line_to_destination(planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0);
 | 
					    prepare_internal_move_to_destination(fr_slow_e);
 | 
				
			||||||
    set_destination_from_current();
 | 
					    set_destination_from_current();
 | 
				
			||||||
    retract_filament(destination);
 | 
					    retract_filament(destination);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -781,12 +773,13 @@ void GcodeSuite::G26() {
 | 
				
			|||||||
        move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
 | 
					        move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        recover_filament(destination);
 | 
					        recover_filament(destination);
 | 
				
			||||||
        const float save_feedrate = feedrate_mm_s;
 | 
					 | 
				
			||||||
        feedrate_mm_s = PLANNER_XY_FEEDRATE() / 10.0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const feedRate_t old_feedrate = feedrate_mm_s;
 | 
				
			||||||
 | 
					        feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f;
 | 
				
			||||||
        plan_arc(endpoint, arc_offset, false);  // Draw a counter-clockwise arc
 | 
					        plan_arc(endpoint, arc_offset, false);  // Draw a counter-clockwise arc
 | 
				
			||||||
        feedrate_mm_s = save_feedrate;
 | 
					        feedrate_mm_s = old_feedrate;
 | 
				
			||||||
        set_destination_from_current();
 | 
					        set_destination_from_current();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #if HAS_LCD_MENU
 | 
					        #if HAS_LCD_MENU
 | 
				
			||||||
          if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
 | 
					          if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,8 +45,10 @@ void GcodeSuite::G42() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_destination_from_current();
 | 
					    set_destination_from_current();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (hasI) destination[X_AXIS] = _GET_MESH_X(ix);
 | 
					    if (hasI) destination[X_AXIS] = _GET_MESH_X(ix);
 | 
				
			||||||
    if (hasJ) destination[Y_AXIS] = _GET_MESH_Y(iy);
 | 
					    if (hasJ) destination[Y_AXIS] = _GET_MESH_Y(iy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if HAS_BED_PROBE
 | 
					    #if HAS_BED_PROBE
 | 
				
			||||||
      if (parser.boolval('P')) {
 | 
					      if (parser.boolval('P')) {
 | 
				
			||||||
        if (hasI) destination[X_AXIS] -= probe_offset[X_AXIS];
 | 
					        if (hasI) destination[X_AXIS] -= probe_offset[X_AXIS];
 | 
				
			||||||
@@ -54,14 +56,14 @@ void GcodeSuite::G42() {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const float fval = parser.linearval('F');
 | 
					    const feedRate_t fval = parser.linearval('F'),
 | 
				
			||||||
    if (fval > 0.0) feedrate_mm_s = MMM_TO_MMS(fval);
 | 
					                     fr_mm_s = fval > 0 ? MMM_TO_MMS(fval) : 0.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // SCARA kinematic has "safe" XY raw moves
 | 
					    // SCARA kinematic has "safe" XY raw moves
 | 
				
			||||||
    #if IS_SCARA
 | 
					    #if IS_SCARA
 | 
				
			||||||
      prepare_uninterpolated_move_to_destination();
 | 
					      prepare_internal_fast_move_to_destination(fr_mm_s);
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      prepare_move_to_destination();
 | 
					      prepare_internal_move_to_destination(fr_mm_s);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,8 +143,7 @@ void GcodeSuite::G29() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        #if ENABLED(MESH_G28_REST_ORIGIN)
 | 
					        #if ENABLED(MESH_G28_REST_ORIGIN)
 | 
				
			||||||
          current_position[Z_AXIS] = 0;
 | 
					          current_position[Z_AXIS] = 0;
 | 
				
			||||||
          set_destination_from_current();
 | 
					          line_to_current_position(homing_feedrate(Z_AXIS));
 | 
				
			||||||
          buffer_line_to_destination(homing_feedrate(Z_AXIS));
 | 
					 | 
				
			||||||
          planner.synchronize();
 | 
					          planner.synchronize();
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,7 +172,7 @@ inline bool read_calibration_pin() {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
float measuring_movement(const AxisEnum axis, const int dir, const bool stop_state, const bool fast) {
 | 
					float measuring_movement(const AxisEnum axis, const int dir, const bool stop_state, const bool fast) {
 | 
				
			||||||
  const float step     = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION;
 | 
					  const float step     = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION;
 | 
				
			||||||
  const float mms   = MMM_TO_MMS(fast ? CALIBRATION_FEEDRATE_FAST : CALIBRATION_FEEDRATE_SLOW);
 | 
					  const feedRate_t mms = fast ? MMM_TO_MMS(CALIBRATION_FEEDRATE_FAST) : MMM_TO_MMS(CALIBRATION_FEEDRATE_SLOW);
 | 
				
			||||||
  const float limit    = fast ? 50 : 5;
 | 
					  const float limit    = fast ? 50 : 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  set_destination_from_current();
 | 
					  set_destination_from_current();
 | 
				
			||||||
@@ -180,8 +180,7 @@ float measuring_movement(const AxisEnum axis, const int dir, const bool stop_sta
 | 
				
			|||||||
    destination[axis] += dir * step;
 | 
					    destination[axis] += dir * step;
 | 
				
			||||||
    do_blocking_move_to(destination, mms);
 | 
					    do_blocking_move_to(destination, mms);
 | 
				
			||||||
    planner.synchronize();
 | 
					    planner.synchronize();
 | 
				
			||||||
    if (read_calibration_pin() == stop_state)
 | 
					    if (read_calibration_pin() == stop_state) break;
 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return destination[axis];
 | 
					  return destination[axis];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@
 | 
				
			|||||||
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
 | 
					#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
 | 
				
			||||||
#include "../../../core/debug_out.h"
 | 
					#include "../../../core/debug_out.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void jiggle_axis(const char axis_char, const float &min, const float &max, const float &rate) {
 | 
					static void jiggle_axis(const char axis_char, const float &min, const float &max, const feedRate_t &fr_mm_m) {
 | 
				
			||||||
  char gcode_string[30], str1[11], str2[11];
 | 
					  char gcode_string[30], str1[11], str2[11];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Turn the motor(s) both directions
 | 
					  // Turn the motor(s) both directions
 | 
				
			||||||
@@ -84,7 +84,7 @@ void GcodeSuite::M916() {
 | 
				
			|||||||
  uint8_t driver_count = 1;
 | 
					  uint8_t driver_count = 1;
 | 
				
			||||||
  float position_max;
 | 
					  float position_max;
 | 
				
			||||||
  float position_min;
 | 
					  float position_min;
 | 
				
			||||||
  float final_feedrate;
 | 
					  feedRate_t final_fr_mm_m;
 | 
				
			||||||
  uint8_t kval_hold;
 | 
					  uint8_t kval_hold;
 | 
				
			||||||
  uint8_t ocd_th_val = 0;
 | 
					  uint8_t ocd_th_val = 0;
 | 
				
			||||||
  uint8_t stall_th_val = 0;
 | 
					  uint8_t stall_th_val = 0;
 | 
				
			||||||
@@ -93,10 +93,10 @@ void GcodeSuite::M916() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  uint8_t j;   // general purpose counter
 | 
					  uint8_t j;   // general purpose counter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
 | 
					  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
 | 
				
			||||||
    return;  // quit if invalid user input
 | 
					    return;  // quit if invalid user input
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
 | 
					  DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  planner.synchronize();                  // Wait for moves to finish
 | 
					  planner.synchronize();                  // Wait for moves to finish
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,7 +115,7 @@ void GcodeSuite::M916() {
 | 
				
			|||||||
      L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
 | 
					      L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Turn the motor(s) both directions
 | 
					    // Turn the motor(s) both directions
 | 
				
			||||||
    jiggle_axis(axis_mon[0][0], position_min, position_max, final_feedrate);
 | 
					    jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status_composite = 0;    // clear out the old bits
 | 
					    status_composite = 0;    // clear out the old bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -190,7 +190,7 @@ void GcodeSuite::M917() {
 | 
				
			|||||||
  uint8_t driver_count = 1;
 | 
					  uint8_t driver_count = 1;
 | 
				
			||||||
  float position_max;
 | 
					  float position_max;
 | 
				
			||||||
  float position_min;
 | 
					  float position_min;
 | 
				
			||||||
  float final_feedrate;
 | 
					  feedRate_t final_fr_mm_m;
 | 
				
			||||||
  uint8_t kval_hold;
 | 
					  uint8_t kval_hold;
 | 
				
			||||||
  uint8_t ocd_th_val = 0;
 | 
					  uint8_t ocd_th_val = 0;
 | 
				
			||||||
  uint8_t stall_th_val = 0;
 | 
					  uint8_t stall_th_val = 0;
 | 
				
			||||||
@@ -199,10 +199,10 @@ void GcodeSuite::M917() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  uint8_t j;   // general purpose counter
 | 
					  uint8_t j;   // general purpose counter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
 | 
					  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
 | 
				
			||||||
    return;  // quit if invalid user input
 | 
					    return;  // quit if invalid user input
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
 | 
					  DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  planner.synchronize();                // Wait for moves to finish
 | 
					  planner.synchronize();                // Wait for moves to finish
 | 
				
			||||||
  for (j = 0; j < driver_count; j++)
 | 
					  for (j = 0; j < driver_count; j++)
 | 
				
			||||||
@@ -225,7 +225,7 @@ void GcodeSuite::M917() {
 | 
				
			|||||||
    DEBUG_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25);
 | 
					    DEBUG_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25);
 | 
				
			||||||
    DEBUG_ECHOLNPAIR("   OCD threshold : ", (ocd_th_val + 1) * 375);
 | 
					    DEBUG_ECHOLNPAIR("   OCD threshold : ", (ocd_th_val + 1) * 375);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    jiggle_axis(axis_mon[0][0], position_min, position_max, final_feedrate);
 | 
					    jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status_composite = 0;    // clear out the old bits
 | 
					    status_composite = 0;    // clear out the old bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -452,7 +452,7 @@ void GcodeSuite::M918() {
 | 
				
			|||||||
  uint16_t axis_status[3];
 | 
					  uint16_t axis_status[3];
 | 
				
			||||||
  uint8_t driver_count = 1;
 | 
					  uint8_t driver_count = 1;
 | 
				
			||||||
  float position_max, position_min;
 | 
					  float position_max, position_min;
 | 
				
			||||||
  float final_feedrate;
 | 
					  feedRate_t final_fr_mm_m;
 | 
				
			||||||
  uint8_t kval_hold;
 | 
					  uint8_t kval_hold;
 | 
				
			||||||
  uint8_t ocd_th_val = 0;
 | 
					  uint8_t ocd_th_val = 0;
 | 
				
			||||||
  uint8_t stall_th_val = 0;
 | 
					  uint8_t stall_th_val = 0;
 | 
				
			||||||
@@ -461,7 +461,7 @@ void GcodeSuite::M918() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  uint8_t j;   // general purpose counter
 | 
					  uint8_t j;   // general purpose counter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
 | 
					  if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
 | 
				
			||||||
    return;  // quit if invalid user input
 | 
					    return;  // quit if invalid user input
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint8_t m_steps = parser.byteval('M');
 | 
					  uint8_t m_steps = parser.byteval('M');
 | 
				
			||||||
@@ -489,10 +489,7 @@ void GcodeSuite::M918() {
 | 
				
			|||||||
  for (j = 0; j < driver_count; j++)
 | 
					  for (j = 0; j < driver_count; j++)
 | 
				
			||||||
    L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits);   // set microsteps
 | 
					    L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits);   // set microsteps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DEBUG_ECHOLNPAIR("target (maximum) feedrate = ",final_feedrate);
 | 
					  DEBUG_ECHOLNPAIR("target (maximum) feedrate = ", final_fr_mm_m);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  float feedrate_inc = final_feedrate / 10, // start at 1/10 of max & go up by 1/10 per step)
 | 
					 | 
				
			||||||
        current_feedrate = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  planner.synchronize();                  // Wait for moves to finish
 | 
					  planner.synchronize();                  // Wait for moves to finish
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -502,18 +499,19 @@ void GcodeSuite::M918() {
 | 
				
			|||||||
  uint16_t status_composite = 0;
 | 
					  uint16_t status_composite = 0;
 | 
				
			||||||
  DEBUG_ECHOLNPGM(".\n.\n.");             // Make the feedrate prints easier to see
 | 
					  DEBUG_ECHOLNPGM(".\n.\n.");             // Make the feedrate prints easier to see
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  do {
 | 
					  constexpr uint8_t iterations = 10;
 | 
				
			||||||
    current_feedrate += feedrate_inc;
 | 
					  for (uint8_t i = 1; i <= iterations; i++) {
 | 
				
			||||||
    DEBUG_ECHOLNPAIR("...feedrate = ", current_feedrate);
 | 
					    const feedRate_t fr_mm_m = i * final_fr_mm_m / iterations;
 | 
				
			||||||
 | 
					    DEBUG_ECHOLNPAIR("...feedrate = ", fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    jiggle_axis(axis_mon[0][0], position_min, position_max, current_feedrate);
 | 
					    jiggle_axis(axis_mon[0][0], position_min, position_max, fr_mm_m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (j = 0; j < driver_count; j++) {
 | 
					    for (j = 0; j < driver_count; j++) {
 | 
				
			||||||
      axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800;    // bits of interest are all active low
 | 
					      axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800;    // bits of interest are all active low
 | 
				
			||||||
      status_composite |= axis_status[j];
 | 
					      status_composite |= axis_status[j];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (status_composite) break;       // quit if any errors flags are raised
 | 
					    if (status_composite) break;       // quit if any errors flags are raised
 | 
				
			||||||
  } while (current_feedrate < final_feedrate * 0.99);
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DEBUG_ECHOPGM("Completed with errors");
 | 
					  DEBUG_ECHOPGM("Completed with errors");
 | 
				
			||||||
  if (status_composite) {
 | 
					  if (status_composite) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@
 | 
				
			|||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #ifdef PHOTO_RETRACT_MM
 | 
					  #ifdef PHOTO_RETRACT_MM
 | 
				
			||||||
    inline void e_move_m240(const float length, const float fr_mm_s) {
 | 
					    inline void e_move_m240(const float length, const feedRate_t &fr_mm_s) {
 | 
				
			||||||
      if (length && thermalManager.hotEnoughToExtrude(active_extruder)) {
 | 
					      if (length && thermalManager.hotEnoughToExtrude(active_extruder)) {
 | 
				
			||||||
        #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
					        #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
				
			||||||
          do_pause_e_move(length, fr_mm_s);
 | 
					          do_pause_e_move(length, fr_mm_s);
 | 
				
			||||||
@@ -104,7 +104,8 @@ void GcodeSuite::M240() {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #ifdef PHOTO_RETRACT_MM
 | 
					    #ifdef PHOTO_RETRACT_MM
 | 
				
			||||||
      constexpr float rfr = (MMS_TO_MMM(
 | 
					      const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM;
 | 
				
			||||||
 | 
					      feedRate_t sval = (
 | 
				
			||||||
        #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
					        #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
				
			||||||
          PAUSE_PARK_RETRACT_FEEDRATE
 | 
					          PAUSE_PARK_RETRACT_FEEDRATE
 | 
				
			||||||
        #elif ENABLED(FWRETRACT)
 | 
					        #elif ENABLED(FWRETRACT)
 | 
				
			||||||
@@ -112,13 +113,12 @@ void GcodeSuite::M240() {
 | 
				
			|||||||
        #else
 | 
					        #else
 | 
				
			||||||
          45
 | 
					          45
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
      ));
 | 
					      );
 | 
				
			||||||
      const float rval = parser.seenval('R') ? parser.value_linear_units() : _PHOTO_RETRACT_MM,
 | 
					      if (parser.seenval('S')) sval = parser.value_feedrate();
 | 
				
			||||||
                  sval = parser.seenval('S') ? MMM_TO_MMS(parser.value_feedrate()) : rfr;
 | 
					 | 
				
			||||||
      e_move_m240(-rval, sval);
 | 
					      e_move_m240(-rval, sval);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float fr_mm_s = MMM_TO_MMS(parser.linearval('F'));
 | 
					    feedRate_t fr_mm_s = MMM_TO_MMS(parser.linearval('F'));
 | 
				
			||||||
    if (fr_mm_s) NOLESS(fr_mm_s, 10.0f);
 | 
					    if (fr_mm_s) NOLESS(fr_mm_s, 10.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constexpr float photo_position[XYZ] = PHOTO_POSITION;
 | 
					    constexpr float photo_position[XYZ] = PHOTO_POSITION;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,7 +97,7 @@ void GcodeSuite::M701() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Lift Z axis
 | 
					  // Lift Z axis
 | 
				
			||||||
  if (park_point.z > 0)
 | 
					  if (park_point.z > 0)
 | 
				
			||||||
    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), NOZZLE_PARK_Z_FEEDRATE);
 | 
					    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Load filament
 | 
					  // Load filament
 | 
				
			||||||
  #if ENABLED(PRUSA_MMU2)
 | 
					  #if ENABLED(PRUSA_MMU2)
 | 
				
			||||||
@@ -116,7 +116,7 @@ void GcodeSuite::M701() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Restore Z axis
 | 
					  // Restore Z axis
 | 
				
			||||||
  if (park_point.z > 0)
 | 
					  if (park_point.z > 0)
 | 
				
			||||||
    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), NOZZLE_PARK_Z_FEEDRATE);
 | 
					    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
 | 
					  #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
 | 
				
			||||||
    // Restore toolhead if it was changed
 | 
					    // Restore toolhead if it was changed
 | 
				
			||||||
@@ -196,7 +196,7 @@ void GcodeSuite::M702() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Lift Z axis
 | 
					  // Lift Z axis
 | 
				
			||||||
  if (park_point.z > 0)
 | 
					  if (park_point.z > 0)
 | 
				
			||||||
    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), NOZZLE_PARK_Z_FEEDRATE);
 | 
					    do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Unload filament
 | 
					  // Unload filament
 | 
				
			||||||
  #if ENABLED(PRUSA_MMU2)
 | 
					  #if ENABLED(PRUSA_MMU2)
 | 
				
			||||||
@@ -226,7 +226,7 @@ void GcodeSuite::M702() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Restore Z axis
 | 
					  // Restore Z axis
 | 
				
			||||||
  if (park_point.z > 0)
 | 
					  if (park_point.z > 0)
 | 
				
			||||||
    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), NOZZLE_PARK_Z_FEEDRATE);
 | 
					    do_blocking_move_to_z(_MAX(current_position[Z_AXIS] - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
 | 
					  #if EXTRUDERS > 1 && DISABLED(PRUSA_MMU2)
 | 
				
			||||||
    // Restore toolhead if it was changed
 | 
					    // Restore toolhead if it was changed
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,7 +129,7 @@ void GcodeSuite::get_destination_from_command() {
 | 
				
			|||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (parser.linearval('F') > 0)
 | 
					  if (parser.linearval('F') > 0)
 | 
				
			||||||
    feedrate_mm_s = MMM_TO_MMS(parser.value_feedrate());
 | 
					    feedrate_mm_s = parser.value_feedrate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ENABLED(PRINTCOUNTER)
 | 
					  #if ENABLED(PRINTCOUNTER)
 | 
				
			||||||
    if (!DEBUGGING(DRYRUN))
 | 
					    if (!DEBUGGING(DRYRUN))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -370,7 +370,7 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  static void G0_G1(
 | 
					  static void G0_G1(
 | 
				
			||||||
    #if IS_SCARA || defined(G0_FEEDRATE)
 | 
					    #if IS_SCARA || defined(G0_FEEDRATE)
 | 
				
			||||||
      bool fast_move=false
 | 
					      const bool fast_move=false
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@
 | 
				
			|||||||
extern float destination[XYZE];
 | 
					extern float destination[XYZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if ENABLED(VARIABLE_G0_FEEDRATE)
 | 
					#if ENABLED(VARIABLE_G0_FEEDRATE)
 | 
				
			||||||
  float saved_g0_feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE);
 | 
					  feedRate_t fast_move_feedrate = MMM_TO_MMS(G0_FEEDRATE);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -46,7 +46,7 @@ extern float destination[XYZE];
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void GcodeSuite::G0_G1(
 | 
					void GcodeSuite::G0_G1(
 | 
				
			||||||
  #if IS_SCARA || defined(G0_FEEDRATE)
 | 
					  #if IS_SCARA || defined(G0_FEEDRATE)
 | 
				
			||||||
    bool fast_move/*=false*/
 | 
					    const bool fast_move/*=false*/
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,23 +60,23 @@ void GcodeSuite::G0_G1(
 | 
				
			|||||||
  ) {
 | 
					  ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #ifdef G0_FEEDRATE
 | 
					    #ifdef G0_FEEDRATE
 | 
				
			||||||
      float saved_feedrate_mm_s;
 | 
					      feedRate_t old_feedrate;
 | 
				
			||||||
      #if ENABLED(VARIABLE_G0_FEEDRATE)
 | 
					      #if ENABLED(VARIABLE_G0_FEEDRATE)
 | 
				
			||||||
        if (fast_move) {
 | 
					        if (fast_move) {
 | 
				
			||||||
          saved_feedrate_mm_s = feedrate_mm_s;      // Back up the (old) motion mode feedrate
 | 
					          old_feedrate = feedrate_mm_s;             // Back up the (old) motion mode feedrate
 | 
				
			||||||
          feedrate_mm_s = saved_g0_feedrate_mm_s;   // Get G0 feedrate from last usage
 | 
					          feedrate_mm_s = fast_move_feedrate;       // Get G0 feedrate from last usage
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get_destination_from_command(); // For X Y Z E F
 | 
					    get_destination_from_command();                 // Process X Y Z E F parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #ifdef G0_FEEDRATE
 | 
					    #ifdef G0_FEEDRATE
 | 
				
			||||||
      if (fast_move) {
 | 
					      if (fast_move) {
 | 
				
			||||||
        #if ENABLED(VARIABLE_G0_FEEDRATE)
 | 
					        #if ENABLED(VARIABLE_G0_FEEDRATE)
 | 
				
			||||||
          saved_g0_feedrate_mm_s = feedrate_mm_s;   // Save feedrate for the next G0
 | 
					          fast_move_feedrate = feedrate_mm_s;       // Save feedrate for the next G0
 | 
				
			||||||
        #else
 | 
					        #else
 | 
				
			||||||
          saved_feedrate_mm_s = feedrate_mm_s;      // Back up the (new) motion mode feedrate
 | 
					          old_feedrate = feedrate_mm_s;             // Back up the (new) motion mode feedrate
 | 
				
			||||||
          feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE);  // Get the fixed G0 feedrate
 | 
					          feedrate_mm_s = MMM_TO_MMS(G0_FEEDRATE);  // Get the fixed G0 feedrate
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -100,14 +100,14 @@ void GcodeSuite::G0_G1(
 | 
				
			|||||||
    #endif // FWRETRACT
 | 
					    #endif // FWRETRACT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if IS_SCARA
 | 
					    #if IS_SCARA
 | 
				
			||||||
      fast_move ? prepare_uninterpolated_move_to_destination() : prepare_move_to_destination();
 | 
					      fast_move ? prepare_fast_move_to_destination() : prepare_move_to_destination();
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      prepare_move_to_destination();
 | 
					      prepare_move_to_destination();
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #ifdef G0_FEEDRATE
 | 
					    #ifdef G0_FEEDRATE
 | 
				
			||||||
      // Restore the motion mode feedrate
 | 
					      // Restore the motion mode feedrate
 | 
				
			||||||
      if (fast_move) feedrate_mm_s = saved_feedrate_mm_s;
 | 
					      if (fast_move) feedrate_mm_s = old_feedrate;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if ENABLED(NANODLP_Z_SYNC)
 | 
					    #if ENABLED(NANODLP_Z_SYNC)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,10 +146,10 @@ void plan_arc(
 | 
				
			|||||||
  // Initialize the extruder axis
 | 
					  // Initialize the extruder axis
 | 
				
			||||||
  raw[E_AXIS] = current_position[E_AXIS];
 | 
					  raw[E_AXIS] = current_position[E_AXIS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const float fr_mm_s = MMS_SCALED(feedrate_mm_s);
 | 
					  const feedRate_t scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					  #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
    const float inv_duration = fr_mm_s / MM_PER_ARC_SEGMENT;
 | 
					    const float inv_duration = scaled_fr_mm_s / MM_PER_ARC_SEGMENT;
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  millis_t next_idle_ms = millis() + 200UL;
 | 
					  millis_t next_idle_ms = millis() + 200UL;
 | 
				
			||||||
@@ -206,7 +206,7 @@ void plan_arc(
 | 
				
			|||||||
      planner.apply_leveling(raw);
 | 
					      planner.apply_leveling(raw);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!planner.buffer_line(raw, fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
 | 
					    if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
 | 
				
			||||||
      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
        , inv_duration
 | 
					        , inv_duration
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
@@ -226,7 +226,7 @@ void plan_arc(
 | 
				
			|||||||
    planner.apply_leveling(raw);
 | 
					    planner.apply_leveling(raw);
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  planner.buffer_line(raw, fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
 | 
					  planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, MM_PER_ARC_SEGMENT
 | 
				
			||||||
    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
      , inv_duration
 | 
					      , inv_duration
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -364,7 +364,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  #endif // !TEMPERATURE_UNITS_SUPPORT
 | 
					  #endif // !TEMPERATURE_UNITS_SUPPORT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static inline float value_feedrate() { return value_linear_units(); }
 | 
					  static inline feedRate_t value_feedrate() { return MMM_TO_MMS(value_linear_units()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void unknown_command_error();
 | 
					  void unknown_command_error();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,7 +301,7 @@ bool StatusScreen::onTouchHeld(uint8_t tag) {
 | 
				
			|||||||
    case 8:
 | 
					    case 8:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      if (ExtUI::isMoving()) return false;
 | 
					      if (ExtUI::isMoving()) return false;
 | 
				
			||||||
      const float feedrate  =  emin_speed + (fine_motion ? 0 : (emax_speed - emin_speed) * sq(increment));
 | 
					      const feedRate_t feedrate = emin_speed + (fine_motion ? 0 : (emax_speed - emin_speed) * sq(increment));
 | 
				
			||||||
      const float increment = 0.25 * feedrate * (tag == 7 ? -1 : 1);
 | 
					      const float increment = 0.25 * feedrate * (tag == 7 ? -1 : 1);
 | 
				
			||||||
      MoveAxisScreen::setManualFeedrate(E0, feedrate);
 | 
					      MoveAxisScreen::setManualFeedrate(E0, feedrate);
 | 
				
			||||||
      UI_INCREMENT(AxisPosition_mm, E0);
 | 
					      UI_INCREMENT(AxisPosition_mm, E0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -338,6 +338,8 @@ namespace ExtUI {
 | 
				
			|||||||
    return pos;
 | 
					    return pos;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constexpr feedRate_t manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setAxisPosition_mm(const float position, const axis_t axis) {
 | 
					  void setAxisPosition_mm(const float position, const axis_t axis) {
 | 
				
			||||||
    // Start with no limits to movement
 | 
					    // Start with no limits to movement
 | 
				
			||||||
    float min = current_position[axis] - 1000,
 | 
					    float min = current_position[axis] - 1000,
 | 
				
			||||||
@@ -382,23 +384,15 @@ namespace ExtUI {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
					    current_position[axis] = constrain(position, min, max);
 | 
				
			||||||
    setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[axis]));
 | 
					    line_to_current_position(MMM_TO_MMS(manual_feedrate_mm_m[axis]));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    set_destination_from_current();
 | 
					 | 
				
			||||||
    destination[axis] = constrain(position, min, max);
 | 
					 | 
				
			||||||
    prepare_move_to_destination();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setAxisPosition_mm(const float position, const extruder_t extruder) {
 | 
					  void setAxisPosition_mm(const float position, const extruder_t extruder) {
 | 
				
			||||||
    setActiveTool(extruder, true);
 | 
					    setActiveTool(extruder, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
					    current_position[E_AXIS] = position;
 | 
				
			||||||
    setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[E_AXIS]));
 | 
					    line_to_current_position(MMM_TO_MMS(manual_feedrate_mm_m[E_AXIS]));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    set_destination_from_current();
 | 
					 | 
				
			||||||
    destination[E_AXIS] = position;
 | 
					 | 
				
			||||||
    prepare_move_to_destination();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setActiveTool(const extruder_t extruder, bool no_move) {
 | 
					  void setActiveTool(const extruder_t extruder, bool no_move) {
 | 
				
			||||||
@@ -581,20 +575,20 @@ namespace ExtUI {
 | 
				
			|||||||
    planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value;
 | 
					    planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float getAxisMaxFeedrate_mm_s(const axis_t axis) {
 | 
					  feedRate_t getAxisMaxFeedrate_mm_s(const axis_t axis) {
 | 
				
			||||||
    return planner.settings.max_feedrate_mm_s[axis];
 | 
					    return planner.settings.max_feedrate_mm_s[axis];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
 | 
					  feedRate_t getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
 | 
				
			||||||
    UNUSED_E(extruder);
 | 
					    UNUSED_E(extruder);
 | 
				
			||||||
    return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
 | 
					    return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setAxisMaxFeedrate_mm_s(const float value, const axis_t axis) {
 | 
					  void setAxisMaxFeedrate_mm_s(const feedRate_t value, const axis_t axis) {
 | 
				
			||||||
    planner.settings.max_feedrate_mm_s[axis] = value;
 | 
					    planner.settings.max_feedrate_mm_s[axis] = value;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setAxisMaxFeedrate_mm_s(const float value, const extruder_t extruder) {
 | 
					  void setAxisMaxFeedrate_mm_s(const feedRate_t value, const extruder_t extruder) {
 | 
				
			||||||
    UNUSED_E(extruder);
 | 
					    UNUSED_E(extruder);
 | 
				
			||||||
    planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value;
 | 
					    planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -670,15 +664,15 @@ namespace ExtUI {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float getFeedrate_mm_s()                            { return feedrate_mm_s; }
 | 
					  feedRate_t getFeedrate_mm_s()                       { return feedrate_mm_s; }
 | 
				
			||||||
  float getMinFeedrate_mm_s()                         { return planner.settings.min_feedrate_mm_s; }
 | 
					  feedRate_t getMinFeedrate_mm_s()                    { return planner.settings.min_feedrate_mm_s; }
 | 
				
			||||||
  float getMinTravelFeedrate_mm_s()                   { return planner.settings.min_travel_feedrate_mm_s; }
 | 
					  feedRate_t getMinTravelFeedrate_mm_s()              { return planner.settings.min_travel_feedrate_mm_s; }
 | 
				
			||||||
  float getPrintingAcceleration_mm_s2()               { return planner.settings.acceleration; }
 | 
					  float getPrintingAcceleration_mm_s2()               { return planner.settings.acceleration; }
 | 
				
			||||||
  float getRetractAcceleration_mm_s2()                { return planner.settings.retract_acceleration; }
 | 
					  float getRetractAcceleration_mm_s2()                { return planner.settings.retract_acceleration; }
 | 
				
			||||||
  float getTravelAcceleration_mm_s2()                 { return planner.settings.travel_acceleration; }
 | 
					  float getTravelAcceleration_mm_s2()                 { return planner.settings.travel_acceleration; }
 | 
				
			||||||
  void setFeedrate_mm_s(const float fr)               { feedrate_mm_s = fr; }
 | 
					  void setFeedrate_mm_s(const feedRate_t fr)          { feedrate_mm_s = fr; }
 | 
				
			||||||
  void setMinFeedrate_mm_s(const float fr)            { planner.settings.min_feedrate_mm_s = fr; }
 | 
					  void setMinFeedrate_mm_s(const feedRate_t fr)       { planner.settings.min_feedrate_mm_s = fr; }
 | 
				
			||||||
  void setMinTravelFeedrate_mm_s(const float fr)      { planner.settings.min_travel_feedrate_mm_s = fr; }
 | 
					  void setMinTravelFeedrate_mm_s(const feedRate_t fr) { planner.settings.min_travel_feedrate_mm_s = fr; }
 | 
				
			||||||
  void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }
 | 
					  void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }
 | 
				
			||||||
  void setRetractAcceleration_mm_s2(const float acc)  { planner.settings.retract_acceleration = acc; }
 | 
					  void setRetractAcceleration_mm_s2(const float acc)  { planner.settings.retract_acceleration = acc; }
 | 
				
			||||||
  void setTravelAcceleration_mm_s2(const float acc)   { planner.settings.travel_acceleration = acc; }
 | 
					  void setTravelAcceleration_mm_s2(const float acc)   { planner.settings.travel_acceleration = acc; }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,12 +116,12 @@ namespace ExtUI {
 | 
				
			|||||||
  float getAxisPosition_mm(const extruder_t);
 | 
					  float getAxisPosition_mm(const extruder_t);
 | 
				
			||||||
  float getAxisSteps_per_mm(const axis_t);
 | 
					  float getAxisSteps_per_mm(const axis_t);
 | 
				
			||||||
  float getAxisSteps_per_mm(const extruder_t);
 | 
					  float getAxisSteps_per_mm(const extruder_t);
 | 
				
			||||||
  float getAxisMaxFeedrate_mm_s(const axis_t);
 | 
					  feedRate_t getAxisMaxFeedrate_mm_s(const axis_t);
 | 
				
			||||||
  float getAxisMaxFeedrate_mm_s(const extruder_t);
 | 
					  feedRate_t getAxisMaxFeedrate_mm_s(const extruder_t);
 | 
				
			||||||
  float getAxisMaxAcceleration_mm_s2(const axis_t);
 | 
					  float getAxisMaxAcceleration_mm_s2(const axis_t);
 | 
				
			||||||
  float getAxisMaxAcceleration_mm_s2(const extruder_t);
 | 
					  float getAxisMaxAcceleration_mm_s2(const extruder_t);
 | 
				
			||||||
  float getMinFeedrate_mm_s();
 | 
					  feedRate_t getMinFeedrate_mm_s();
 | 
				
			||||||
  float getMinTravelFeedrate_mm_s();
 | 
					  feedRate_t getMinTravelFeedrate_mm_s();
 | 
				
			||||||
  float getPrintingAcceleration_mm_s2();
 | 
					  float getPrintingAcceleration_mm_s2();
 | 
				
			||||||
  float getRetractAcceleration_mm_s2();
 | 
					  float getRetractAcceleration_mm_s2();
 | 
				
			||||||
  float getTravelAcceleration_mm_s2();
 | 
					  float getTravelAcceleration_mm_s2();
 | 
				
			||||||
@@ -160,13 +160,13 @@ namespace ExtUI {
 | 
				
			|||||||
  void setAxisPosition_mm(const float, const extruder_t);
 | 
					  void setAxisPosition_mm(const float, const extruder_t);
 | 
				
			||||||
  void setAxisSteps_per_mm(const float, const axis_t);
 | 
					  void setAxisSteps_per_mm(const float, const axis_t);
 | 
				
			||||||
  void setAxisSteps_per_mm(const float, const extruder_t);
 | 
					  void setAxisSteps_per_mm(const float, const extruder_t);
 | 
				
			||||||
  void setAxisMaxFeedrate_mm_s(const float, const axis_t);
 | 
					  void setAxisMaxFeedrate_mm_s(const feedRate_t, const axis_t);
 | 
				
			||||||
  void setAxisMaxFeedrate_mm_s(const float, const extruder_t);
 | 
					  void setAxisMaxFeedrate_mm_s(const feedRate_t, const extruder_t);
 | 
				
			||||||
  void setAxisMaxAcceleration_mm_s2(const float, const axis_t);
 | 
					  void setAxisMaxAcceleration_mm_s2(const float, const axis_t);
 | 
				
			||||||
  void setAxisMaxAcceleration_mm_s2(const float, const extruder_t);
 | 
					  void setAxisMaxAcceleration_mm_s2(const float, const extruder_t);
 | 
				
			||||||
  void setFeedrate_mm_s(const float);
 | 
					  void setFeedrate_mm_s(const feedRate_t);
 | 
				
			||||||
  void setMinFeedrate_mm_s(const float);
 | 
					  void setMinFeedrate_mm_s(const feedRate_t);
 | 
				
			||||||
  void setMinTravelFeedrate_mm_s(const float);
 | 
					  void setMinTravelFeedrate_mm_s(const feedRate_t);
 | 
				
			||||||
  void setPrintingAcceleration_mm_s2(const float);
 | 
					  void setPrintingAcceleration_mm_s2(const float);
 | 
				
			||||||
  void setRetractAcceleration_mm_s2(const float);
 | 
					  void setRetractAcceleration_mm_s2(const float);
 | 
				
			||||||
  void setTravelAcceleration_mm_s2(const float);
 | 
					  void setTravelAcceleration_mm_s2(const float);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -430,21 +430,21 @@ void _lcd_ubl_map_lcd_edit_cmd() {
 | 
				
			|||||||
 * UBL LCD Map Movement
 | 
					 * UBL LCD Map Movement
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ubl_map_move_to_xy() {
 | 
					void ubl_map_move_to_xy() {
 | 
				
			||||||
  REMEMBER(fr, feedrate_mm_s, MMM_TO_MMS(XY_PROBE_SPEED));
 | 
					  const feedRate_t fr_mm_s = MMM_TO_MMS(XY_PROBE_SPEED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  set_destination_from_current(); // sync destination at the start
 | 
					  set_destination_from_current(); // sync destination at the start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ENABLED(DELTA)
 | 
					  #if ENABLED(DELTA)
 | 
				
			||||||
    if (current_position[Z_AXIS] > delta_clip_start_height) {
 | 
					    if (current_position[Z_AXIS] > delta_clip_start_height) {
 | 
				
			||||||
      destination[Z_AXIS] = delta_clip_start_height;
 | 
					      destination[Z_AXIS] = delta_clip_start_height;
 | 
				
			||||||
      prepare_move_to_destination();
 | 
					      prepare_internal_move_to_destination(fr_mm_s);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  destination[X_AXIS] = pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]);
 | 
					  destination[X_AXIS] = pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]);
 | 
				
			||||||
  destination[Y_AXIS] = pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]);
 | 
					  destination[Y_AXIS] = pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  prepare_move_to_destination();
 | 
					  prepare_internal_move_to_destination(fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -662,11 +662,9 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
 | 
					    if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const feedRate_t fr_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
 | 
				
			||||||
      #if IS_KINEMATIC
 | 
					      #if IS_KINEMATIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const float old_feedrate = feedrate_mm_s;
 | 
					 | 
				
			||||||
        feedrate_mm_s = MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #if EXTRUDERS > 1
 | 
					        #if EXTRUDERS > 1
 | 
				
			||||||
          const int8_t old_extruder = active_extruder;
 | 
					          const int8_t old_extruder = active_extruder;
 | 
				
			||||||
          if (manual_move_axis == E_AXIS) active_extruder = manual_move_e_index;
 | 
					          if (manual_move_axis == E_AXIS) active_extruder = manual_move_e_index;
 | 
				
			||||||
@@ -685,17 +683,16 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
 | 
				
			|||||||
        // previous invocation is being blocked. Modifications to manual_move_offset shouldn't be made while
 | 
					        // previous invocation is being blocked. Modifications to manual_move_offset shouldn't be made while
 | 
				
			||||||
        // processing_manual_move is true or the planner will get out of sync.
 | 
					        // processing_manual_move is true or the planner will get out of sync.
 | 
				
			||||||
        processing_manual_move = true;
 | 
					        processing_manual_move = true;
 | 
				
			||||||
        prepare_move_to_destination(); // will set current_position from destination
 | 
					        prepare_internal_move_to_destination(fr_mm_s);  // will set current_position from destination
 | 
				
			||||||
        processing_manual_move = false;
 | 
					        processing_manual_move = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        feedrate_mm_s = old_feedrate;
 | 
					 | 
				
			||||||
        #if EXTRUDERS > 1
 | 
					        #if EXTRUDERS > 1
 | 
				
			||||||
          active_extruder = old_extruder;
 | 
					          active_extruder = old_extruder;
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #else
 | 
					      #else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        planner.buffer_line(current_position, MMM_TO_MMS(manual_feedrate_mm_m[manual_move_axis]), manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder);
 | 
					        planner.buffer_line(current_position, fr_mm_s, manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder);
 | 
				
			||||||
        manual_move_axis = (int8_t)NO_AXIS;
 | 
					        manual_move_axis = (int8_t)NO_AXIS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@
 | 
				
			|||||||
    typedef void (*menuAction_t)();
 | 
					    typedef void (*menuAction_t)();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Manual Movement
 | 
					    // Manual Movement
 | 
				
			||||||
    constexpr float manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
 | 
					    constexpr feedRate_t manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
 | 
				
			||||||
    extern float move_menu_scale;
 | 
					    extern float move_menu_scale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
					    #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -186,7 +186,7 @@ Nozzle nozzle;
 | 
				
			|||||||
#if ENABLED(NOZZLE_PARK_FEATURE)
 | 
					#if ENABLED(NOZZLE_PARK_FEATURE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void Nozzle::park(const uint8_t z_action, const point_t &park/*=NOZZLE_PARK_POINT*/) {
 | 
					  void Nozzle::park(const uint8_t z_action, const point_t &park/*=NOZZLE_PARK_POINT*/) {
 | 
				
			||||||
    constexpr float fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
 | 
					    constexpr feedRate_t fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (z_action) {
 | 
					    switch (z_action) {
 | 
				
			||||||
      case 1: // Go to Z-park height
 | 
					      case 1: // Go to Z-park height
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -124,6 +124,11 @@ typedef struct {     bool X, Y, Z, X2, Y2, Z2, Z3, E0, E1, E2, E3, E4, E5; } tmc
 | 
				
			|||||||
// Limit an index to an array size
 | 
					// Limit an index to an array size
 | 
				
			||||||
#define ALIM(I,ARR) _MIN(I, COUNT(ARR) - 1)
 | 
					#define ALIM(I,ARR) _MIN(I, COUNT(ARR) - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Defaults for reset / fill in on load
 | 
				
			||||||
 | 
					static const uint32_t   _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION;
 | 
				
			||||||
 | 
					static const float     _DASU[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT;
 | 
				
			||||||
 | 
					static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Current EEPROM Layout
 | 
					 * Current EEPROM Layout
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -1289,21 +1294,19 @@ void MarlinSettings::postprocess() {
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        // Get only the number of E stepper parameters previously stored
 | 
					        // Get only the number of E stepper parameters previously stored
 | 
				
			||||||
        // Any steppers added later are set to their defaults
 | 
					        // Any steppers added later are set to their defaults
 | 
				
			||||||
        const uint32_t def1[] = DEFAULT_MAX_ACCELERATION;
 | 
					 | 
				
			||||||
        const float def2[] = DEFAULT_AXIS_STEPS_PER_UNIT, def3[] = DEFAULT_MAX_FEEDRATE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        uint32_t tmp1[XYZ + esteppers];
 | 
					        uint32_t tmp1[XYZ + esteppers];
 | 
				
			||||||
 | 
					        float tmp2[XYZ + esteppers];
 | 
				
			||||||
 | 
					        feedRate_t tmp3[XYZ + esteppers];
 | 
				
			||||||
        EEPROM_READ(tmp1);                         // max_acceleration_mm_per_s2
 | 
					        EEPROM_READ(tmp1);                         // max_acceleration_mm_per_s2
 | 
				
			||||||
        EEPROM_READ(planner.settings.min_segment_time_us);
 | 
					        EEPROM_READ(planner.settings.min_segment_time_us);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        float tmp2[XYZ + esteppers], tmp3[XYZ + esteppers];
 | 
					 | 
				
			||||||
        EEPROM_READ(tmp2);                         // axis_steps_per_mm
 | 
					        EEPROM_READ(tmp2);                         // axis_steps_per_mm
 | 
				
			||||||
        EEPROM_READ(tmp3);                         // max_feedrate_mm_s
 | 
					        EEPROM_READ(tmp3);                         // max_feedrate_mm_s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!validating) LOOP_XYZE_N(i) {
 | 
					        if (!validating) LOOP_XYZE_N(i) {
 | 
				
			||||||
          const bool in = (i < esteppers + XYZ);
 | 
					          const bool in = (i < esteppers + XYZ);
 | 
				
			||||||
          planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : def1[ALIM(i, def1)];
 | 
					          planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
 | 
				
			||||||
          planner.settings.axis_steps_per_mm[i]          = in ? tmp2[i] : def2[ALIM(i, def2)];
 | 
					          planner.settings.axis_steps_per_mm[i]          = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]);
 | 
				
			||||||
          planner.settings.max_feedrate_mm_s[i]          = in ? tmp3[i] : def3[ALIM(i, def3)];
 | 
					          planner.settings.max_feedrate_mm_s[i]          = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        EEPROM_READ(planner.settings.acceleration);
 | 
					        EEPROM_READ(planner.settings.acceleration);
 | 
				
			||||||
@@ -2205,20 +2208,18 @@ void MarlinSettings::postprocess() {
 | 
				
			|||||||
 * M502 - Reset Configuration
 | 
					 * M502 - Reset Configuration
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void MarlinSettings::reset() {
 | 
					void MarlinSettings::reset() {
 | 
				
			||||||
  static const float tmp1[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] PROGMEM = DEFAULT_MAX_FEEDRATE;
 | 
					 | 
				
			||||||
  static const uint32_t tmp3[] PROGMEM = DEFAULT_MAX_ACCELERATION;
 | 
					 | 
				
			||||||
  LOOP_XYZE_N(i) {
 | 
					  LOOP_XYZE_N(i) {
 | 
				
			||||||
    planner.settings.axis_steps_per_mm[i]          = pgm_read_float(&tmp1[ALIM(i, tmp1)]);
 | 
					    planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
 | 
				
			||||||
    planner.settings.max_feedrate_mm_s[i]          = pgm_read_float(&tmp2[ALIM(i, tmp2)]);
 | 
					    planner.settings.axis_steps_per_mm[i]          = pgm_read_float(&_DASU[ALIM(i, _DASU)]);
 | 
				
			||||||
    planner.settings.max_acceleration_mm_per_s2[i] = pgm_read_dword(&tmp3[ALIM(i, tmp3)]);
 | 
					    planner.settings.max_feedrate_mm_s[i]          = pgm_read_float(&_DMF[ALIM(i, _DMF)]);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  planner.settings.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
 | 
					  planner.settings.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
 | 
				
			||||||
  planner.settings.acceleration = DEFAULT_ACCELERATION;
 | 
					  planner.settings.acceleration = DEFAULT_ACCELERATION;
 | 
				
			||||||
  planner.settings.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
 | 
					  planner.settings.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
 | 
				
			||||||
  planner.settings.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
 | 
					  planner.settings.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
 | 
				
			||||||
  planner.settings.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE;
 | 
					  planner.settings.min_feedrate_mm_s = feedRate_t(DEFAULT_MINIMUMFEEDRATE);
 | 
				
			||||||
  planner.settings.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE;
 | 
					  planner.settings.min_travel_feedrate_mm_s = feedRate_t(DEFAULT_MINTRAVELFEEDRATE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if HAS_CLASSIC_JERK
 | 
					  #if HAS_CLASSIC_JERK
 | 
				
			||||||
    #ifndef DEFAULT_XJERK
 | 
					    #ifndef DEFAULT_XJERK
 | 
				
			||||||
@@ -3039,7 +3040,7 @@ void MarlinSettings::reset() {
 | 
				
			|||||||
      SERIAL_ECHOLNPAIR(
 | 
					      SERIAL_ECHOLNPAIR(
 | 
				
			||||||
          "  M207 S", LINEAR_UNIT(fwretract.settings.retract_length)
 | 
					          "  M207 S", LINEAR_UNIT(fwretract.settings.retract_length)
 | 
				
			||||||
        , " W", LINEAR_UNIT(fwretract.settings.swap_retract_length)
 | 
					        , " W", LINEAR_UNIT(fwretract.settings.swap_retract_length)
 | 
				
			||||||
        , " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.settings.retract_feedrate_mm_s))
 | 
					        , " F", LINEAR_UNIT(MMS_TO_MMM(fwretract.settings.retract_feedrate_mm_s))
 | 
				
			||||||
        , " Z", LINEAR_UNIT(fwretract.settings.retract_zraise)
 | 
					        , " Z", LINEAR_UNIT(fwretract.settings.retract_zraise)
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3048,7 +3049,7 @@ void MarlinSettings::reset() {
 | 
				
			|||||||
      SERIAL_ECHOLNPAIR(
 | 
					      SERIAL_ECHOLNPAIR(
 | 
				
			||||||
          "  M208 S", LINEAR_UNIT(fwretract.settings.retract_recover_extra)
 | 
					          "  M208 S", LINEAR_UNIT(fwretract.settings.retract_recover_extra)
 | 
				
			||||||
        , " W", LINEAR_UNIT(fwretract.settings.swap_retract_recover_extra)
 | 
					        , " W", LINEAR_UNIT(fwretract.settings.swap_retract_recover_extra)
 | 
				
			||||||
        , " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.settings.retract_recover_feedrate_mm_s))
 | 
					        , " F", LINEAR_UNIT(MMS_TO_MMM(fwretract.settings.retract_recover_feedrate_mm_s))
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #if ENABLED(FWRETRACT_AUTORETRACT)
 | 
					      #if ENABLED(FWRETRACT_AUTORETRACT)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -231,12 +231,12 @@ void home_delta() {
 | 
				
			|||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Move all carriages together linearly until an endstop is hit.
 | 
					  // Move all carriages together linearly until an endstop is hit.
 | 
				
			||||||
  destination[Z_AXIS] = (delta_height
 | 
					  current_position[Z_AXIS] = (delta_height + 10
 | 
				
			||||||
    #if HAS_BED_PROBE
 | 
					    #if HAS_BED_PROBE
 | 
				
			||||||
      - probe_offset[Z_AXIS]
 | 
					      - probe_offset[Z_AXIS]
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
    + 10);
 | 
					  );
 | 
				
			||||||
  buffer_line_to_destination(homing_feedrate(X_AXIS));
 | 
					  line_to_current_position(homing_feedrate(X_AXIS));
 | 
				
			||||||
  planner.synchronize();
 | 
					  planner.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Re-enable stealthChop if used. Disable diag1 pin on driver.
 | 
					  // Re-enable stealthChop if used. Disable diag1 pin on driver.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,12 +134,11 @@ float destination[XYZE]; // = { 0 }
 | 
				
			|||||||
// no other feedrate is specified. Overridden for special moves.
 | 
					// no other feedrate is specified. Overridden for special moves.
 | 
				
			||||||
// Set by the last G0 through G5 command's "F" parameter.
 | 
					// Set by the last G0 through G5 command's "F" parameter.
 | 
				
			||||||
// Functions that override this for custom moves *must always* restore it!
 | 
					// Functions that override this for custom moves *must always* restore it!
 | 
				
			||||||
float feedrate_mm_s = MMM_TO_MMS(1500.0f);
 | 
					feedRate_t feedrate_mm_s = MMM_TO_MMS(1500);
 | 
				
			||||||
 | 
					 | 
				
			||||||
int16_t feedrate_percentage = 100;
 | 
					int16_t feedrate_percentage = 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Homing feedrate is const progmem - compare to constexpr in the header
 | 
					// Homing feedrate is const progmem - compare to constexpr in the header
 | 
				
			||||||
const float homing_feedrate_mm_s[XYZ] PROGMEM = {
 | 
					const feedRate_t homing_feedrate_mm_s[XYZ] PROGMEM = {
 | 
				
			||||||
  #if ENABLED(DELTA)
 | 
					  #if ENABLED(DELTA)
 | 
				
			||||||
    MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
 | 
					    MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
 | 
				
			||||||
  #else
 | 
					  #else
 | 
				
			||||||
@@ -285,29 +284,21 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
 | 
				
			|||||||
 * Move the planner to the current position from wherever it last moved
 | 
					 * Move the planner to the current position from wherever it last moved
 | 
				
			||||||
 * (or from wherever it has been told it is located).
 | 
					 * (or from wherever it has been told it is located).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void line_to_current_position(const float &fr_mm_s/*=feedrate_mm_s*/) {
 | 
					void line_to_current_position(const feedRate_t &fr_mm_s/*=feedrate_mm_s*/) {
 | 
				
			||||||
  planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], fr_mm_s, active_extruder);
 | 
					  planner.buffer_line(current_position, fr_mm_s, active_extruder);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Move the planner to the position stored in the destination array, which is
 | 
					 | 
				
			||||||
 * used by G0/G1/G2/G3/G5 and many other functions to set a destination.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void buffer_line_to_destination(const float fr_mm_s) {
 | 
					 | 
				
			||||||
  planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], fr_mm_s, active_extruder);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if IS_KINEMATIC
 | 
					#if IS_KINEMATIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Calculate delta, start a line, and set current_position to destination
 | 
					   * Buffer a fast move without interpolation. Set current_position to destination
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  void prepare_uninterpolated_move_to_destination(const float &fr_mm_s/*=0.0*/) {
 | 
					  void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s/*=MMS_SCALED(feedrate_mm_s)*/) {
 | 
				
			||||||
    if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_uninterpolated_move_to_destination", destination);
 | 
					    if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_fast_move_to_destination", destination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if UBL_SEGMENTED
 | 
					    #if UBL_SEGMENTED
 | 
				
			||||||
      // ubl segmented line will do z-only moves in single segment
 | 
					      // 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));
 | 
					      ubl.line_to_destination_segmented(scaled_fr_mm_s);
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      if ( current_position[X_AXIS] == destination[X_AXIS]
 | 
					      if ( current_position[X_AXIS] == destination[X_AXIS]
 | 
				
			||||||
        && current_position[Y_AXIS] == destination[Y_AXIS]
 | 
					        && current_position[Y_AXIS] == destination[Y_AXIS]
 | 
				
			||||||
@@ -315,7 +306,7 @@ void buffer_line_to_destination(const float fr_mm_s) {
 | 
				
			|||||||
        && current_position[E_AXIS] == destination[E_AXIS]
 | 
					        && current_position[E_AXIS] == destination[E_AXIS]
 | 
				
			||||||
      ) return;
 | 
					      ) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      planner.buffer_line(destination, MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder);
 | 
					      planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_current_from_destination();
 | 
					    set_current_from_destination();
 | 
				
			||||||
@@ -323,14 +314,40 @@ void buffer_line_to_destination(const float fr_mm_s) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#endif // IS_KINEMATIC
 | 
					#endif // IS_KINEMATIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _internal_move_to_destination(const feedRate_t &fr_mm_s/*=0.0f*/
 | 
				
			||||||
 | 
					  #if IS_KINEMATIC
 | 
				
			||||||
 | 
					    , const bool is_fast/*=false*/
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  const feedRate_t old_feedrate = feedrate_mm_s;
 | 
				
			||||||
 | 
					  if (fr_mm_s) feedrate_mm_s = fr_mm_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const uint16_t old_pct = feedrate_percentage;
 | 
				
			||||||
 | 
					  feedrate_percentage = 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const float old_fac = planner.e_factor[active_extruder];
 | 
				
			||||||
 | 
					  planner.e_factor[active_extruder] = 1.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #if IS_KINEMATIC
 | 
				
			||||||
 | 
					    if (is_fast)
 | 
				
			||||||
 | 
					      prepare_fast_move_to_destination();
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					      prepare_move_to_destination();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  feedrate_mm_s = old_feedrate;
 | 
				
			||||||
 | 
					  feedrate_percentage = old_pct;
 | 
				
			||||||
 | 
					  planner.e_factor[active_extruder] = old_fac;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Plan a move to (X, Y, Z) and set the current_position
 | 
					 * Plan a move to (X, Y, Z) and set the current_position
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s/*=0.0*/) {
 | 
					void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s/*=0.0*/) {
 | 
				
			||||||
  if (DEBUGGING(LEVELING)) DEBUG_XYZ(">>> do_blocking_move_to", rx, ry, rz);
 | 
					  if (DEBUGGING(LEVELING)) DEBUG_XYZ(">>> do_blocking_move_to", rx, ry, rz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const float z_feedrate  = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS),
 | 
					  const feedRate_t z_feedrate = fr_mm_s ? fr_mm_s : homing_feedrate(Z_AXIS),
 | 
				
			||||||
              xy_feedrate = fr_mm_s ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S;
 | 
					                  xy_feedrate = fr_mm_s ? fr_mm_s : feedRate_t(XY_PROBE_FEEDRATE_MM_S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ENABLED(DELTA)
 | 
					  #if ENABLED(DELTA)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -348,29 +365,29 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
 | 
				
			|||||||
        destination[X_AXIS] = rx;                             // move directly (uninterpolated)
 | 
					        destination[X_AXIS] = rx;                             // move directly (uninterpolated)
 | 
				
			||||||
        destination[Y_AXIS] = ry;
 | 
					        destination[Y_AXIS] = ry;
 | 
				
			||||||
        destination[Z_AXIS] = rz;
 | 
					        destination[Z_AXIS] = rz;
 | 
				
			||||||
        prepare_uninterpolated_move_to_destination(); // set_current_from_destination()
 | 
					        prepare_internal_fast_move_to_destination();          // set_current_from_destination()
 | 
				
			||||||
        if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position);
 | 
					        if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      destination[Z_AXIS] = delta_clip_start_height;
 | 
					      destination[Z_AXIS] = delta_clip_start_height;
 | 
				
			||||||
      prepare_uninterpolated_move_to_destination(); // set_current_from_destination()
 | 
					      prepare_internal_fast_move_to_destination();            // set_current_from_destination()
 | 
				
			||||||
      if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position);
 | 
					      if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (rz > current_position[Z_AXIS]) {                      // raising?
 | 
					    if (rz > current_position[Z_AXIS]) {                      // raising?
 | 
				
			||||||
      destination[Z_AXIS] = rz;
 | 
					      destination[Z_AXIS] = rz;
 | 
				
			||||||
      prepare_uninterpolated_move_to_destination(z_feedrate);   // set_current_from_destination()
 | 
					      prepare_internal_fast_move_to_destination(z_feedrate);  // set_current_from_destination()
 | 
				
			||||||
      if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position);
 | 
					      if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    destination[X_AXIS] = rx;
 | 
					    destination[X_AXIS] = rx;
 | 
				
			||||||
    destination[Y_AXIS] = ry;
 | 
					    destination[Y_AXIS] = ry;
 | 
				
			||||||
    prepare_move_to_destination();         // set_current_from_destination()
 | 
					    prepare_internal_move_to_destination();                   // set_current_from_destination()
 | 
				
			||||||
    if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position);
 | 
					    if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (rz < current_position[Z_AXIS]) {                      // lowering?
 | 
					    if (rz < current_position[Z_AXIS]) {                      // lowering?
 | 
				
			||||||
      destination[Z_AXIS] = rz;
 | 
					      destination[Z_AXIS] = rz;
 | 
				
			||||||
      prepare_uninterpolated_move_to_destination(z_feedrate);   // set_current_from_destination()
 | 
					      prepare_fast_move_to_destination(z_feedrate);           // set_current_from_destination()
 | 
				
			||||||
      if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position);
 | 
					      if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -383,17 +400,17 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
 | 
				
			|||||||
    // If Z needs to raise, do it before moving XY
 | 
					    // If Z needs to raise, do it before moving XY
 | 
				
			||||||
    if (destination[Z_AXIS] < rz) {
 | 
					    if (destination[Z_AXIS] < rz) {
 | 
				
			||||||
      destination[Z_AXIS] = rz;
 | 
					      destination[Z_AXIS] = rz;
 | 
				
			||||||
      prepare_uninterpolated_move_to_destination(z_feedrate);
 | 
					      prepare_internal_fast_move_to_destination(z_feedrate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    destination[X_AXIS] = rx;
 | 
					    destination[X_AXIS] = rx;
 | 
				
			||||||
    destination[Y_AXIS] = ry;
 | 
					    destination[Y_AXIS] = ry;
 | 
				
			||||||
    prepare_uninterpolated_move_to_destination(xy_feedrate);
 | 
					    prepare_internal_fast_move_to_destination(xy_feedrate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If Z needs to lower, do it after moving XY
 | 
					    // If Z needs to lower, do it after moving XY
 | 
				
			||||||
    if (destination[Z_AXIS] > rz) {
 | 
					    if (destination[Z_AXIS] > rz) {
 | 
				
			||||||
      destination[Z_AXIS] = rz;
 | 
					      destination[Z_AXIS] = rz;
 | 
				
			||||||
      prepare_uninterpolated_move_to_destination(z_feedrate);
 | 
					      prepare_internal_fast_move_to_destination(z_feedrate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #else
 | 
					  #else
 | 
				
			||||||
@@ -420,16 +437,16 @@ void do_blocking_move_to(const float rx, const float ry, const float rz, const f
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  planner.synchronize();
 | 
					  planner.synchronize();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s/*=0.0*/) {
 | 
					void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s/*=0.0*/) {
 | 
				
			||||||
  do_blocking_move_to(rx, current_position[Y_AXIS], current_position[Z_AXIS], fr_mm_s);
 | 
					  do_blocking_move_to(rx, current_position[Y_AXIS], current_position[Z_AXIS], fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void do_blocking_move_to_y(const float &ry, const float &fr_mm_s/*=0.0*/) {
 | 
					void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s/*=0.0*/) {
 | 
				
			||||||
  do_blocking_move_to(current_position[X_AXIS], ry, current_position[Z_AXIS], fr_mm_s);
 | 
					  do_blocking_move_to(current_position[X_AXIS], ry, current_position[Z_AXIS], fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s/*=0.0*/) {
 | 
					void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s/*=0.0*/) {
 | 
				
			||||||
  do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], rz, fr_mm_s);
 | 
					  do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], rz, fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s/*=0.0*/) {
 | 
					void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s/*=0.0*/) {
 | 
				
			||||||
  do_blocking_move_to(rx, ry, current_position[Z_AXIS], fr_mm_s);
 | 
					  do_blocking_move_to(rx, ry, current_position[Z_AXIS], fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -629,31 +646,31 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
   * small incremental moves for DELTA or SCARA.
 | 
					   * small incremental moves for DELTA or SCARA.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * For Unified Bed Leveling (Delta or Segmented Cartesian)
 | 
					   * For Unified Bed Leveling (Delta or Segmented Cartesian)
 | 
				
			||||||
   * the ubl.prepare_segmented_line_to method replaces this.
 | 
					   * the ubl.line_to_destination_segmented method replaces this.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * For Auto Bed Leveling (Bilinear) with SEGMENT_LEVELED_MOVES
 | 
					   * For Auto Bed Leveling (Bilinear) with SEGMENT_LEVELED_MOVES
 | 
				
			||||||
   * this is replaced by segmented_line_to_destination below.
 | 
					   * this is replaced by segmented_line_to_destination below.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  inline bool prepare_kinematic_move_to(const float (&rtarget)[XYZE]) {
 | 
					  inline bool line_to_destination_kinematic() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Get the top feedrate of the move in the XY plane
 | 
					    // Get the top feedrate of the move in the XY plane
 | 
				
			||||||
    const float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
 | 
					    const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const float xdiff = rtarget[X_AXIS] - current_position[X_AXIS],
 | 
					    const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
 | 
				
			||||||
                ydiff = rtarget[Y_AXIS] - current_position[Y_AXIS];
 | 
					                ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If the move is only in Z/E don't split up the move
 | 
					    // If the move is only in Z/E don't split up the move
 | 
				
			||||||
    if (!xdiff && !ydiff) {
 | 
					    if (!xdiff && !ydiff) {
 | 
				
			||||||
      planner.buffer_line(rtarget, _feedrate_mm_s, active_extruder);
 | 
					      planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
 | 
				
			||||||
      return false; // caller will update current_position
 | 
					      return false; // caller will update current_position
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Fail if attempting move outside printable radius
 | 
					    // Fail if attempting move outside printable radius
 | 
				
			||||||
    if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS])) return true;
 | 
					    if (!position_is_reachable(destination[X_AXIS], destination[Y_AXIS])) return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Remaining cartesian distances
 | 
					    // Remaining cartesian distances
 | 
				
			||||||
    const float zdiff = rtarget[Z_AXIS] - current_position[Z_AXIS],
 | 
					    const float zdiff = destination[Z_AXIS] - current_position[Z_AXIS],
 | 
				
			||||||
                ediff = rtarget[E_AXIS] - current_position[E_AXIS];
 | 
					                ediff = destination[E_AXIS] - current_position[E_AXIS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Get the linear distance in XYZ
 | 
					    // Get the linear distance in XYZ
 | 
				
			||||||
    float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff));
 | 
					    float cartesian_mm = SQRT(sq(xdiff) + sq(ydiff) + sq(zdiff));
 | 
				
			||||||
@@ -665,7 +682,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
    if (UNEAR_ZERO(cartesian_mm)) return true;
 | 
					    if (UNEAR_ZERO(cartesian_mm)) return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Minimum number of seconds to move the given distance
 | 
					    // Minimum number of seconds to move the given distance
 | 
				
			||||||
    const float seconds = cartesian_mm / _feedrate_mm_s;
 | 
					    const float seconds = cartesian_mm / scaled_fr_mm_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The number of segments-per-second times the duration
 | 
					    // The number of segments-per-second times the duration
 | 
				
			||||||
    // gives the number of segments
 | 
					    // gives the number of segments
 | 
				
			||||||
@@ -690,7 +707,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
                cartesian_segment_mm = cartesian_mm * inv_segments;
 | 
					                cartesian_segment_mm = cartesian_mm * inv_segments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
      const float inv_duration = _feedrate_mm_s / cartesian_segment_mm;
 | 
					      const float inv_duration = scaled_fr_mm_s / cartesian_segment_mm;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
@@ -717,7 +734,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      LOOP_XYZE(i) raw[i] += segment_distance[i];
 | 
					      LOOP_XYZE(i) raw[i] += segment_distance[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (!planner.buffer_line(raw, _feedrate_mm_s, active_extruder, cartesian_segment_mm
 | 
					      if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
 | 
				
			||||||
        #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					        #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
          , inv_duration
 | 
					          , inv_duration
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
@@ -726,7 +743,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Ensure last segment arrives at target location.
 | 
					    // Ensure last segment arrives at target location.
 | 
				
			||||||
    planner.buffer_line(rtarget, _feedrate_mm_s, active_extruder, cartesian_segment_mm
 | 
					    planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
 | 
				
			||||||
      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
        , inv_duration
 | 
					        , inv_duration
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
@@ -746,7 +763,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
     * small incremental moves. This allows the planner to
 | 
					     * small incremental moves. This allows the planner to
 | 
				
			||||||
     * apply more detailed bed leveling to the full move.
 | 
					     * apply more detailed bed leveling to the full move.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    inline void segmented_line_to_destination(const float &fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) {
 | 
					    inline void segmented_line_to_destination(const feedRate_t &fr_mm_s, const float segment_size=LEVELED_SEGMENT_LENGTH) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
 | 
					      const float xdiff = destination[X_AXIS] - current_position[X_AXIS],
 | 
				
			||||||
                  ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
 | 
					                  ydiff = destination[Y_AXIS] - current_position[Y_AXIS];
 | 
				
			||||||
@@ -784,7 +801,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
                  };
 | 
					                  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
        const float inv_duration = _feedrate_mm_s / cartesian_segment_mm;
 | 
					        const float inv_duration = scaled_fr_mm_s / cartesian_segment_mm;
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // SERIAL_ECHOPAIR("mm=", cartesian_mm);
 | 
					      // SERIAL_ECHOPAIR("mm=", cartesian_mm);
 | 
				
			||||||
@@ -832,13 +849,14 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
   * Returns true if current_position[] was set to destination[]
 | 
					   * Returns true if current_position[] was set to destination[]
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  inline bool prepare_move_to_destination_cartesian() {
 | 
					  inline bool prepare_move_to_destination_cartesian() {
 | 
				
			||||||
 | 
					    const float scaled_fr_mm_s = MMS_SCALED(feedrate_mm_s);
 | 
				
			||||||
    #if HAS_MESH
 | 
					    #if HAS_MESH
 | 
				
			||||||
      if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
 | 
					      if (planner.leveling_active && planner.leveling_active_at_z(destination[Z_AXIS])) {
 | 
				
			||||||
        #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
					        #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
				
			||||||
          ubl.line_to_destination_cartesian(MMS_SCALED(feedrate_mm_s), active_extruder);  // UBL's motion routine needs to know about
 | 
					          ubl.line_to_destination_cartesian(scaled_fr_mm_s, active_extruder); // UBL's motion routine needs to know about
 | 
				
			||||||
          return true;                                                        // all moves, including Z-only moves.
 | 
					          return true;                                                        // all moves, including Z-only moves.
 | 
				
			||||||
        #elif ENABLED(SEGMENT_LEVELED_MOVES)
 | 
					        #elif ENABLED(SEGMENT_LEVELED_MOVES)
 | 
				
			||||||
          segmented_line_to_destination(MMS_SCALED(feedrate_mm_s));
 | 
					          segmented_line_to_destination(scaled_fr_mm_s);
 | 
				
			||||||
          return false; // caller will update current_position
 | 
					          return false; // caller will update current_position
 | 
				
			||||||
        #else
 | 
					        #else
 | 
				
			||||||
          /**
 | 
					          /**
 | 
				
			||||||
@@ -847,9 +865,9 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
           */
 | 
					           */
 | 
				
			||||||
          if (current_position[X_AXIS] != destination[X_AXIS] || current_position[Y_AXIS] != destination[Y_AXIS]) {
 | 
					          if (current_position[X_AXIS] != destination[X_AXIS] || current_position[Y_AXIS] != destination[Y_AXIS]) {
 | 
				
			||||||
            #if ENABLED(MESH_BED_LEVELING)
 | 
					            #if ENABLED(MESH_BED_LEVELING)
 | 
				
			||||||
              mbl.line_to_destination(MMS_SCALED(feedrate_mm_s));
 | 
					              mbl.line_to_destination(scaled_fr_mm_s);
 | 
				
			||||||
            #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
 | 
					            #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
 | 
				
			||||||
              bilinear_line_to_destination(MMS_SCALED(feedrate_mm_s));
 | 
					              bilinear_line_to_destination(scaled_fr_mm_s);
 | 
				
			||||||
            #endif
 | 
					            #endif
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@@ -857,7 +875,7 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    #endif // HAS_MESH
 | 
					    #endif // HAS_MESH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    buffer_line_to_destination(MMS_SCALED(feedrate_mm_s));
 | 
					    planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
 | 
				
			||||||
    return false; // caller will update current_position
 | 
					    return false; // caller will update current_position
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -971,6 +989,8 @@ void restore_feedrate_and_scaling() {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * Make sure current_position[E] and destination[E] are good
 | 
					 * Make sure current_position[E] and destination[E] are good
 | 
				
			||||||
 * before calling or cold/lengthy extrusion may get missed.
 | 
					 * before calling or cold/lengthy extrusion may get missed.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Before exit, current_position is set to destination.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void prepare_move_to_destination() {
 | 
					void prepare_move_to_destination() {
 | 
				
			||||||
  apply_motion_limits(destination);
 | 
					  apply_motion_limits(destination);
 | 
				
			||||||
@@ -1014,14 +1034,13 @@ void prepare_move_to_destination() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (
 | 
					  if (
 | 
				
			||||||
    #if UBL_SEGMENTED
 | 
					    #if UBL_SEGMENTED
 | 
				
			||||||
      //ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))   // This doesn't seem to work correctly on UBL.
 | 
					      #if IS_KINEMATIC // UBL using Kinematic / Cartesian cases as a workaround for now.
 | 
				
			||||||
      #if IS_KINEMATIC                                                          // Use Kinematic / Cartesian cases as a workaround for now.
 | 
					        ubl.line_to_destination_segmented(MMS_SCALED(feedrate_mm_s))
 | 
				
			||||||
        ubl.prepare_segmented_line_to(destination, MMS_SCALED(feedrate_mm_s))
 | 
					 | 
				
			||||||
      #else
 | 
					      #else
 | 
				
			||||||
        prepare_move_to_destination_cartesian()
 | 
					        prepare_move_to_destination_cartesian()
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    #elif IS_KINEMATIC
 | 
					    #elif IS_KINEMATIC
 | 
				
			||||||
      prepare_kinematic_move_to(destination)
 | 
					      line_to_destination_kinematic()
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      prepare_move_to_destination_cartesian()
 | 
					      prepare_move_to_destination_cartesian()
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
@@ -1065,7 +1084,7 @@ bool axis_unhomed_error(uint8_t axis_bits/*=0x07*/) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Homing bump feedrate (mm/s)
 | 
					 * Homing bump feedrate (mm/s)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
float get_homing_bump_feedrate(const AxisEnum axis) {
 | 
					feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
 | 
				
			||||||
  #if HOMING_Z_WITH_PROBE
 | 
					  #if HOMING_Z_WITH_PROBE
 | 
				
			||||||
    if (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW);
 | 
					    if (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW);
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
@@ -1075,7 +1094,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
 | 
				
			|||||||
    hbd = 10;
 | 
					    hbd = 10;
 | 
				
			||||||
    SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1");
 | 
					    SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return homing_feedrate(axis) / hbd;
 | 
					  return homing_feedrate(axis) / float(hbd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if ENABLED(SENSORLESS_HOMING)
 | 
					#if ENABLED(SENSORLESS_HOMING)
 | 
				
			||||||
@@ -1221,7 +1240,7 @@ float get_homing_bump_feedrate(const AxisEnum axis) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Home an individual linear axis
 | 
					 * Home an individual linear axis
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm_s=0.0) {
 | 
					void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t fr_mm_s=0.0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (DEBUGGING(LEVELING)) {
 | 
					  if (DEBUGGING(LEVELING)) {
 | 
				
			||||||
    DEBUG_ECHOPAIR(">>> do_homing_move(", axis_codes[axis], ", ", distance, ", ");
 | 
					    DEBUG_ECHOPAIR(">>> do_homing_move(", axis_codes[axis], ", ", distance, ", ");
 | 
				
			||||||
@@ -1266,12 +1285,13 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
 | 
				
			|||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const feedRate_t real_fr_mm_s = fr_mm_s ? fr_mm_s : homing_feedrate(axis);
 | 
				
			||||||
  #if IS_SCARA
 | 
					  #if IS_SCARA
 | 
				
			||||||
    // Tell the planner the axis is at 0
 | 
					    // Tell the planner the axis is at 0
 | 
				
			||||||
    current_position[axis] = 0;
 | 
					    current_position[axis] = 0;
 | 
				
			||||||
    sync_plan_position();
 | 
					    sync_plan_position();
 | 
				
			||||||
    current_position[axis] = distance;
 | 
					    current_position[axis] = distance;
 | 
				
			||||||
    planner.buffer_line(current_position, fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder);
 | 
					    line_to_current_position(real_fr_mm_s);
 | 
				
			||||||
  #else
 | 
					  #else
 | 
				
			||||||
    float target[ABCE] = { planner.get_axis_position_mm(A_AXIS), planner.get_axis_position_mm(B_AXIS), planner.get_axis_position_mm(C_AXIS), planner.get_axis_position_mm(E_AXIS) };
 | 
					    float target[ABCE] = { planner.get_axis_position_mm(A_AXIS), planner.get_axis_position_mm(B_AXIS), planner.get_axis_position_mm(C_AXIS), planner.get_axis_position_mm(E_AXIS) };
 | 
				
			||||||
    target[axis] = 0;
 | 
					    target[axis] = 0;
 | 
				
			||||||
@@ -1287,7 +1307,7 @@ void do_homing_move(const AxisEnum axis, const float distance, const float fr_mm
 | 
				
			|||||||
      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
        , delta_mm_cart
 | 
					        , delta_mm_cart
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
      , fr_mm_s ? fr_mm_s : homing_feedrate(axis), active_extruder
 | 
					      , real_fr_mm_s, active_extruder
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1507,7 +1527,7 @@ void homeaxis(const AxisEnum axis) {
 | 
				
			|||||||
    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move Away:");
 | 
					    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move Away:");
 | 
				
			||||||
    do_homing_move(axis, -bump
 | 
					    do_homing_move(axis, -bump
 | 
				
			||||||
      #if HOMING_Z_WITH_PROBE
 | 
					      #if HOMING_Z_WITH_PROBE
 | 
				
			||||||
        , axis == Z_AXIS ? MMM_TO_MMS(Z_PROBE_SPEED_FAST) : 0.0
 | 
					        , MMM_TO_MMS(axis == Z_AXIS ? Z_PROBE_SPEED_FAST : 0)
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,17 +85,16 @@ extern float cartes[XYZ];
 | 
				
			|||||||
 * Feed rates are often configured with mm/m
 | 
					 * Feed rates are often configured with mm/m
 | 
				
			||||||
 * but the planner and stepper like mm/s units.
 | 
					 * but the planner and stepper like mm/s units.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
extern const float homing_feedrate_mm_s[XYZ];
 | 
					extern const feedRate_t homing_feedrate_mm_s[XYZ];
 | 
				
			||||||
FORCE_INLINE float homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
 | 
					FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
 | 
				
			||||||
float get_homing_bump_feedrate(const AxisEnum axis);
 | 
					feedRate_t get_homing_bump_feedrate(const AxisEnum axis);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern float feedrate_mm_s;
 | 
					extern feedRate_t feedrate_mm_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Feedrate scaling and conversion
 | 
					 * Feedrate scaling
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
extern int16_t feedrate_percentage;
 | 
					extern int16_t feedrate_percentage;
 | 
				
			||||||
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The active extruder (tool). Set with T<extruder> command.
 | 
					// The active extruder (tool). Set with T<extruder> command.
 | 
				
			||||||
#if EXTRUDERS > 1
 | 
					#if EXTRUDERS > 1
 | 
				
			||||||
@@ -172,34 +171,42 @@ void sync_plan_position_e();
 | 
				
			|||||||
 * Move the planner to the current position from wherever it last moved
 | 
					 * Move the planner to the current position from wherever it last moved
 | 
				
			||||||
 * (or from wherever it has been told it is located).
 | 
					 * (or from wherever it has been told it is located).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void line_to_current_position(const float &fr_mm_s=feedrate_mm_s);
 | 
					void line_to_current_position(const feedRate_t &fr_mm_s=feedrate_mm_s);
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Move the planner to the position stored in the destination array, which is
 | 
					 | 
				
			||||||
 * used by G0/G1/G2/G3/G5 and many other functions to set a destination.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void buffer_line_to_destination(const float fr_mm_s);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if IS_KINEMATIC
 | 
					 | 
				
			||||||
  void prepare_uninterpolated_move_to_destination(const float &fr_mm_s=0);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void prepare_move_to_destination();
 | 
					void prepare_move_to_destination();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f
 | 
				
			||||||
 | 
					  #if IS_KINEMATIC
 | 
				
			||||||
 | 
					    , const bool is_fast=false
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void prepare_internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
 | 
				
			||||||
 | 
					  _internal_move_to_destination(fr_mm_s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IS_KINEMATIC
 | 
				
			||||||
 | 
					  void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inline void prepare_internal_fast_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
 | 
				
			||||||
 | 
					    _internal_move_to_destination(fr_mm_s, true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Blocking movement and shorthand functions
 | 
					 * Blocking movement and shorthand functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0);
 | 
					void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s=0.0f);
 | 
				
			||||||
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0);
 | 
					void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s=0.0f);
 | 
				
			||||||
void do_blocking_move_to_y(const float &ry, const float &fr_mm_s=0);
 | 
					void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s=0.0f);
 | 
				
			||||||
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0);
 | 
					void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s=0.0f);
 | 
				
			||||||
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0);
 | 
					void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s=0.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const float &fr_mm_s=0) {
 | 
					FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZ], const feedRate_t &fr_mm_s=0) {
 | 
				
			||||||
  do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
 | 
					  do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZE], const float &fr_mm_s=0) {
 | 
					FORCE_INLINE void do_blocking_move_to(const float (&raw)[XYZE], const feedRate_t &fr_mm_s=0) {
 | 
				
			||||||
  do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
 | 
					  do_blocking_move_to(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], fr_mm_s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1570,7 +1570,7 @@ bool Planner::_buffer_steps(const int32_t (&target)[XYZE]
 | 
				
			|||||||
  #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					  #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
    , const float (&delta_mm_cart)[XYZE]
 | 
					    , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
  , float fr_mm_s, const uint8_t extruder, const float &millimeters
 | 
					  , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If we are cleaning, do not accept queuing of movements
 | 
					  // If we are cleaning, do not accept queuing of movements
 | 
				
			||||||
@@ -1634,7 +1634,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 | 
				
			|||||||
  #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					  #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
    , const float (&delta_mm_cart)[XYZE]
 | 
					    , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
  , float fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
 | 
					  , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const int32_t da = target[A_AXIS] - position[A_AXIS],
 | 
					  const int32_t da = target[A_AXIS] - position[A_AXIS],
 | 
				
			||||||
@@ -2091,7 +2091,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 | 
				
			|||||||
    #else
 | 
					    #else
 | 
				
			||||||
      const float delta_mm_i = delta_mm[i];
 | 
					      const float delta_mm_i = delta_mm[i];
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
    const float cs = ABS(current_speed[i] = delta_mm_i * inverse_secs);
 | 
					    const feedRate_t cs = ABS(current_speed[i] = delta_mm_i * inverse_secs);
 | 
				
			||||||
    #if ENABLED(DISTINCT_E_FACTORS)
 | 
					    #if ENABLED(DISTINCT_E_FACTORS)
 | 
				
			||||||
      if (i == E_AXIS) i += extruder;
 | 
					      if (i == E_AXIS) i += extruder;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
@@ -2569,7 +2569,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
 | 
				
			|||||||
  #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					  #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
    , const float (&delta_mm_cart)[XYZE]
 | 
					    , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
  , const float &fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
 | 
					  , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters/*=0.0*/
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If we are cleaning, do not accept queuing of movements
 | 
					  // If we are cleaning, do not accept queuing of movements
 | 
				
			||||||
@@ -2651,9 +2651,8 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Add a new linear movement to the buffer.
 | 
					 * Add a new linear movement to the buffer.
 | 
				
			||||||
 * The target is cartesian, it's translated to delta/scara if
 | 
					 * The target is cartesian. It's translated to
 | 
				
			||||||
 * needed.
 | 
					 * delta/scara if needed.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  rx,ry,rz,e   - target position in mm or degrees
 | 
					 *  rx,ry,rz,e   - target position in mm or degrees
 | 
				
			||||||
 *  fr_mm_s      - (target) speed of the move (mm/s)
 | 
					 *  fr_mm_s      - (target) speed of the move (mm/s)
 | 
				
			||||||
@@ -2661,7 +2660,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
 | 
				
			|||||||
 *  millimeters  - the length of the movement, if known
 | 
					 *  millimeters  - the length of the movement, if known
 | 
				
			||||||
 *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
 | 
					 *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters
 | 
					bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters
 | 
				
			||||||
  #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					  #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
    , const float &inv_duration
 | 
					    , const float &inv_duration
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
@@ -2690,10 +2689,10 @@ bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, con
 | 
				
			|||||||
    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					    #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
      // For SCARA scale the feed rate from mm/s to degrees/s
 | 
					      // For SCARA scale the feed rate from mm/s to degrees/s
 | 
				
			||||||
      // i.e., Complete the angular vector in the given time.
 | 
					      // i.e., Complete the angular vector in the given time.
 | 
				
			||||||
      const float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm,
 | 
					      const float duration_recip = inv_duration ? inv_duration : fr_mm_s / mm;
 | 
				
			||||||
                  feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip;
 | 
					      const feedRate_t feedrate = HYPOT(delta[A_AXIS] - position_float[A_AXIS], delta[B_AXIS] - position_float[B_AXIS]) * duration_recip;
 | 
				
			||||||
    #else
 | 
					    #else
 | 
				
			||||||
      const float feedrate = fr_mm_s;
 | 
					      const feedRate_t feedrate = fr_mm_s;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
    if (buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS]
 | 
					    if (buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS]
 | 
				
			||||||
      #if ENABLED(JUNCTION_DEVIATION)
 | 
					      #if ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,12 +172,12 @@ typedef struct block_t {
 | 
				
			|||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
   uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
 | 
					   uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
 | 
				
			||||||
            min_segment_time_us;                // (µs) M205 B
 | 
					            min_segment_time_us;                // (µs) M205 B
 | 
				
			||||||
  float axis_steps_per_mm[XYZE_N],              // (steps) M92 XYZE - Steps per millimeter
 | 
					      float axis_steps_per_mm[XYZE_N];          // (steps) M92 XYZE - Steps per millimeter
 | 
				
			||||||
        max_feedrate_mm_s[XYZE_N],              // (mm/s) M203 XYZE - Max speeds
 | 
					 feedRate_t max_feedrate_mm_s[XYZE_N];          // (mm/s) M203 XYZE - Max speeds
 | 
				
			||||||
        acceleration,                           // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
 | 
					      float acceleration,                       // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
 | 
				
			||||||
            retract_acceleration,               // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
 | 
					            retract_acceleration,               // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
 | 
				
			||||||
        travel_acceleration,                    // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
 | 
					            travel_acceleration;                // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
 | 
				
			||||||
        min_feedrate_mm_s,                      // (mm/s) M205 S - Minimum linear feedrate
 | 
					 feedRate_t min_feedrate_mm_s,                  // (mm/s) M205 S - Minimum linear feedrate
 | 
				
			||||||
            min_travel_feedrate_mm_s;           // (mm/s) M205 T - Minimum travel feedrate
 | 
					            min_travel_feedrate_mm_s;           // (mm/s) M205 T - Minimum travel feedrate
 | 
				
			||||||
} planner_settings_t;
 | 
					} planner_settings_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -585,7 +585,7 @@ class Planner {
 | 
				
			|||||||
      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
        , const float (&delta_mm_cart)[XYZE]
 | 
					        , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
					      , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -608,7 +608,7 @@ class Planner {
 | 
				
			|||||||
      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
        , const float (&delta_mm_cart)[XYZE]
 | 
					        , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
					      , feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -621,7 +621,7 @@ class Planner {
 | 
				
			|||||||
    private:
 | 
					    private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Allow do_homing_move to access internal functions, such as buffer_segment.
 | 
					      // Allow do_homing_move to access internal functions, such as buffer_segment.
 | 
				
			||||||
      friend void do_homing_move(const AxisEnum, const float, const float);
 | 
					      friend void do_homing_move(const AxisEnum, const float, const feedRate_t);
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -640,14 +640,14 @@ class Planner {
 | 
				
			|||||||
      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
        , const float (&delta_mm_cart)[XYZE]
 | 
					        , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
      , const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
					      , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FORCE_INLINE static bool buffer_segment(const float (&abce)[ABCE]
 | 
					    FORCE_INLINE static bool buffer_segment(const float (&abce)[ABCE]
 | 
				
			||||||
      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					      #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
        , const float (&delta_mm_cart)[XYZE]
 | 
					        , const float (&delta_mm_cart)[XYZE]
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
      , const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
					      , const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
      return buffer_segment(abce[A_AXIS], abce[B_AXIS], abce[C_AXIS], abce[E_AXIS]
 | 
					      return buffer_segment(abce[A_AXIS], abce[B_AXIS], abce[C_AXIS], abce[E_AXIS]
 | 
				
			||||||
        #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
					        #if IS_KINEMATIC && ENABLED(JUNCTION_DEVIATION)
 | 
				
			||||||
@@ -660,9 +660,8 @@ class Planner {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Add a new linear movement to the buffer.
 | 
					     * Add a new linear movement to the buffer.
 | 
				
			||||||
     * The target is cartesian, it's translated to delta/scara if
 | 
					     * The target is cartesian. It's translated to
 | 
				
			||||||
     * needed.
 | 
					     * delta/scara if needed.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  rx,ry,rz,e   - target position in mm or degrees
 | 
					     *  rx,ry,rz,e   - target position in mm or degrees
 | 
				
			||||||
     *  fr_mm_s      - (target) speed of the move (mm/s)
 | 
					     *  fr_mm_s      - (target) speed of the move (mm/s)
 | 
				
			||||||
@@ -670,13 +669,13 @@ class Planner {
 | 
				
			|||||||
     *  millimeters  - the length of the movement, if known
 | 
					     *  millimeters  - the length of the movement, if known
 | 
				
			||||||
     *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
 | 
					     *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
 | 
					    static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
 | 
				
			||||||
      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
        , const float &inv_duration=0.0
 | 
					        , const float &inv_duration=0.0
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FORCE_INLINE static bool buffer_line(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
 | 
					    FORCE_INLINE static bool buffer_line(const float (&cart)[XYZE], const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
 | 
				
			||||||
      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
					      #if ENABLED(SCARA_FEEDRATE_SCALING)
 | 
				
			||||||
        , const float &inv_duration=0.0
 | 
					        , const float &inv_duration=0.0
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,13 +107,18 @@ static inline float dist1(const float &x1, const float &y1, const float &x2, con
 | 
				
			|||||||
 * the mitigation offered by MIN_STEP and the small computational
 | 
					 * the mitigation offered by MIN_STEP and the small computational
 | 
				
			||||||
 * power available on Arduino, I think it is not wise to implement it.
 | 
					 * power available on Arduino, I think it is not wise to implement it.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS], const float offset[4], float fr_mm_s, uint8_t extruder) {
 | 
					void cubic_b_spline(
 | 
				
			||||||
 | 
					  const float position[NUM_AXIS],   // current position
 | 
				
			||||||
 | 
					  const float target[NUM_AXIS],     // target position
 | 
				
			||||||
 | 
					  const float (&offset)[4],         // a pair of offsets
 | 
				
			||||||
 | 
					  const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
 | 
				
			||||||
 | 
					  const uint8_t extruder
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
  // Absolute first and second control points are recovered.
 | 
					  // Absolute first and second control points are recovered.
 | 
				
			||||||
  const float first0 = position[X_AXIS] + offset[0],
 | 
					  const float first0 = position[X_AXIS] + offset[0],
 | 
				
			||||||
              first1 = position[Y_AXIS] + offset[1],
 | 
					              first1 = position[Y_AXIS] + offset[1],
 | 
				
			||||||
              second0 = target[X_AXIS] + offset[2],
 | 
					              second0 = target[X_AXIS] + offset[2],
 | 
				
			||||||
              second1 = target[Y_AXIS] + offset[3];
 | 
					              second1 = target[Y_AXIS] + offset[3];
 | 
				
			||||||
  float t = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float bez_target[4];
 | 
					  float bez_target[4];
 | 
				
			||||||
  bez_target[X_AXIS] = position[X_AXIS];
 | 
					  bez_target[X_AXIS] = position[X_AXIS];
 | 
				
			||||||
@@ -122,7 +127,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  millis_t next_idle_ms = millis() + 200UL;
 | 
					  millis_t next_idle_ms = millis() + 200UL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (t < 1) {
 | 
					  for (float t = 0; t < 1;) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    thermalManager.manage_heater();
 | 
					    thermalManager.manage_heater();
 | 
				
			||||||
    millis_t now = millis();
 | 
					    millis_t now = millis();
 | 
				
			||||||
@@ -197,7 +202,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
 | 
				
			|||||||
      const float (&pos)[XYZE] = bez_target;
 | 
					      const float (&pos)[XYZE] = bez_target;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!planner.buffer_line(pos, fr_mm_s, active_extruder, step))
 | 
					    if (!planner.buffer_line(pos, scaled_fr_mm_s, active_extruder, step))
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@
 | 
				
			|||||||
void cubic_b_spline(
 | 
					void cubic_b_spline(
 | 
				
			||||||
  const float position[NUM_AXIS],   // current position
 | 
					  const float position[NUM_AXIS],   // current position
 | 
				
			||||||
  const float target[NUM_AXIS],     // target position
 | 
					  const float target[NUM_AXIS],     // target position
 | 
				
			||||||
              const float offset[4],          // a pair of offsets
 | 
					  const float (&offset)[4],         // a pair of offsets
 | 
				
			||||||
              float fr_mm_s,
 | 
					  const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
 | 
				
			||||||
              uint8_t extruder
 | 
					  const uint8_t extruder
 | 
				
			||||||
            );
 | 
					);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -446,7 +446,7 @@ bool set_probe_deployed(const bool deploy) {
 | 
				
			|||||||
  const char msg_wait_for_bed_heating[25] PROGMEM = "Wait for bed heating...\n";
 | 
					  const char msg_wait_for_bed_heating[25] PROGMEM = "Wait for bed heating...\n";
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool do_probe_move(const float z, const float fr_mm_s) {
 | 
					static bool do_probe_move(const float z, const feedRate_t fr_mm_s) {
 | 
				
			||||||
  if (DEBUGGING(LEVELING)) DEBUG_POS(">>> do_probe_move", current_position);
 | 
					  if (DEBUGGING(LEVELING)) DEBUG_POS(">>> do_probe_move", current_position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER)
 | 
					  #if HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,10 +72,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  typedef struct MPESettings {
 | 
					  typedef struct MPESettings {
 | 
				
			||||||
      float parking_xpos[2],      // M951 L R
 | 
					      float parking_xpos[2],      // M951 L R
 | 
				
			||||||
          grab_distance,        // M951 I
 | 
					            grab_distance;        // M951 I
 | 
				
			||||||
          slow_feedrate,        // M951 J
 | 
					 feedRate_t slow_feedrate,        // M951 J
 | 
				
			||||||
          fast_feedrate,        // M951 H
 | 
					            fast_feedrate;        // M951 H
 | 
				
			||||||
          travel_distance,      // M951 D
 | 
					      float travel_distance,      // M951 D
 | 
				
			||||||
            compensation_factor;  // M951 C
 | 
					            compensation_factor;  // M951 C
 | 
				
			||||||
  } mpe_settings_t;
 | 
					  } mpe_settings_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user