🧑💻 Misc. updates for extra axes (#23521)
This commit is contained in:
		
				
					committed by
					
						
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							39e4310c7b
						
					
				
				
					commit
					5617edbb96
				
			@@ -3224,7 +3224,7 @@
 | 
			
		||||
    #define Z4_SLEW_RATE                 1
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if AXIS_DRIVER_TYPE_I(L6470)
 | 
			
		||||
  #if AXIS_IS_L64XX(I)
 | 
			
		||||
    #define I_MICROSTEPS      128
 | 
			
		||||
    #define I_OVERCURRENT    2000
 | 
			
		||||
    #define I_STALLCURRENT   1500
 | 
			
		||||
@@ -3233,7 +3233,7 @@
 | 
			
		||||
    #define I_SLEW_RATE         1
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if AXIS_DRIVER_TYPE_J(L6470)
 | 
			
		||||
  #if AXIS_IS_L64XX(J)
 | 
			
		||||
    #define J_MICROSTEPS      128
 | 
			
		||||
    #define J_OVERCURRENT    2000
 | 
			
		||||
    #define J_STALLCURRENT   1500
 | 
			
		||||
@@ -3242,7 +3242,7 @@
 | 
			
		||||
    #define J_SLEW_RATE         1
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if AXIS_DRIVER_TYPE_K(L6470)
 | 
			
		||||
  #if AXIS_IS_L64XX(K)
 | 
			
		||||
    #define K_MICROSTEPS      128
 | 
			
		||||
    #define K_OVERCURRENT    2000
 | 
			
		||||
    #define K_STALLCURRENT   1500
 | 
			
		||||
 
 | 
			
		||||
@@ -301,5 +301,6 @@ void setup_endstop_interrupts() {
 | 
			
		||||
      pciSetup(Z_MIN_PROBE_PIN);
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -384,20 +384,14 @@
 | 
			
		||||
    #define STR_I_MIN "w_min"
 | 
			
		||||
    #define STR_I_MAX "w_max"
 | 
			
		||||
  #else
 | 
			
		||||
    #define STR_I "A"
 | 
			
		||||
    #define STR_I_MIN "a_min"
 | 
			
		||||
    #define STR_I_MAX "a_max"
 | 
			
		||||
    #error "AXIS4_NAME can only be one of 'A', 'B', 'C', 'U', 'V', or 'W'."
 | 
			
		||||
  #endif
 | 
			
		||||
#else
 | 
			
		||||
  #define STR_I   ""
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if HAS_J_AXIS
 | 
			
		||||
  #if AXIS5_NAME == 'A'
 | 
			
		||||
    #define STR_J "A"
 | 
			
		||||
    #define STR_J_MIN "a_min"
 | 
			
		||||
    #define STR_J_MAX "a_max"
 | 
			
		||||
  #elif AXIS5_NAME == 'B'
 | 
			
		||||
  #if AXIS5_NAME == 'B'
 | 
			
		||||
    #define STR_J "B"
 | 
			
		||||
    #define STR_J_MIN "b_min"
 | 
			
		||||
    #define STR_J_MAX "b_max"
 | 
			
		||||
@@ -418,24 +412,14 @@
 | 
			
		||||
    #define STR_J_MIN "w_min"
 | 
			
		||||
    #define STR_J_MAX "w_max"
 | 
			
		||||
  #else
 | 
			
		||||
    #define STR_J "B"
 | 
			
		||||
    #define STR_J_MIN "b_min"
 | 
			
		||||
    #define STR_J_MAX "b_max"
 | 
			
		||||
    #error "AXIS5_NAME can only be one of 'B', 'C', 'U', 'V', or 'W'."
 | 
			
		||||
  #endif
 | 
			
		||||
#else
 | 
			
		||||
  #define STR_J   ""
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if HAS_K_AXIS
 | 
			
		||||
  #if AXIS6_NAME == 'A'
 | 
			
		||||
    #define STR_K "A"
 | 
			
		||||
    #define STR_K_MIN "a_min"
 | 
			
		||||
    #define STR_K_MAX "a_max"
 | 
			
		||||
  #elif AXIS6_NAME == 'B'
 | 
			
		||||
    #define STR_K "B"
 | 
			
		||||
    #define STR_K_MIN "b_min"
 | 
			
		||||
    #define STR_K_MAX "b_max"
 | 
			
		||||
  #elif AXIS6_NAME == 'C'
 | 
			
		||||
  #if AXIS6_NAME == 'C'
 | 
			
		||||
    #define STR_K "C"
 | 
			
		||||
    #define STR_K_MIN "c_min"
 | 
			
		||||
    #define STR_K_MAX "c_max"
 | 
			
		||||
@@ -452,9 +436,7 @@
 | 
			
		||||
    #define STR_K_MIN "w_min"
 | 
			
		||||
    #define STR_K_MAX "w_max"
 | 
			
		||||
  #else
 | 
			
		||||
    #define STR_K "C"
 | 
			
		||||
    #define STR_K_MIN "c_min"
 | 
			
		||||
    #define STR_K_MAX "c_max"
 | 
			
		||||
    #error "AXIS6_NAME can only be one of 'C', 'U', 'V', or 'W'."
 | 
			
		||||
  #endif
 | 
			
		||||
#else
 | 
			
		||||
  #define STR_K   ""
 | 
			
		||||
 
 | 
			
		||||
@@ -52,13 +52,13 @@ namespace DirectStepping {
 | 
			
		||||
  volatile bool SerialPageManager<Cfg>::fatal_error;
 | 
			
		||||
 | 
			
		||||
  template<typename Cfg>
 | 
			
		||||
  volatile PageState SerialPageManager<Cfg>::page_states[Cfg::NUM_PAGES];
 | 
			
		||||
  volatile PageState SerialPageManager<Cfg>::page_states[Cfg::PAGE_COUNT];
 | 
			
		||||
 | 
			
		||||
  template<typename Cfg>
 | 
			
		||||
  volatile bool SerialPageManager<Cfg>::page_states_dirty;
 | 
			
		||||
 | 
			
		||||
  template<typename Cfg>
 | 
			
		||||
  uint8_t SerialPageManager<Cfg>::pages[Cfg::NUM_PAGES][Cfg::PAGE_SIZE];
 | 
			
		||||
  uint8_t SerialPageManager<Cfg>::pages[Cfg::PAGE_COUNT][Cfg::PAGE_SIZE];
 | 
			
		||||
 | 
			
		||||
  template<typename Cfg>
 | 
			
		||||
  uint8_t SerialPageManager<Cfg>::checksum;
 | 
			
		||||
@@ -74,7 +74,7 @@ namespace DirectStepping {
 | 
			
		||||
 | 
			
		||||
  template <typename Cfg>
 | 
			
		||||
  void SerialPageManager<Cfg>::init() {
 | 
			
		||||
    for (int i = 0 ; i < Cfg::NUM_PAGES ; i++)
 | 
			
		||||
    for (int i = 0 ; i < Cfg::PAGE_COUNT ; i++)
 | 
			
		||||
      page_states[i] = PageState::FREE;
 | 
			
		||||
 | 
			
		||||
    fatal_error = false;
 | 
			
		||||
@@ -183,10 +183,10 @@ namespace DirectStepping {
 | 
			
		||||
 | 
			
		||||
    SERIAL_CHAR(Cfg::CONTROL_CHAR);
 | 
			
		||||
    constexpr int state_bits = 2;
 | 
			
		||||
    constexpr int n_bytes = Cfg::NUM_PAGES >> state_bits;
 | 
			
		||||
    constexpr int n_bytes = Cfg::PAGE_COUNT >> state_bits;
 | 
			
		||||
    volatile uint8_t bits_b[n_bytes] = { 0 };
 | 
			
		||||
 | 
			
		||||
    for (page_idx_t i = 0 ; i < Cfg::NUM_PAGES ; i++) {
 | 
			
		||||
    for (page_idx_t i = 0 ; i < Cfg::PAGE_COUNT ; i++) {
 | 
			
		||||
      bits_b[i >> state_bits] |= page_states[i] << ((i * state_bits) & 0x7);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -68,10 +68,10 @@ namespace DirectStepping {
 | 
			
		||||
    static State state;
 | 
			
		||||
    static volatile bool fatal_error;
 | 
			
		||||
 | 
			
		||||
    static volatile PageState page_states[Cfg::NUM_PAGES];
 | 
			
		||||
    static volatile PageState page_states[Cfg::PAGE_COUNT];
 | 
			
		||||
    static volatile bool page_states_dirty;
 | 
			
		||||
 | 
			
		||||
    static uint8_t pages[Cfg::NUM_PAGES][Cfg::PAGE_SIZE];
 | 
			
		||||
    static uint8_t pages[Cfg::PAGE_COUNT][Cfg::PAGE_SIZE];
 | 
			
		||||
    static uint8_t checksum;
 | 
			
		||||
    static write_byte_idx_t write_byte_idx;
 | 
			
		||||
    static page_idx_t write_page_idx;
 | 
			
		||||
@@ -87,8 +87,8 @@ namespace DirectStepping {
 | 
			
		||||
  struct config_t {
 | 
			
		||||
    static constexpr char CONTROL_CHAR  = '!';
 | 
			
		||||
 | 
			
		||||
    static constexpr int NUM_PAGES      = num_pages;
 | 
			
		||||
    static constexpr int NUM_AXES       = num_axes;
 | 
			
		||||
    static constexpr int PAGE_COUNT     = num_pages;
 | 
			
		||||
    static constexpr int AXIS_COUNT     = num_axes;
 | 
			
		||||
    static constexpr int BITS_SEGMENT   = bits_segment;
 | 
			
		||||
    static constexpr int DIRECTIONAL    = dir ? 1 : 0;
 | 
			
		||||
    static constexpr int SEGMENTS       = segments;
 | 
			
		||||
@@ -96,10 +96,10 @@ namespace DirectStepping {
 | 
			
		||||
    static constexpr int NUM_SEGMENTS   = _BV(BITS_SEGMENT);
 | 
			
		||||
    static constexpr int SEGMENT_STEPS  = _BV(BITS_SEGMENT - DIRECTIONAL) - 1;
 | 
			
		||||
    static constexpr int TOTAL_STEPS    = SEGMENT_STEPS * SEGMENTS;
 | 
			
		||||
    static constexpr int PAGE_SIZE      = (NUM_AXES * BITS_SEGMENT * SEGMENTS) / 8;
 | 
			
		||||
    static constexpr int PAGE_SIZE      = (AXIS_COUNT * BITS_SEGMENT * SEGMENTS) / 8;
 | 
			
		||||
 | 
			
		||||
    typedef typename TypeSelector<(PAGE_SIZE>256), uint16_t, uint8_t>::type write_byte_idx_t;
 | 
			
		||||
    typedef typename TypeSelector<(NUM_PAGES>256), uint16_t, uint8_t>::type page_idx_t;
 | 
			
		||||
    typedef typename TypeSelector<(PAGE_COUNT>256), uint16_t, uint8_t>::type page_idx_t;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <uint8_t num_pages>
 | 
			
		||||
 
 | 
			
		||||
@@ -421,12 +421,10 @@
 | 
			
		||||
        if (monitor_tmc_driver(stepperI, need_update_error_counters, need_debug_reporting))
 | 
			
		||||
          step_current_down(stepperI);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if AXIS_IS_TMC(J)
 | 
			
		||||
        if (monitor_tmc_driver(stepperJ, need_update_error_counters, need_debug_reporting))
 | 
			
		||||
          step_current_down(stepperJ);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if AXIS_IS_TMC(K)
 | 
			
		||||
        if (monitor_tmc_driver(stepperK, need_update_error_counters, need_debug_reporting))
 | 
			
		||||
          step_current_down(stepperK);
 | 
			
		||||
 
 | 
			
		||||
@@ -262,7 +262,7 @@ void GcodeSuite::G28() {
 | 
			
		||||
  reset_stepper_timeout();
 | 
			
		||||
 | 
			
		||||
  #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
 | 
			
		||||
  #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K) || (ENABLED(DELTA) && HAS_CURRENT_HOME(Z))
 | 
			
		||||
  #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || (ENABLED(DELTA) && HAS_CURRENT_HOME(Z)) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K)
 | 
			
		||||
    #define HAS_HOMING_CURRENT 1
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
@@ -273,22 +273,22 @@ void GcodeSuite::G28() {
 | 
			
		||||
    #if HAS_CURRENT_HOME(X)
 | 
			
		||||
      const int16_t tmc_save_current_X = stepperX.getMilliamps();
 | 
			
		||||
      stepperX.rms_current(X_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F("X"), tmc_save_current_X, X_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_X), tmc_save_current_X, X_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(X2)
 | 
			
		||||
      const int16_t tmc_save_current_X2 = stepperX2.getMilliamps();
 | 
			
		||||
      stepperX2.rms_current(X2_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F("X2"), tmc_save_current_X2, X2_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_X2), tmc_save_current_X2, X2_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(Y)
 | 
			
		||||
      const int16_t tmc_save_current_Y = stepperY.getMilliamps();
 | 
			
		||||
      stepperY.rms_current(Y_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F("Y"), tmc_save_current_Y, Y_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_Y), tmc_save_current_Y, Y_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(Y2)
 | 
			
		||||
      const int16_t tmc_save_current_Y2 = stepperY2.getMilliamps();
 | 
			
		||||
      stepperY2.rms_current(Y2_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F("Y2"), tmc_save_current_Y2, Y2_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_Y2), tmc_save_current_Y2, Y2_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(I)
 | 
			
		||||
      const int16_t tmc_save_current_I = stepperI.getMilliamps();
 | 
			
		||||
@@ -308,7 +308,22 @@ void GcodeSuite::G28() {
 | 
			
		||||
    #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA)
 | 
			
		||||
      const int16_t tmc_save_current_Z = stepperZ.getMilliamps();
 | 
			
		||||
      stepperZ.rms_current(Z_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F("Z"), tmc_save_current_Z, Z_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_Z), tmc_save_current_Z, Z_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(I)
 | 
			
		||||
      const int16_t tmc_save_current_I = stepperI.getMilliamps();
 | 
			
		||||
      stepperI.rms_current(I_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_I), tmc_save_current_I, I_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(J)
 | 
			
		||||
      const int16_t tmc_save_current_J = stepperJ.getMilliamps();
 | 
			
		||||
      stepperJ.rms_current(J_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_J), tmc_save_current_J, J_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_CURRENT_HOME(K)
 | 
			
		||||
      const int16_t tmc_save_current_K = stepperK.getMilliamps();
 | 
			
		||||
      stepperK.rms_current(K_CURRENT_HOME);
 | 
			
		||||
      if (DEBUGGING(LEVELING)) debug_current(F(STR_K), tmc_save_current_K, K_CURRENT_HOME);
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
@@ -361,7 +376,7 @@ void GcodeSuite::G28() {
 | 
			
		||||
                 homeX = needX || parser.seen_test('X'),
 | 
			
		||||
                 homeY = needY || parser.seen_test('Y'),
 | 
			
		||||
                 homeZZ = homeZ,
 | 
			
		||||
                 homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME),
 | 
			
		||||
                 homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME)
 | 
			
		||||
               ),
 | 
			
		||||
               home_all = LINEAR_AXIS_GANG(   // Home-all if all or none are flagged
 | 
			
		||||
                    homeX == homeX, && homeY == homeX, && homeZ == homeX,
 | 
			
		||||
 
 | 
			
		||||
@@ -241,14 +241,15 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
 | 
			
		||||
 | 
			
		||||
  park_above_object(m, uncertainty);
 | 
			
		||||
 | 
			
		||||
  #define _ACASE(N,A,B) case A: dir = -1; case B: axis = N##_AXIS; break
 | 
			
		||||
  #define _PCASE(N) _ACASE(N, N##MINIMUM, N##MAXIMUM)
 | 
			
		||||
 | 
			
		||||
  switch (side) {
 | 
			
		||||
    #if AXIS_CAN_CALIBRATE(X)
 | 
			
		||||
      case RIGHT: dir = -1;
 | 
			
		||||
      case LEFT:  axis = X_AXIS; break;
 | 
			
		||||
      _ACASE(X, RIGHT, LEFT);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Y_AXIS && AXIS_CAN_CALIBRATE(Y)
 | 
			
		||||
      case BACK:  dir = -1;
 | 
			
		||||
      case FRONT: axis = Y_AXIS; break;
 | 
			
		||||
      _ACASE(Y, BACK, FRONT);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
 | 
			
		||||
      case TOP: {
 | 
			
		||||
@@ -259,16 +260,13 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_I_AXIS && AXIS_CAN_CALIBRATE(I)
 | 
			
		||||
      case IMINIMUM: dir = -1;
 | 
			
		||||
      case IMAXIMUM: axis = I_AXIS; break;
 | 
			
		||||
      _PCASE(I);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_J_AXIS && AXIS_CAN_CALIBRATE(J)
 | 
			
		||||
      case JMINIMUM: dir = -1;
 | 
			
		||||
      case JMAXIMUM: axis = J_AXIS; break;
 | 
			
		||||
      _PCASE(J);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_K_AXIS && AXIS_CAN_CALIBRATE(K)
 | 
			
		||||
      case KMINIMUM: dir = -1;
 | 
			
		||||
      case KMAXIMUM: axis = K_AXIS; break;
 | 
			
		||||
      _PCASE(K);
 | 
			
		||||
    #endif
 | 
			
		||||
    default: return;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ void GcodeSuite::M425() {
 | 
			
		||||
        case Z_AXIS: return AXIS_CAN_CALIBRATE(Z),
 | 
			
		||||
        case I_AXIS: return AXIS_CAN_CALIBRATE(I),
 | 
			
		||||
        case J_AXIS: return AXIS_CAN_CALIBRATE(J),
 | 
			
		||||
        case K_AXIS: return AXIS_CAN_CALIBRATE(K),
 | 
			
		||||
        case K_AXIS: return AXIS_CAN_CALIBRATE(K)
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 
 | 
			
		||||
@@ -288,8 +288,13 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) {
 | 
			
		||||
  report_heading_etc(forReplay, F(
 | 
			
		||||
    "Advanced (B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate>"
 | 
			
		||||
    TERN_(HAS_JUNCTION_DEVIATION, " J<junc_dev>")
 | 
			
		||||
    TERN_(HAS_CLASSIC_JERK, " X<max_x_jerk> Y<max_y_jerk> Z<max_z_jerk>")
 | 
			
		||||
    TERN_(HAS_CLASSIC_E_JERK, " E<max_e_jerk>")
 | 
			
		||||
    #if HAS_CLASSIC_JERK
 | 
			
		||||
      LINEAR_AXIS_GANG(
 | 
			
		||||
        " X<max_jerk>", " Y<max_jerk>", " Z<max_jerk>",
 | 
			
		||||
        " " STR_I "<max_jerk>", " " STR_J "<max_jerk>", " " STR_K "<max_jerk>"
 | 
			
		||||
      )
 | 
			
		||||
    #endif
 | 
			
		||||
    TERN_(HAS_CLASSIC_E_JERK, " E<max_jerk>")
 | 
			
		||||
    ")"
 | 
			
		||||
  ));
 | 
			
		||||
  SERIAL_ECHOLNPGM_P(
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,9 @@
 | 
			
		||||
 *  W[linear]   0/1 Enable park & Z Raise
 | 
			
		||||
 *  X[linear]   Park X (Requires TOOLCHANGE_PARK)
 | 
			
		||||
 *  Y[linear]   Park Y (Requires TOOLCHANGE_PARK)
 | 
			
		||||
 *  I[linear]   Park I (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 4)
 | 
			
		||||
 *  J[linear]   Park J (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 5)
 | 
			
		||||
 *  K[linear]   Park K (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 6)
 | 
			
		||||
 *  Z[linear]   Z Raise
 | 
			
		||||
 *  F[linear]   Fan Speed 0-255
 | 
			
		||||
 *  G[linear/s] Fan time
 | 
			
		||||
@@ -88,10 +91,23 @@ void GcodeSuite::M217() {
 | 
			
		||||
  #if ENABLED(TOOLCHANGE_PARK)
 | 
			
		||||
    if (parser.seenval('W')) { toolchange_settings.enable_park = parser.value_linear_units(); }
 | 
			
		||||
    if (parser.seenval('X')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.x = constrain(v, X_MIN_POS, X_MAX_POS); }
 | 
			
		||||
    #if HAS_Y_AXIS
 | 
			
		||||
      if (parser.seenval('Y')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.y = constrain(v, Y_MIN_POS, Y_MAX_POS); }
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_I_AXIS
 | 
			
		||||
      if (parser.seenval('I')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); }
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_J_AXIS
 | 
			
		||||
      if (parser.seenval('J')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); }
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_K_AXIS
 | 
			
		||||
      if (parser.seenval('K')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); }
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if HAS_Z_AXIS
 | 
			
		||||
    if (parser.seenval('Z')) { toolchange_settings.z_raise = parser.value_linear_units(); }
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
 | 
			
		||||
    migration.target = 0;       // 0 = disabled
 | 
			
		||||
@@ -151,9 +167,24 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(TOOLCHANGE_PARK)
 | 
			
		||||
    {
 | 
			
		||||
      SERIAL_ECHOPGM(" W", LINEAR_UNIT(toolchange_settings.enable_park));
 | 
			
		||||
      SERIAL_ECHOPGM_P(SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x));
 | 
			
		||||
      SERIAL_ECHOPGM_P(SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y));
 | 
			
		||||
      SERIAL_ECHOPGM_P(
 | 
			
		||||
            SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x)
 | 
			
		||||
        #if HAS_Y_AXIS
 | 
			
		||||
          , SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y)
 | 
			
		||||
        #endif
 | 
			
		||||
        #if HAS_I_AXIS
 | 
			
		||||
          , SP_I_STR, LINEAR_UNIT(toolchange_settings.change_point.i)
 | 
			
		||||
        #endif
 | 
			
		||||
        #if HAS_J_AXIS
 | 
			
		||||
          , SP_J_STR, LINEAR_UNIT(toolchange_settings.change_point.j)
 | 
			
		||||
        #endif
 | 
			
		||||
        #if HAS_K_AXIS
 | 
			
		||||
          , SP_K_STR, LINEAR_UNIT(toolchange_settings.change_point.k)
 | 
			
		||||
        #endif
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
#include "../../module/planner.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, and E.
 | 
			
		||||
 * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, [I, [J, [K]]] and E.
 | 
			
		||||
 *      (Follows the same syntax as G92)
 | 
			
		||||
 *
 | 
			
		||||
 *      With multiple extruders use T to specify which one.
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,9 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S
 | 
			
		||||
 * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E]
 | 
			
		||||
 *   B<current> - Special case for 4th (E) axis
 | 
			
		||||
 *   S<current> - Special case to set first 3 axes
 | 
			
		||||
 */
 | 
			
		||||
void GcodeSuite::M907() {
 | 
			
		||||
  #if HAS_MOTOR_CURRENT_SPI
 | 
			
		||||
@@ -75,7 +77,7 @@ void GcodeSuite::M907() {
 | 
			
		||||
      if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int());
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
  #endif
 | 
			
		||||
  #endif // HAS_MOTOR_CURRENT_PWM
 | 
			
		||||
 | 
			
		||||
  #if HAS_MOTOR_CURRENT_I2C
 | 
			
		||||
    // this one uses actual amps in floating point
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,9 @@
 | 
			
		||||
 *    L<linear> = Override retract Length
 | 
			
		||||
 *    X<pos>    = Override park position X
 | 
			
		||||
 *    Y<pos>    = Override park position Y
 | 
			
		||||
 *    A<pos>    = Override park position A (requires AXIS*_NAME 'A')
 | 
			
		||||
 *    B<pos>    = Override park position B (requires AXIS*_NAME 'B')
 | 
			
		||||
 *    C<pos>    = Override park position C (requires AXIS*_NAME 'C')
 | 
			
		||||
 *    Z<linear> = Override Z raise
 | 
			
		||||
 *
 | 
			
		||||
 *  With an LCD menu:
 | 
			
		||||
@@ -60,9 +63,15 @@ void GcodeSuite::M125() {
 | 
			
		||||
 | 
			
		||||
  xyz_pos_t park_point = NOZZLE_PARK_POINT;
 | 
			
		||||
 | 
			
		||||
  // Move XY axes to filament change position or given position
 | 
			
		||||
  if (parser.seenval('X')) park_point.x = RAW_X_POSITION(parser.linearval('X'));
 | 
			
		||||
  if (parser.seenval('Y')) park_point.y = RAW_X_POSITION(parser.linearval('Y'));
 | 
			
		||||
  // Move to filament change position or given position
 | 
			
		||||
  LINEAR_AXIS_CODE(
 | 
			
		||||
    if (parser.seenval('X')) park_point.x = RAW_X_POSITION(parser.linearval('X')),
 | 
			
		||||
    if (parser.seenval('Y')) park_point.y = RAW_Y_POSITION(parser.linearval('Y')),
 | 
			
		||||
    NOOP,
 | 
			
		||||
    if (parser.seenval(AXIS4_NAME)) park_point.i = RAW_I_POSITION(parser.linearval(AXIS4_NAME)),
 | 
			
		||||
    if (parser.seenval(AXIS5_NAME)) park_point.j = RAW_J_POSITION(parser.linearval(AXIS5_NAME)),
 | 
			
		||||
    if (parser.seenval(AXIS6_NAME)) park_point.k = RAW_K_POSITION(parser.linearval(AXIS6_NAME))
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  // Lift Z axis
 | 
			
		||||
  if (parser.seenval('Z')) park_point.z = parser.linearval('Z');
 | 
			
		||||
 
 | 
			
		||||
@@ -101,10 +101,8 @@ void GcodeSuite::M600() {
 | 
			
		||||
  if (standardM600)
 | 
			
		||||
    ui.pause_show_message(PAUSE_MESSAGE_CHANGING, PAUSE_MODE_PAUSE_PRINT, target_extruder);
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(HOME_BEFORE_FILAMENT_CHANGE)
 | 
			
		||||
  // If needed, home before parking for filament change
 | 
			
		||||
    home_if_needed(true);
 | 
			
		||||
  #endif
 | 
			
		||||
  TERN_(HOME_BEFORE_FILAMENT_CHANGE, home_if_needed(true));
 | 
			
		||||
 | 
			
		||||
  #if HAS_MULTI_EXTRUDER
 | 
			
		||||
    // Change toolhead if specified
 | 
			
		||||
@@ -118,12 +116,18 @@ void GcodeSuite::M600() {
 | 
			
		||||
 | 
			
		||||
  xyz_pos_t park_point NOZZLE_PARK_POINT;
 | 
			
		||||
 | 
			
		||||
  // Lift Z axis
 | 
			
		||||
  // Lift Z axis first
 | 
			
		||||
  if (parser.seenval('Z')) park_point.z = parser.linearval('Z');
 | 
			
		||||
 | 
			
		||||
  // Move XY axes to filament change position or given position
 | 
			
		||||
  if (parser.seenval('X')) park_point.x = parser.linearval('X');
 | 
			
		||||
  if (parser.seenval('Y')) park_point.y = parser.linearval('Y');
 | 
			
		||||
  LINEAR_AXIS_CODE(
 | 
			
		||||
    if (parser.seenval('X')) park_point.x = parser.linearval('X'),
 | 
			
		||||
    if (parser.seenval('Y')) park_point.y = parser.linearval('Y'),
 | 
			
		||||
    NOOP,
 | 
			
		||||
    if (parser.seenval(AXIS4_NAME)) park_point.i = parser.linearval(AXIS4_NAME);
 | 
			
		||||
    if (parser.seenval(AXIS5_NAME)) park_point.j = parser.linearval(AXIS5_NAME);
 | 
			
		||||
    if (parser.seenval(AXIS6_NAME)) park_point.k = parser.linearval(AXIS6_NAME);
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA)
 | 
			
		||||
    park_point += hotend_offset[active_extruder];
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,9 @@ static void tmc_print_current(TMC &st) {
 | 
			
		||||
 *   X[current]  - Set mA current for X driver(s)
 | 
			
		||||
 *   Y[current]  - Set mA current for Y driver(s)
 | 
			
		||||
 *   Z[current]  - Set mA current for Z driver(s)
 | 
			
		||||
 *   A[current]  - Set mA current for A driver(s) (Requires AXIS*_NAME 'A')
 | 
			
		||||
 *   B[current]  - Set mA current for B driver(s) (Requires AXIS*_NAME 'B')
 | 
			
		||||
 *   C[current]  - Set mA current for C driver(s) (Requires AXIS*_NAME 'C')
 | 
			
		||||
 *   E[current]  - Set mA current for E driver(s)
 | 
			
		||||
 *
 | 
			
		||||
 *   I[index]    - Axis sub-index (Omit or 0 for X, Y, Z; 1 for X2, Y2, Z2; 2 for Z3; 3 for Z4.)
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * G92: Set the Current Position to the given X Y Z E values.
 | 
			
		||||
 * G92: Set the Current Position to the given X [Y [Z [A [B [C [E]]]]]] values.
 | 
			
		||||
 *
 | 
			
		||||
 * Behind the scenes the G92 command may modify the Current Position
 | 
			
		||||
 * or the Position Shift depending on settings and sub-commands.
 | 
			
		||||
@@ -37,14 +37,14 @@
 | 
			
		||||
 * Since E has no Workspace Offset, it is always set directly.
 | 
			
		||||
 *
 | 
			
		||||
 * Without Workspace Offsets (e.g., with NO_WORKSPACE_OFFSETS):
 | 
			
		||||
 *   G92   : Set NATIVE Current Position to the given X Y Z E.
 | 
			
		||||
 *   G92   : Set NATIVE Current Position to the given X [Y [Z [A [B [C [E]]]]]].
 | 
			
		||||
 *
 | 
			
		||||
 * Using Workspace Offsets (default Marlin behavior):
 | 
			
		||||
 *   G92   : Modify Workspace Offsets so the reported position shows the given X Y Z E.
 | 
			
		||||
 *   G92   : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [E]]]]]].
 | 
			
		||||
 *   G92.1 : Zero XYZ Workspace Offsets (so the reported position = the native position).
 | 
			
		||||
 *
 | 
			
		||||
 * With POWER_LOSS_RECOVERY:
 | 
			
		||||
 *   G92.9 : Set NATIVE Current Position to the given X Y Z E.
 | 
			
		||||
 *   G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [E]]]]]].
 | 
			
		||||
 */
 | 
			
		||||
void GcodeSuite::G92() {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2214,6 +2214,7 @@
 | 
			
		||||
#define TMC_UART_IS(A,N) (defined(A##_HARDWARE_SERIAL) && (CAT(HW_,A##_HARDWARE_SERIAL) == HW_Serial##N || CAT(HW_,A##_HARDWARE_SERIAL) == HW_MSerial##N))
 | 
			
		||||
#define ANY_SERIAL_IS(N) (  CONF_SERIAL_IS(N) \
 | 
			
		||||
                         || TMC_UART_IS(X,  N) || TMC_UART_IS(Y , N) || TMC_UART_IS(Z , N) \
 | 
			
		||||
                         || TMC_UART_IS(I,  N) || TMC_UART_IS(J , N) || TMC_UART_IS(K , N) \
 | 
			
		||||
                         || TMC_UART_IS(X2, N) || TMC_UART_IS(Y2, N) || TMC_UART_IS(Z2, N) || TMC_UART_IS(Z3, N) || TMC_UART_IS(Z4, N) \
 | 
			
		||||
                         || TMC_UART_IS(E0, N) || TMC_UART_IS(E1, N) || TMC_UART_IS(E2, N) || TMC_UART_IS(E3, N) || TMC_UART_IS(E4, N) )
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -791,6 +791,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
 | 
			
		||||
  #error "Enable only one of ENDSTOPPULLUP_Y_MAX or ENDSTOPPULLDOWN_Y_MAX."
 | 
			
		||||
#elif BOTH(ENDSTOPPULLUP_ZMAX, ENDSTOPPULLDOWN_ZMAX)
 | 
			
		||||
  #error "Enable only one of ENDSTOPPULLUP_Z_MAX or ENDSTOPPULLDOWN_Z_MAX."
 | 
			
		||||
#elif BOTH(ENDSTOPPULLUP_IMAX, ENDSTOPPULLDOWN_IMAX)
 | 
			
		||||
  #error "Enable only one of ENDSTOPPULLUP_I_MAX or ENDSTOPPULLDOWN_I_MAX."
 | 
			
		||||
#elif BOTH(ENDSTOPPULLUP_JMAX, ENDSTOPPULLDOWN_JMAX)
 | 
			
		||||
  #error "Enable only one of ENDSTOPPULLUP_J_MAX or ENDSTOPPULLDOWN_J_MAX."
 | 
			
		||||
#elif BOTH(ENDSTOPPULLUP_KMAX, ENDSTOPPULLDOWN_KMAX)
 | 
			
		||||
  #error "Enable only one of ENDSTOPPULLUP_K_MAX or ENDSTOPPULLDOWN_K_MAX."
 | 
			
		||||
#elif BOTH(ENDSTOPPULLUP_XMIN, ENDSTOPPULLDOWN_XMIN)
 | 
			
		||||
  #error "Enable only one of ENDSTOPPULLUP_X_MIN or ENDSTOPPULLDOWN_X_MIN."
 | 
			
		||||
#elif BOTH(ENDSTOPPULLUP_YMIN, ENDSTOPPULLDOWN_YMIN)
 | 
			
		||||
@@ -1417,9 +1423,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
 | 
			
		||||
 * Allow only extra axis codes that do not conflict with G-code parameter names
 | 
			
		||||
 */
 | 
			
		||||
#if HAS_I_AXIS
 | 
			
		||||
  #if AXIS4_NAME != 'A' && AXIS4_NAME != 'B' && AXIS4_NAME != 'C' && AXIS4_NAME != 'U' && AXIS4_NAME != 'V' && AXIS4_NAME != 'W'
 | 
			
		||||
    #error "AXIS4_NAME can only be one of 'A', 'B', 'C', 'U', 'V', or 'W'."
 | 
			
		||||
  #elif !defined(I_MIN_POS) || !defined(I_MAX_POS)
 | 
			
		||||
  #if !defined(I_MIN_POS) || !defined(I_MAX_POS)
 | 
			
		||||
    #error "I_MIN_POS and I_MAX_POS are required with LINEAR_AXES >= 4."
 | 
			
		||||
  #elif !defined(I_HOME_DIR)
 | 
			
		||||
    #error "I_HOME_DIR is required with LINEAR_AXES >= 4."
 | 
			
		||||
@@ -1430,8 +1434,6 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
 | 
			
		||||
#if HAS_J_AXIS
 | 
			
		||||
  #if AXIS5_NAME == AXIS4_NAME
 | 
			
		||||
    #error "AXIS5_NAME must be unique."
 | 
			
		||||
  #elif AXIS5_NAME != 'A' && AXIS5_NAME != 'B' && AXIS5_NAME != 'C' && AXIS5_NAME != 'U' && AXIS5_NAME != 'V' && AXIS5_NAME != 'W'
 | 
			
		||||
    #error "AXIS5_NAME can only be one of 'A', 'B', 'C', 'U', 'V', or 'W'."
 | 
			
		||||
  #elif !defined(J_MIN_POS) || !defined(J_MAX_POS)
 | 
			
		||||
    #error "J_MIN_POS and J_MAX_POS are required with LINEAR_AXES >= 5."
 | 
			
		||||
  #elif !defined(J_HOME_DIR)
 | 
			
		||||
@@ -1443,8 +1445,6 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
 | 
			
		||||
#if HAS_K_AXIS
 | 
			
		||||
  #if AXIS6_NAME == AXIS5_NAME || AXIS6_NAME == AXIS4_NAME
 | 
			
		||||
    #error "AXIS6_NAME must be unique."
 | 
			
		||||
  #elif AXIS6_NAME != 'A' && AXIS6_NAME != 'B' && AXIS6_NAME != 'C' && AXIS6_NAME != 'U' && AXIS6_NAME != 'V' && AXIS6_NAME != 'W'
 | 
			
		||||
    #error "AXIS6_NAME can only be one of 'A', 'B', 'C', 'U', 'V', or 'W'."
 | 
			
		||||
  #elif !defined(K_MIN_POS) || !defined(K_MAX_POS)
 | 
			
		||||
    #error "K_MIN_POS and K_MAX_POS are required with LINEAR_AXES >= 6."
 | 
			
		||||
  #elif !defined(K_HOME_DIR)
 | 
			
		||||
@@ -3304,7 +3304,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
 | 
			
		||||
 * L64XX requirement
 | 
			
		||||
 */
 | 
			
		||||
#if HAS_L64XX && HAS_I_AXIS
 | 
			
		||||
  #error "L64XX requires LINEAR_AXES 3. Homing with L64XX is not yet implemented for LINEAR_AXES > 3."
 | 
			
		||||
  #error "L64XX requires LINEAR_AXES <= 3. Homing with L64XX is not yet implemented for LINEAR_AXES > 3."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -3780,22 +3780,15 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
 | 
			
		||||
#if _BAD_DRIVER(Z)
 | 
			
		||||
  #error "Z_DRIVER_TYPE is not recognized."
 | 
			
		||||
#endif
 | 
			
		||||
#if HAS_I_AXIS
 | 
			
		||||
#if _BAD_DRIVER(I)
 | 
			
		||||
  #error "I_DRIVER_TYPE is not recognized."
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if HAS_J_AXIS
 | 
			
		||||
#if _BAD_DRIVER(J)
 | 
			
		||||
  #error "J_DRIVER_TYPE is not recognized."
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if HAS_K_AXIS
 | 
			
		||||
#if _BAD_DRIVER(K)
 | 
			
		||||
  #error "K_DRIVER_TYPE is not recognized."
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if _BAD_DRIVER(X2)
 | 
			
		||||
  #error "X2_DRIVER_TYPE is not recognized."
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -467,8 +467,8 @@ void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plan a move to (X, Y, Z, [I, [J, [K]]]) and set the current_position
 | 
			
		||||
 * Plan a move to (X, Y, Z) with separation of Z from other components.
 | 
			
		||||
 * Plan a move to (X, Y, Z, [I, [J, [K...]]]) and set the current_position
 | 
			
		||||
 * Plan a move to (X, Y, Z, [I, [J, [K...]]]) with separation of Z from other components.
 | 
			
		||||
 *
 | 
			
		||||
 * - If Z is moving up, the Z move is done before XY, etc.
 | 
			
		||||
 * - If Z is moving down, the Z move is done after XY, etc.
 | 
			
		||||
@@ -484,6 +484,15 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s
 | 
			
		||||
  #if HAS_Z_AXIS
 | 
			
		||||
    const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if HAS_I_AXIS
 | 
			
		||||
    const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if HAS_J_AXIS
 | 
			
		||||
    const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if HAS_K_AXIS
 | 
			
		||||
    const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if IS_KINEMATIC
 | 
			
		||||
    if (!position_is_reachable(x, y)) return;
 | 
			
		||||
@@ -528,39 +537,32 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s
 | 
			
		||||
  #elif IS_SCARA
 | 
			
		||||
 | 
			
		||||
    // If Z needs to raise, do it before moving XY
 | 
			
		||||
    if (destination.z < z) {
 | 
			
		||||
      destination.z = z;
 | 
			
		||||
      prepare_internal_fast_move_to_destination(z_feedrate);
 | 
			
		||||
    }
 | 
			
		||||
    if (destination.z < z) { destination.z = z; prepare_internal_fast_move_to_destination(z_feedrate); }
 | 
			
		||||
 | 
			
		||||
    destination.set(x, y);
 | 
			
		||||
    prepare_internal_fast_move_to_destination(xy_feedrate);
 | 
			
		||||
    destination.set(x, y); prepare_internal_fast_move_to_destination(xy_feedrate);
 | 
			
		||||
 | 
			
		||||
    // If Z needs to lower, do it after moving XY
 | 
			
		||||
    if (destination.z > z) {
 | 
			
		||||
      destination.z = z;
 | 
			
		||||
      prepare_internal_fast_move_to_destination(z_feedrate);
 | 
			
		||||
    }
 | 
			
		||||
    if (destination.z > z) { destination.z = z; prepare_internal_fast_move_to_destination(z_feedrate); }
 | 
			
		||||
 | 
			
		||||
  #else
 | 
			
		||||
 | 
			
		||||
    #if HAS_Z_AXIS
 | 
			
		||||
      // If Z needs to raise, do it before moving XY
 | 
			
		||||
      if (current_position.z < z) {
 | 
			
		||||
        current_position.z = z;
 | 
			
		||||
        line_to_current_position(z_feedrate);
 | 
			
		||||
      }
 | 
			
		||||
    #if HAS_Z_AXIS  // If Z needs to raise, do it before moving XY
 | 
			
		||||
      if (current_position.z < z) { current_position.z = z; line_to_current_position(z_feedrate); }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    current_position.set(x, y);
 | 
			
		||||
    line_to_current_position(xy_feedrate);
 | 
			
		||||
    current_position.set(x, y); line_to_current_position(xy_feedrate);
 | 
			
		||||
 | 
			
		||||
    #if HAS_Z_AXIS
 | 
			
		||||
      // If Z needs to lower, do it after moving XY
 | 
			
		||||
      if (current_position.z > z) {
 | 
			
		||||
        current_position.z = z;
 | 
			
		||||
        line_to_current_position(z_feedrate);
 | 
			
		||||
      }
 | 
			
		||||
    #if HAS_I_AXIS
 | 
			
		||||
      current_position.i = i; line_to_current_position(i_feedrate);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_J_AXIS
 | 
			
		||||
      current_position.j = j; line_to_current_position(j_feedrate);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_K_AXIS
 | 
			
		||||
      current_position.k = k; line_to_current_position(k_feedrate);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Z_AXIS  // If Z needs to lower, do it after moving XY...
 | 
			
		||||
      if (current_position.z > z) { current_position.z = z; line_to_current_position(z_feedrate); }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
  #endif
 | 
			
		||||
@@ -1402,6 +1404,15 @@ void prepare_line_to_destination() {
 | 
			
		||||
            #endif
 | 
			
		||||
            break;
 | 
			
		||||
        #endif
 | 
			
		||||
        #if I_SENSORLESS
 | 
			
		||||
          case I_AXIS: stealth_states.i = tmc_enable_stallguard(stepperI); break;
 | 
			
		||||
        #endif
 | 
			
		||||
        #if J_SENSORLESS
 | 
			
		||||
          case J_AXIS: stealth_states.j = tmc_enable_stallguard(stepperJ); break;
 | 
			
		||||
        #endif
 | 
			
		||||
        #if K_SENSORLESS
 | 
			
		||||
          case K_AXIS: stealth_states.k = tmc_enable_stallguard(stepperK); break;
 | 
			
		||||
        #endif
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      #if ENABLED(SPI_ENDSTOPS)
 | 
			
		||||
@@ -1479,6 +1490,15 @@ void prepare_line_to_destination() {
 | 
			
		||||
            #endif
 | 
			
		||||
            break;
 | 
			
		||||
        #endif
 | 
			
		||||
        #if I_SENSORLESS
 | 
			
		||||
          case I_AXIS: tmc_disable_stallguard(stepperI, enable_stealth.i); break;
 | 
			
		||||
        #endif
 | 
			
		||||
        #if J_SENSORLESS
 | 
			
		||||
          case J_AXIS: tmc_disable_stallguard(stepperJ, enable_stealth.j); break;
 | 
			
		||||
        #endif
 | 
			
		||||
        #if K_SENSORLESS
 | 
			
		||||
          case K_AXIS: tmc_disable_stallguard(stepperK, enable_stealth.k); break;
 | 
			
		||||
        #endif
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      #if ENABLED(SPI_ENDSTOPS)
 | 
			
		||||
@@ -1815,8 +1835,12 @@ void prepare_line_to_destination() {
 | 
			
		||||
        switch (axis) {
 | 
			
		||||
          default:
 | 
			
		||||
          case X_AXIS: es = X_ENDSTOP; break;
 | 
			
		||||
          #if HAS_Y_AXIS
 | 
			
		||||
            case Y_AXIS: es = Y_ENDSTOP; break;
 | 
			
		||||
          #endif
 | 
			
		||||
          #if HAS_Z_AXIS
 | 
			
		||||
            case Z_AXIS: es = Z_ENDSTOP; break;
 | 
			
		||||
          #endif
 | 
			
		||||
          #if HAS_I_AXIS
 | 
			
		||||
            case I_AXIS: es = I_ENDSTOP; break;
 | 
			
		||||
          #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -2041,15 +2041,9 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 | 
			
		||||
      steps_dist_mm.b      = (db + dc) * mm_per_step[B_AXIS];
 | 
			
		||||
      steps_dist_mm.c      = CORESIGN(db - dc) * mm_per_step[C_AXIS];
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_I_AXIS
 | 
			
		||||
      steps_dist_mm.i = di * mm_per_step[I_AXIS];
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_J_AXIS
 | 
			
		||||
      steps_dist_mm.j = dj * mm_per_step[J_AXIS];
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_K_AXIS
 | 
			
		||||
      steps_dist_mm.k = dk * mm_per_step[K_AXIS];
 | 
			
		||||
    #endif
 | 
			
		||||
    TERN_(HAS_I_AXIS, steps_dist_mm.i = di * mm_per_step[I_AXIS]);
 | 
			
		||||
    TERN_(HAS_J_AXIS, steps_dist_mm.j = dj * mm_per_step[J_AXIS]);
 | 
			
		||||
    TERN_(HAS_K_AXIS, steps_dist_mm.k = dk * mm_per_step[K_AXIS]);
 | 
			
		||||
  #elif ENABLED(MARKFORGED_XY)
 | 
			
		||||
    steps_dist_mm.a      = (da - db) * mm_per_step[A_AXIS];
 | 
			
		||||
    steps_dist_mm.b      = db * mm_per_step[B_AXIS];
 | 
			
		||||
@@ -2197,15 +2191,9 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 | 
			
		||||
    );
 | 
			
		||||
  #endif
 | 
			
		||||
  #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
 | 
			
		||||
    #if HAS_I_AXIS
 | 
			
		||||
      if (block->steps.i) stepper.enable_axis(I_AXIS);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_J_AXIS
 | 
			
		||||
      if (block->steps.j) stepper.enable_axis(J_AXIS);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_K_AXIS
 | 
			
		||||
      if (block->steps.k) stepper.enable_axis(K_AXIS);
 | 
			
		||||
    #endif
 | 
			
		||||
    TERN_(HAS_I_AXIS, if (block->steps.i) stepper.enable_axis(I_AXIS));
 | 
			
		||||
    TERN_(HAS_J_AXIS, if (block->steps.j) stepper.enable_axis(J_AXIS));
 | 
			
		||||
    TERN_(HAS_K_AXIS, if (block->steps.k) stepper.enable_axis(K_AXIS));
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // Enable extruder(s)
 | 
			
		||||
@@ -2260,7 +2248,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 | 
			
		||||
 | 
			
		||||
  // Slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill
 | 
			
		||||
  #if EITHER(SLOWDOWN, HAS_WIRED_LCD) || defined(XY_FREQUENCY_LIMIT)
 | 
			
		||||
    // Segment time im micro seconds
 | 
			
		||||
    // Segment time in microseconds
 | 
			
		||||
    int32_t segment_time_us = LROUND(1000000.0f / inverse_secs);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
@@ -2419,7 +2407,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 | 
			
		||||
    accel = CEIL((esteps ? settings.acceleration : settings.travel_acceleration) * steps_per_mm);
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(LIN_ADVANCE)
 | 
			
		||||
 | 
			
		||||
      // Linear advance is currently not ready for HAS_I_AXIS
 | 
			
		||||
      #define MAX_E_JERK(N) TERN(HAS_LINEAR_E_JERK, max_e_jerk[E_INDEX_N(N)], max_jerk.e)
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
@@ -2939,7 +2927,7 @@ bool Planner::buffer_segment(const abce_pos_t &abce
 | 
			
		||||
      SERIAL_ECHOPGM_P(SP_Y_LBL, abce.b);
 | 
			
		||||
    #endif
 | 
			
		||||
    SERIAL_ECHOPGM(" (", position.y, "->", target.y);
 | 
			
		||||
    #if LINEAR_AXES >= ABC
 | 
			
		||||
    #if HAS_Z_AXIS
 | 
			
		||||
      #if ENABLED(DELTA)
 | 
			
		||||
        SERIAL_ECHOPGM(") C:", abce.c);
 | 
			
		||||
      #else
 | 
			
		||||
 
 | 
			
		||||
@@ -772,7 +772,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // On delta keep Z below clip height or do_blocking_move_to will abort
 | 
			
		||||
  xyz_pos_t npos = { rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z) };
 | 
			
		||||
  xyz_pos_t npos = LINEAR_AXIS_ARRAY(
 | 
			
		||||
    rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z),
 | 
			
		||||
    current_position.i, current_position.j, current_position.k
 | 
			
		||||
  );
 | 
			
		||||
  if (!can_reach(npos, probe_relative)) {
 | 
			
		||||
    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable");
 | 
			
		||||
    return NAN;
 | 
			
		||||
 
 | 
			
		||||
@@ -522,7 +522,7 @@ bool Stepper::disable_axis(const AxisEnum axis) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool Stepper::disable_extruder(E_TERN_(const uint8_t eindex)) {
 | 
			
		||||
  bool Stepper::disable_extruder(E_TERN_(const uint8_t eindex/*=0*/)) {
 | 
			
		||||
    IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr uint8_t eindex = 0);
 | 
			
		||||
    mark_axis_disabled(E_AXIS E_OPTARG(eindex));
 | 
			
		||||
    const bool can_disable = can_axis_disable(E_AXIS E_OPTARG(eindex));
 | 
			
		||||
@@ -1688,7 +1688,7 @@ void Stepper::pulse_phase_isr() {
 | 
			
		||||
    const bool is_page = IS_PAGE(current_block);
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(DIRECT_STEPPING)
 | 
			
		||||
      // TODO (DerAndere): Add support for HAS_I_AXIS
 | 
			
		||||
      // Direct stepping is currently not ready for HAS_I_AXIS
 | 
			
		||||
      if (is_page) {
 | 
			
		||||
 | 
			
		||||
        #if STEPPER_PAGE_FORMAT == SP_4x4D_128
 | 
			
		||||
@@ -1929,7 +1929,7 @@ uint32_t Stepper::block_phase_isr() {
 | 
			
		||||
    // If current block is finished, reset pointer and finalize state
 | 
			
		||||
    if (step_events_completed >= step_event_count) {
 | 
			
		||||
      #if ENABLED(DIRECT_STEPPING)
 | 
			
		||||
        // TODO (DerAndere): Add support for HAS_I_AXIS
 | 
			
		||||
        // Direct stepping is currently not ready for HAS_I_AXIS
 | 
			
		||||
        #if STEPPER_PAGE_FORMAT == SP_4x4D_128
 | 
			
		||||
          #define PAGE_SEGMENT_UPDATE_POS(AXIS) \
 | 
			
		||||
            count_position[_AXIS(AXIS)] += page_step_state.bd[_AXIS(AXIS)] - 128 * 7;
 | 
			
		||||
@@ -3352,113 +3352,115 @@ void Stepper::report_positions() {
 | 
			
		||||
 | 
			
		||||
  void Stepper::microstep_init() {
 | 
			
		||||
    #if HAS_X_MS_PINS
 | 
			
		||||
      SET_OUTPUT(X_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(X_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(X_MS1_PIN); SET_OUTPUT(X_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(X_MS3)
 | 
			
		||||
        SET_OUTPUT(X_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_X2_MS_PINS
 | 
			
		||||
      SET_OUTPUT(X2_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(X2_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(X2_MS1_PIN); SET_OUTPUT(X2_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(X2_MS3)
 | 
			
		||||
        SET_OUTPUT(X2_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Y_MS_PINS
 | 
			
		||||
      SET_OUTPUT(Y_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(Y_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(Y_MS1_PIN); SET_OUTPUT(Y_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(Y_MS3)
 | 
			
		||||
        SET_OUTPUT(Y_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Y2_MS_PINS
 | 
			
		||||
      SET_OUTPUT(Y2_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(Y2_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(Y2_MS1_PIN); SET_OUTPUT(Y2_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(Y2_MS3)
 | 
			
		||||
        SET_OUTPUT(Y2_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Z_MS_PINS
 | 
			
		||||
      SET_OUTPUT(Z_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(Z_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(Z_MS1_PIN); SET_OUTPUT(Z_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(Z_MS3)
 | 
			
		||||
        SET_OUTPUT(Z_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Z2_MS_PINS
 | 
			
		||||
      SET_OUTPUT(Z2_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(Z2_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(Z2_MS1_PIN); SET_OUTPUT(Z2_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(Z2_MS3)
 | 
			
		||||
        SET_OUTPUT(Z2_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Z3_MS_PINS
 | 
			
		||||
      SET_OUTPUT(Z3_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(Z3_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(Z3_MS1_PIN); SET_OUTPUT(Z3_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(Z3_MS3)
 | 
			
		||||
        SET_OUTPUT(Z3_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_Z4_MS_PINS
 | 
			
		||||
      SET_OUTPUT(Z4_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(Z4_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(Z4_MS1_PIN); SET_OUTPUT(Z4_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(Z4_MS3)
 | 
			
		||||
        SET_OUTPUT(Z4_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_I_MS_PINS
 | 
			
		||||
      SET_OUTPUT(I_MS1_PIN); SET_OUTPUT(I_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(I_MS3)
 | 
			
		||||
        SET_OUTPUT(I_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_J_MS_PINS
 | 
			
		||||
      SET_OUTPUT(J_MS1_PIN); SET_OUTPUT(J_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(J_MS3)
 | 
			
		||||
        SET_OUTPUT(J_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_K_MS_PINS
 | 
			
		||||
      SET_OUTPUT(K_MS1_PIN); SET_OUTPUT(K_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(K_MS3)
 | 
			
		||||
        SET_OUTPUT(K_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E0_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E0_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E0_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E0_MS1_PIN); SET_OUTPUT(E0_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E0_MS3)
 | 
			
		||||
        SET_OUTPUT(E0_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E1_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E1_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E1_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E1_MS1_PIN); SET_OUTPUT(E1_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E1_MS3)
 | 
			
		||||
        SET_OUTPUT(E1_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E2_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E2_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E2_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E2_MS1_PIN); SET_OUTPUT(E2_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E2_MS3)
 | 
			
		||||
        SET_OUTPUT(E2_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E3_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E3_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E3_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E3_MS1_PIN); SET_OUTPUT(E3_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E3_MS3)
 | 
			
		||||
        SET_OUTPUT(E3_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E4_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E4_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E4_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E4_MS1_PIN); SET_OUTPUT(E4_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E4_MS3)
 | 
			
		||||
        SET_OUTPUT(E4_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E5_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E5_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E5_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E5_MS1_PIN); SET_OUTPUT(E5_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E5_MS3)
 | 
			
		||||
        SET_OUTPUT(E5_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E6_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E6_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E6_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E6_MS1_PIN); SET_OUTPUT(E6_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E6_MS3)
 | 
			
		||||
        SET_OUTPUT(E6_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
    #endif
 | 
			
		||||
    #if HAS_E7_MS_PINS
 | 
			
		||||
      SET_OUTPUT(E7_MS1_PIN);
 | 
			
		||||
      SET_OUTPUT(E7_MS2_PIN);
 | 
			
		||||
      SET_OUTPUT(E7_MS1_PIN); SET_OUTPUT(E7_MS2_PIN);
 | 
			
		||||
      #if PIN_EXISTS(E7_MS3)
 | 
			
		||||
        SET_OUTPUT(E7_MS3_PIN);
 | 
			
		||||
      #endif
 | 
			
		||||
@@ -3531,13 +3533,13 @@ void Stepper::report_positions() {
 | 
			
		||||
      #if HAS_E7_MS_PINS
 | 
			
		||||
        case 10: WRITE(E7_MS1_PIN, ms1); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if HAS_I_MICROSTEPS
 | 
			
		||||
      #if HAS_I_MS_PINS
 | 
			
		||||
        case 11: WRITE(I_MS1_PIN, ms1); break
 | 
			
		||||
      #endif
 | 
			
		||||
      #if HAS_J_MICROSTEPS
 | 
			
		||||
      #if HAS_J_MS_PINS
 | 
			
		||||
        case 12: WRITE(J_MS1_PIN, ms1); break
 | 
			
		||||
      #endif
 | 
			
		||||
      #if HAS_K_MICROSTEPS
 | 
			
		||||
      #if HAS_K_MS_PINS
 | 
			
		||||
        case 13: WRITE(K_MS1_PIN, ms1); break
 | 
			
		||||
      #endif
 | 
			
		||||
    }
 | 
			
		||||
@@ -3602,13 +3604,13 @@ void Stepper::report_positions() {
 | 
			
		||||
      #if HAS_E7_MS_PINS
 | 
			
		||||
        case 10: WRITE(E7_MS2_PIN, ms2); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if HAS_I_M_PINS
 | 
			
		||||
      #if HAS_I_MS_PINS
 | 
			
		||||
        case 11: WRITE(I_MS2_PIN, ms2); break
 | 
			
		||||
      #endif
 | 
			
		||||
      #if HAS_J_M_PINS
 | 
			
		||||
      #if HAS_J_MS_PINS
 | 
			
		||||
        case 12: WRITE(J_MS2_PIN, ms2); break
 | 
			
		||||
      #endif
 | 
			
		||||
      #if HAS_K_M_PINS
 | 
			
		||||
      #if HAS_K_MS_PINS
 | 
			
		||||
        case 13: WRITE(K_MS2_PIN, ms2); break
 | 
			
		||||
      #endif
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -320,7 +320,6 @@ class Stepper {
 | 
			
		||||
        #ifndef MOTOR_CURRENT_PWM_FREQUENCY
 | 
			
		||||
          #define MOTOR_CURRENT_PWM_FREQUENCY 31400
 | 
			
		||||
        #endif
 | 
			
		||||
 | 
			
		||||
        #define MOTOR_CURRENT_COUNT LINEAR_AXES
 | 
			
		||||
      #elif HAS_MOTOR_CURRENT_SPI
 | 
			
		||||
        static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
 | 
			
		||||
 
 | 
			
		||||
@@ -1601,6 +1601,24 @@
 | 
			
		||||
#if PIN_EXISTS(Z4_SERIAL_RX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, Z4_SERIAL_RX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(I_SERIAL_TX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, I_SERIAL_TX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(I_SERIAL_RX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, I_SERIAL_RX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(J_SERIAL_TX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, J_SERIAL_TX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(J_SERIAL_RX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, J_SERIAL_RX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(K_SERIAL_TX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, K_SERIAL_TX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(K_SERIAL_RX)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, K_SERIAL_RX_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
#if PIN_EXISTS(E0_DIAG)
 | 
			
		||||
  REPORT_NAME_DIGITAL(__LINE__, E0_DIAG_PIN)
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -546,6 +546,7 @@
 | 
			
		||||
  #undef K_MAX_PIN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Filament Sensor first pin alias
 | 
			
		||||
#if HAS_FILAMENT_SENSOR
 | 
			
		||||
  #define FIL_RUNOUT1_PIN FIL_RUNOUT_PIN  // Filament Sensor first pin alias
 | 
			
		||||
#else
 | 
			
		||||
@@ -598,12 +599,13 @@
 | 
			
		||||
  #define X2_E_INDEX E_STEPPERS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The X2 axis, if any, should be the next open extruder port
 | 
			
		||||
#if HAS_X2_STEPPER && !defined(X2_DIAG_PIN) && !defined(X2_STEP_PIN) && !PIN_EXISTS(X2_CS_PIN)
 | 
			
		||||
  #define Y2_E_INDEX INCREMENT(X2_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define Y2_E_INDEX X2_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The X2 axis, if any, should be the next open extruder port
 | 
			
		||||
#if HAS_X2_STEPPER
 | 
			
		||||
  #ifndef X2_STEP_PIN
 | 
			
		||||
    #define X2_STEP_PIN   _EPIN(X2_E_INDEX, STEP)
 | 
			
		||||
@@ -686,12 +688,13 @@
 | 
			
		||||
  #define X2_MS3_PIN -1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Y2 axis, if any, should be the next open extruder port
 | 
			
		||||
#if ENABLED(Y_DUAL_STEPPER_DRIVERS) && !defined(Y2_DIAG_PIN) && !defined(Y2_STEP_PIN) && !PIN_EXISTS(Y2_CS_PIN)
 | 
			
		||||
  #define Z2_E_INDEX INCREMENT(Y2_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define Z2_E_INDEX Y2_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Y2 axis, if any, should be the next open extruder port
 | 
			
		||||
#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
 | 
			
		||||
  #ifndef Y2_STEP_PIN
 | 
			
		||||
    #define Y2_STEP_PIN   _EPIN(Y2_E_INDEX, STEP)
 | 
			
		||||
@@ -771,12 +774,13 @@
 | 
			
		||||
  #define Y2_MS3_PIN -1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Z2 axis, if any, should be the next open extruder port
 | 
			
		||||
#if NUM_Z_STEPPER_DRIVERS >= 2 && !defined(Z2_DIAG_PIN) && !defined(Z2_STEP_PIN) && !PIN_EXISTS(Z2_CS_PIN)
 | 
			
		||||
  #define Z3_E_INDEX INCREMENT(Z2_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define Z3_E_INDEX Z2_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Z2 axis, if any, should be the next open extruder port
 | 
			
		||||
#if NUM_Z_STEPPER_DRIVERS >= 2
 | 
			
		||||
  #ifndef Z2_STEP_PIN
 | 
			
		||||
    #define Z2_STEP_PIN   _EPIN(Z2_E_INDEX, STEP)
 | 
			
		||||
@@ -856,12 +860,13 @@
 | 
			
		||||
  #define Z2_MS3_PIN -1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Z3 axis, if any, should be the next open extruder port
 | 
			
		||||
#if NUM_Z_STEPPER_DRIVERS >= 3 && !defined(Z3_DIAG_PIN) && !defined(Z3_STEP_PIN) && !PIN_EXISTS(Z3_CS_PIN)
 | 
			
		||||
  #define Z4_E_INDEX INCREMENT(Z3_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define Z4_E_INDEX Z3_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Z3 axis, if any, should be the next open extruder port
 | 
			
		||||
#if NUM_Z_STEPPER_DRIVERS >= 3
 | 
			
		||||
  #ifndef Z3_STEP_PIN
 | 
			
		||||
    #define Z3_STEP_PIN   _EPIN(Z3_E_INDEX, STEP)
 | 
			
		||||
@@ -941,12 +946,13 @@
 | 
			
		||||
  #define Z3_MS3_PIN -1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Z4 axis, if any, should be the next open extruder port
 | 
			
		||||
#if NUM_Z_STEPPER_DRIVERS >= 4 && !defined(Z4_DIAG_PIN) && !defined(Z4_STEP_PIN) && !PIN_EXISTS(Z4_CS_PIN)
 | 
			
		||||
  #define I_E_INDEX INCREMENT(Z4_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define I_E_INDEX Z4_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The Z4 axis, if any, should be the next open extruder port
 | 
			
		||||
#if NUM_Z_STEPPER_DRIVERS >= 4
 | 
			
		||||
  #ifndef Z4_STEP_PIN
 | 
			
		||||
    #define Z4_STEP_PIN   _EPIN(Z4_E_INDEX, STEP)
 | 
			
		||||
@@ -1026,12 +1032,13 @@
 | 
			
		||||
  #define Z4_MS3_PIN -1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The I axis, if any, should be the next open extruder port
 | 
			
		||||
#if HAS_I_AXIS && !defined(I_DIAG_PIN) && !defined(I_STEP_PIN) && !PIN_EXISTS(I_CS_PIN)
 | 
			
		||||
  #define J_E_INDEX INCREMENT(I_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define J_E_INDEX I_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The I axis, if any, should be the next open extruder port
 | 
			
		||||
#if HAS_I_AXIS
 | 
			
		||||
  #ifndef I_STEP_PIN
 | 
			
		||||
    #define I_STEP_PIN   _EPIN(I_E_INDEX, STEP)
 | 
			
		||||
@@ -1111,12 +1118,13 @@
 | 
			
		||||
  #define I_MS3_PIN -1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The J axis, if any, should be the next open extruder port
 | 
			
		||||
#if HAS_J_AXIS && !defined(J_DIAG_PIN) && !defined(J_STEP_PIN) && !PIN_EXISTS(J_CS_PIN)
 | 
			
		||||
  #define K_E_INDEX INCREMENT(J_E_INDEX)
 | 
			
		||||
#else
 | 
			
		||||
  #define K_E_INDEX J_E_INDEX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The J axis, if any, should be the next open extruder port
 | 
			
		||||
#if HAS_J_AXIS
 | 
			
		||||
  #ifndef J_STEP_PIN
 | 
			
		||||
    #define J_STEP_PIN   _EPIN(J_E_INDEX, STEP)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user