From 50889c0f94778c378357bcc4d4a966fa869bc5c1 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Thu, 30 Jan 2020 03:24:23 -0600
Subject: [PATCH] Move L64XX index_to_axis to progmem (#16697)

---
 Marlin/src/MarlinCore.cpp                |  32 +-
 Marlin/src/feature/babystep.cpp          |   2 +-
 Marlin/src/feature/prusa_MMU2/mmu2.cpp   |  16 +-
 Marlin/src/gcode/calibrate/G33.cpp       |   4 +-
 Marlin/src/gcode/control/M17_M18_M84.cpp |  12 +-
 Marlin/src/libs/L64XX/L64XX_Marlin.cpp   | 102 ++--
 Marlin/src/libs/L64XX/L64XX_Marlin.h     |   6 +-
 Marlin/src/module/planner.cpp            |  40 +-
 Marlin/src/module/probe.cpp              |   2 +-
 Marlin/src/module/stepper.cpp            |  16 +-
 Marlin/src/module/stepper/L64xx.h        |  50 ++
 Marlin/src/module/stepper/indirection.h  | 662 +++++++++++++----------
 12 files changed, 539 insertions(+), 405 deletions(-)

diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp
index 7ec6ffb488..6d78190218 100644
--- a/Marlin/src/MarlinCore.cpp
+++ b/Marlin/src/MarlinCore.cpp
@@ -291,7 +291,7 @@ void quickstop_stepper() {
 }
 
 void enable_e_steppers() {
-  #define _ENA_E(N) enable_E##N();
+  #define _ENA_E(N) ENABLE_AXIS_E##N();
   REPEAT(E_STEPPERS, _ENA_E)
 }
 
@@ -299,28 +299,28 @@ void enable_all_steppers() {
   #if ENABLED(AUTO_POWER_CONTROL)
     powerManager.power_on();
   #endif
-  enable_X();
-  enable_Y();
-  enable_Z();
+  ENABLE_AXIS_X();
+  ENABLE_AXIS_Y();
+  ENABLE_AXIS_Z();
   enable_e_steppers();
 }
 
 void disable_e_steppers() {
-  #define _DIS_E(N) disable_E##N();
+  #define _DIS_E(N) DISABLE_AXIS_E##N();
   REPEAT(E_STEPPERS, _DIS_E)
 }
 
 void disable_e_stepper(const uint8_t e) {
-  #define _CASE_DIS_E(N) case N: disable_E##N(); break;
+  #define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break;
   switch (e) {
     REPEAT(EXTRUDERS, _CASE_DIS_E)
   }
 }
 
 void disable_all_steppers() {
-  disable_X();
-  disable_Y();
-  disable_Z();
+  DISABLE_AXIS_X();
+  DISABLE_AXIS_Y();
+  DISABLE_AXIS_Z();
   disable_e_steppers();
 }
 
@@ -461,13 +461,13 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) {
       if (!already_shutdown_steppers) {
         already_shutdown_steppers = true;  // L6470 SPI will consume 99% of free time without this
         #if ENABLED(DISABLE_INACTIVE_X)
-          disable_X();
+          DISABLE_AXIS_X();
         #endif
         #if ENABLED(DISABLE_INACTIVE_Y)
-          disable_Y();
+          DISABLE_AXIS_Y();
         #endif
         #if ENABLED(DISABLE_INACTIVE_Z)
-          disable_Z();
+          DISABLE_AXIS_Z();
         #endif
         #if ENABLED(DISABLE_INACTIVE_E)
           disable_e_steppers();
@@ -542,11 +542,11 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) {
       #if ENABLED(SWITCHING_EXTRUDER)
         bool oldstatus;
         switch (active_extruder) {
-          default: oldstatus = E0_ENABLE_READ(); enable_E0(); break;
+          default: oldstatus = E0_ENABLE_READ(); ENABLE_AXIS_E0(); break;
           #if E_STEPPERS > 1
-            case 2: case 3: oldstatus = E1_ENABLE_READ(); enable_E1(); break;
+            case 2: case 3: oldstatus = E1_ENABLE_READ(); ENABLE_AXIS_E1(); break;
             #if E_STEPPERS > 2
-              case 4: case 5: oldstatus = E2_ENABLE_READ(); enable_E2(); break;
+              case 4: case 5: oldstatus = E2_ENABLE_READ(); ENABLE_AXIS_E2(); break;
             #endif // E_STEPPERS > 2
           #endif // E_STEPPERS > 1
         }
@@ -554,7 +554,7 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) {
         bool oldstatus;
         switch (active_extruder) {
           default:
-          #define _CASE_EN(N) case N: oldstatus = E##N##_ENABLE_READ(); enable_E##N(); break;
+          #define _CASE_EN(N) case N: oldstatus = E##N##_ENABLE_READ(); ENABLE_AXIS_E##N(); break;
           REPEAT(E_STEPPERS, _CASE_EN);
         }
       #endif
diff --git a/Marlin/src/feature/babystep.cpp b/Marlin/src/feature/babystep.cpp
index 510950095f..0b08f8ae41 100644
--- a/Marlin/src/feature/babystep.cpp
+++ b/Marlin/src/feature/babystep.cpp
@@ -78,7 +78,7 @@ void Babystep::add_steps(const AxisEnum axis, const int16_t distance) {
   #endif
 
   #if ENABLED(BABYSTEP_ALWAYS_AVAILABLE)
-    #define BSA_ENABLE(AXIS) do{ switch (AXIS) { case X_AXIS: enable_X(); break; case Y_AXIS: enable_Y(); break; case Z_AXIS: enable_Z(); break; default: break; } }while(0)
+    #define BSA_ENABLE(AXIS) do{ switch (AXIS) { case X_AXIS: ENABLE_AXIS_X(); break; case Y_AXIS: ENABLE_AXIS_Y(); break; case Z_AXIS: ENABLE_AXIS_Z(); break; default: break; } }while(0)
   #else
     #define BSA_ENABLE(AXIS) NOOP
   #endif
diff --git a/Marlin/src/feature/prusa_MMU2/mmu2.cpp b/Marlin/src/feature/prusa_MMU2/mmu2.cpp
index 0e25c86708..d96cbf9720 100644
--- a/Marlin/src/feature/prusa_MMU2/mmu2.cpp
+++ b/Marlin/src/feature/prusa_MMU2/mmu2.cpp
@@ -448,7 +448,7 @@ void MMU2::tool_change(uint8_t index) {
 
   if (index != extruder) {
 
-    disable_E0();
+    DISABLE_AXIS_E0();
     ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
 
     command(MMU_CMD_T0 + index);
@@ -459,7 +459,7 @@ void MMU2::tool_change(uint8_t index) {
     extruder = index; //filament change is finished
     active_extruder = 0;
 
-    enable_E0();
+    ENABLE_AXIS_E0();
 
     SERIAL_ECHO_START();
     SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(extruder));
@@ -497,13 +497,13 @@ void MMU2::tool_change(const char* special) {
       case 'x': {
         planner.synchronize();
         uint8_t index = mmu2_choose_filament();
-        disable_E0();
+        DISABLE_AXIS_E0();
         command(MMU_CMD_T0 + index);
         manage_response(true, true);
         command(MMU_CMD_C0);
         mmu_loop();
 
-        enable_E0();
+        ENABLE_AXIS_E0();
         extruder = index;
         active_extruder = 0;
       } break;
@@ -697,7 +697,7 @@ void MMU2::filament_runout() {
 
     LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT);
 
-    enable_E0();
+    ENABLE_AXIS_E0();
     current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED;
     line_to_current_position(2500 / 60);
     planner.synchronize();
@@ -731,7 +731,7 @@ void MMU2::filament_runout() {
 
     BUZZ(200, 404);
 
-    disable_E0();
+    DISABLE_AXIS_E0();
 
     return true;
   }
@@ -776,7 +776,7 @@ void MMU2::filament_runout() {
   void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) {
 
     planner.synchronize();
-    enable_E0();
+    ENABLE_AXIS_E0();
 
     const E_Step* step = sequence;
 
@@ -794,7 +794,7 @@ void MMU2::filament_runout() {
       step++;
     }
 
-    disable_E0();
+    DISABLE_AXIS_E0();
   }
 
 #endif // HAS_LCD_MENU && MMU2_MENUS
diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp
index 1931d226af..2ce45359d3 100644
--- a/Marlin/src/gcode/calibrate/G33.cpp
+++ b/Marlin/src/gcode/calibrate/G33.cpp
@@ -439,7 +439,6 @@ void GcodeSuite::G33() {
              _opposite_results    = (_4p_calibration && !towers_set) || probe_points >= 3,
              _endstop_results     = probe_points != 1 && probe_points != -1 && probe_points != 0,
              _angle_results       = probe_points >= 3 && towers_set;
-  static const char save_message[] PROGMEM = "Save with M500 and/or copy to Configuration.h";
   int8_t iterations = 0;
   float test_precision,
         zero_std_dev = (verbose_level ? 999.0f : 0.0f), // 0.0 in dry-run mode : forced end
@@ -625,8 +624,7 @@ void GcodeSuite::G33() {
           sprintf_P(&mess[15], PSTR("%03i.x"), (int)LROUND(zero_std_dev_min));
         ui.set_status(mess);
         print_calibration_settings(_endstop_results, _angle_results);
-        serialprintPGM(save_message);
-        SERIAL_EOL();
+        SERIAL_ECHOLNPGM("Save with M500 and/or copy to Configuration.h");
       }
       else { // !end iterations
         char mess[15];
diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp
index 081ca18d89..4908a64ecb 100644
--- a/Marlin/src/gcode/control/M17_M18_M84.cpp
+++ b/Marlin/src/gcode/control/M17_M18_M84.cpp
@@ -34,9 +34,9 @@
  */
 void GcodeSuite::M17() {
   if (parser.seen("XYZE")) {
-    if (parser.seen('X')) enable_X();
-    if (parser.seen('Y')) enable_Y();
-    if (parser.seen('Z')) enable_Z();
+    if (parser.seen('X')) ENABLE_AXIS_X();
+    if (parser.seen('Y')) ENABLE_AXIS_Y();
+    if (parser.seen('Z')) ENABLE_AXIS_Z();
     #if HAS_E_STEPPER_ENABLE
       if (parser.seen('E')) enable_e_steppers();
     #endif
@@ -57,9 +57,9 @@ void GcodeSuite::M18_M84() {
   else {
     if (parser.seen("XYZE")) {
       planner.synchronize();
-      if (parser.seen('X')) disable_X();
-      if (parser.seen('Y')) disable_Y();
-      if (parser.seen('Z')) disable_Z();
+      if (parser.seen('X')) DISABLE_AXIS_X();
+      if (parser.seen('Y')) DISABLE_AXIS_Y();
+      if (parser.seen('Z')) DISABLE_AXIS_Z();
       #if HAS_E_STEPPER_ENABLE
         if (parser.seen('E')) disable_e_steppers();
       #endif
diff --git a/Marlin/src/libs/L64XX/L64XX_Marlin.cpp b/Marlin/src/libs/L64XX/L64XX_Marlin.cpp
index cfa28586b6..645823a126 100644
--- a/Marlin/src/libs/L64XX/L64XX_Marlin.cpp
+++ b/Marlin/src/libs/L64XX/L64XX_Marlin.cpp
@@ -39,39 +39,40 @@ L64XX_Marlin L64xxManager;
 
 void echo_yes_no(const bool yes) { serialprintPGM(yes ? PSTR(" YES") : PSTR(" NO ")); }
 
-char L64XX_Marlin::index_to_axis[MAX_L64XX][3] = { "X ", "Y ", "Z ", "X2", "Y2", "Z2", "Z3", "Z4", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7" };
+static const char str_X[] PROGMEM = "X ",  str_Y[] PROGMEM = "Y ",  str_Z[] PROGMEM = "Z ",
+                 str_X2[] PROGMEM = "X2", str_Y2[] PROGMEM = "Y2",
+                 str_Z2[] PROGMEM = "Z2", str_Z3[] PROGMEM = "Z3", str_Z4[] PROGMEM = "Z4",
+                 str_E0[] PROGMEM = "E0", str_E1[] PROGMEM = "E1",
+                 str_E2[] PROGMEM = "E2", str_E3[] PROGMEM = "E3",
+                 str_E4[] PROGMEM = "E4", str_E5[] PROGMEM = "E5",
+                 str_E6[] PROGMEM = "E6", str_E7[] PROGMEM = "E7"
+                 ;
+
+PGM_P const L64XX_Marlin::index_to_axis[] PROGMEM = {
+  str_X, str_Y, str_Z, str_X2, str_Y2, str_Z2, str_Z3, str_Z4,
+  str_E0, str_E1, str_E2, str_E3, str_E4, str_E5, str_E6, str_E7
+};
 
 #define DEBUG_OUT ENABLED(L6470_CHITCHAT)
 #include "../../core/debug_out.h"
 
 uint8_t L64XX_Marlin::dir_commands[MAX_L64XX];  // array to hold direction command for each driver
 
-uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = { (INVERT_X_DIR),                         //  0 X
-                                                  (INVERT_Y_DIR),                         //  1 Y
-                                                  (INVERT_Z_DIR),                         //  2 Z
-                                                  #if ENABLED(X_DUAL_STEPPER_DRIVERS)     //  3 X2
-                                                    (INVERT_X_DIR) ^ (INVERT_X2_VS_X_DIR),
-                                                  #else
-                                                    (INVERT_X_DIR),
-                                                  #endif
-                                                  #if ENABLED(Y_DUAL_STEPPER_DRIVERS)     //  4 Y2
-                                                    (INVERT_Y_DIR) ^ (INVERT_Y2_VS_Y_DIR),
-                                                  #else
-                                                    (INVERT_Y_DIR),
-                                                  #endif
-                                                  (INVERT_Z_DIR),                         //  5 Z2
-                                                  (INVERT_Z_DIR),                         //  6 Z3
-                                                  (INVERT_Z_DIR),                         //  7 Z4
+const uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = {
+  INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR
+  , (INVERT_X_DIR)                            // X2
+    #if ENABLED(X_DUAL_STEPPER_DRIVERS)
+      ^ (INVERT_X2_VS_X_DIR)
+    #endif
+  , (INVERT_Y_DIR)                            // Y2
+    #if ENABLED(Y_DUAL_STEPPER_DRIVERS)
+      ^ (INVERT_Y2_VS_Y_DIR)
+    #endif
+  , INVERT_Z_DIR, INVERT_Z_DIR, INVERT_Z_DIR  // Z2,Z3,Z4
 
-                                                  (INVERT_E0_DIR),                        //  8 E0
-                                                  (INVERT_E1_DIR),                        //  9 E1
-                                                  (INVERT_E2_DIR),                        // 10 E2
-                                                  (INVERT_E3_DIR),                        // 11 E3
-                                                  (INVERT_E4_DIR),                        // 12 E4
-                                                  (INVERT_E5_DIR),                        // 13 E5
-                                                  (INVERT_E6_DIR),                        // 14 E6
-                                                  (INVERT_E7_DIR)                         // 15 E7
-                                                };
+  , INVERT_E0_DIR, INVERT_E1_DIR, INVERT_E2_DIR, INVERT_E3_DIR
+  , INVERT_E4_DIR, INVERT_E5_DIR, INVERT_E6_DIR, INVERT_E7_DIR
+};
 
 volatile uint8_t L64XX_Marlin::spi_abort = false;
 uint8_t L64XX_Marlin::spi_active = false;
@@ -379,35 +380,27 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
     found_displacement = true;
     displacement = _displacement;
     uint8_t axis_offset = parser.byteval('J');
-    axis_mon[0][0] = axis_codes[i];   // axis ASCII value (target character)
+    axis_mon[0][0] = axis_codes[i];         // Axis first character, one of XYZE
+    const bool single_or_e = axis_offset >= 2 || axis_mon[0][0] == 'E',
+               one_or_more = !single_or_e && axis_offset == 0;
     uint8_t driver_count_local = 0;         // Can't use "driver_count" directly as a subscript because it's passed by reference
-    if (axis_offset >= 2 || axis_mon[0][0] == 'E') {  // Single axis, E0, or E1
-      axis_mon[0][1] = axis_offset + '0';
-      for (j = 0; j < MAX_L64XX; j++) {       // See how many drivers on this axis
-        const char * const str = index_to_axis[j];
-        if (axis_mon[0][0] == str[0]) {
-          char * const mon = axis_mon[driver_count_local];
-          mon[0] = str[0];
-          mon[1] = str[1];
-          mon[2] = str[2];   // append end of string
-          axis_index[driver_count_local] = (L64XX_axis_t)j;        // set axis index
+    if (single_or_e)                        // Single axis, E0, or E1
+      axis_mon[0][1] = axis_offset + '0';   // Index given by 'J' parameter
+
+    if (single_or_e || one_or_more) {
+      for (j = 0; j < MAX_L64XX; j++) {     // Count up the drivers on this axis
+        PGM_P str = (PGM_P)pgm_read_ptr(&index_to_axis[j]); // Get a PGM_P from progmem
+        const char c = pgm_read_byte(str);                  // Get a char from progmem
+        if (axis_mon[0][0] == c) {          // For each stepper on this axis...
+          char *mon = axis_mon[driver_count_local];
+          *mon++ = c;                        // Copy the 3 letter axis name
+          *mon++ = pgm_read_byte(&str[1]);   //  to the axis_mon array
+          *mon   = pgm_read_byte(&str[2]);
+          axis_index[driver_count_local] = (L64XX_axis_t)j; // And store the L64XX axis index
           driver_count_local++;
         }
       }
-    }
-    else if (axis_offset == 0) {              // One or more axes
-      for (j = 0; j < MAX_L64XX; j++) {       // See how many drivers on this axis
-        const char * const str = index_to_axis[j];
-        if (axis_mon[0][0] == str[0]) {
-          char * const mon = axis_mon[driver_count_local];
-          mon[0] = str[0];
-          mon[1] = str[1];
-          mon[2] = str[2];   // append end of string
-          axis_index[driver_count_local] = (L64XX_axis_t)j;        // set axis index
-          driver_count_local++;
-        }
-      }
-      driver_count = driver_count_local;
+      if (one_or_more) driver_count = driver_count_local;
     }
     break; // only take first axis found
   }
@@ -494,8 +487,8 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
   for (uint8_t k = 0; k < driver_count; k++) {
     uint8_t not_found = true;
     for (j = 1; j <= L64XX::chain[0]; j++) {
-      const char * const ind_axis = index_to_axis[L64XX::chain[j]];
-      if (ind_axis[0] == axis_mon[k][0] && ind_axis[1] == axis_mon[k][1]) { // See if a L6470 driver
+      PGM_P const str = (PGM_P)pgm_read_ptr(&index_to_axis[L64XX::chain[j]]);
+      if (pgm_read_byte(&str[0]) == axis_mon[k][0] && pgm_read_byte(&str[1]) == axis_mon[k][1]) { // See if a L6470 driver
         not_found = false;
         break;
       }
@@ -724,7 +717,8 @@ void L64XX_Marlin::say_axis(const L64XX_axis_t axis, const uint8_t label/*=true*
   };
 
   void L64XX_Marlin::append_stepper_err(char* &p, const uint8_t stepper_index, const char * const err/*=nullptr*/) {
-    p += sprintf_P(p, PSTR("Stepper %c%c "), index_to_axis[stepper_index][0], index_to_axis[stepper_index][1]);
+    PGM_P const str = (PGM_P)pgm_read_ptr(&index_to_axis[stepper_index]);
+    p += sprintf_P(p, PSTR("Stepper %c%c "), pgm_read_byte(&str[0]), pgm_read_byte(&str[1]));
     if (err) p += sprintf_P(p, err);
   }
 
diff --git a/Marlin/src/libs/L64XX/L64XX_Marlin.h b/Marlin/src/libs/L64XX/L64XX_Marlin.h
index 9c233fdf03..08315fc68f 100644
--- a/Marlin/src/libs/L64XX/L64XX_Marlin.h
+++ b/Marlin/src/libs/L64XX/L64XX_Marlin.h
@@ -39,9 +39,10 @@ enum L64XX_axis_t : uint8_t { X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E
 
 class L64XX_Marlin : public L64XXHelper {
 public:
-  static char index_to_axis[MAX_L64XX][3];
+  static PGM_P const index_to_axis[MAX_L64XX];
+
+  static const uint8_t index_to_dir[MAX_L64XX];
 
-  static uint8_t index_to_dir[MAX_L64XX];
   static uint8_t dir_commands[MAX_L64XX];
 
   // Flags to guarantee graceful switch if stepper interrupts L6470 SPI transfer
@@ -69,7 +70,6 @@ public:
 
   static void transfer(uint8_t L6470_buf[], const uint8_t length);
 
-  //static char* index_to_axis(const uint8_t index);
   static void say_axis(const L64XX_axis_t axis, const uint8_t label=true);
   #if ENABLED(L6470_CHITCHAT)
     static void error_status_decode(
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 0552206315..351b089895 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1252,13 +1252,13 @@ void Planner::check_axes_activity() {
   // Disable inactive axes
   //
   #if ENABLED(DISABLE_X)
-    if (!axis_active.x) disable_X();
+    if (!axis_active.x) DISABLE_AXIS_X();
   #endif
   #if ENABLED(DISABLE_Y)
-    if (!axis_active.y) disable_Y();
+    if (!axis_active.y) DISABLE_AXIS_Y();
   #endif
   #if ENABLED(DISABLE_Z)
-    if (!axis_active.z) disable_Z();
+    if (!axis_active.z) DISABLE_AXIS_Z();
   #endif
   #if ENABLED(DISABLE_E)
     if (!axis_active.e) disable_e_steppers();
@@ -1905,29 +1905,29 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
   // Enable active axes
   #if CORE_IS_XY
     if (block->steps.a || block->steps.b) {
-      enable_X();
-      enable_Y();
+      ENABLE_AXIS_X();
+      ENABLE_AXIS_Y();
     }
     #if DISABLED(Z_LATE_ENABLE)
-      if (block->steps.z) enable_Z();
+      if (block->steps.z) ENABLE_AXIS_Z();
     #endif
   #elif CORE_IS_XZ
     if (block->steps.a || block->steps.c) {
-      enable_X();
-      enable_Z();
+      ENABLE_AXIS_X();
+      ENABLE_AXIS_Z();
     }
-    if (block->steps.y) enable_Y();
+    if (block->steps.y) ENABLE_AXIS_Y();
   #elif CORE_IS_YZ
     if (block->steps.b || block->steps.c) {
-      enable_Y();
-      enable_Z();
+      ENABLE_AXIS_Y();
+      ENABLE_AXIS_Z();
     }
-    if (block->steps.x) enable_X();
+    if (block->steps.x) ENABLE_AXIS_X();
   #else
-    if (block->steps.x) enable_X();
-    if (block->steps.y) enable_Y();
+    if (block->steps.x) ENABLE_AXIS_X();
+    if (block->steps.y) ENABLE_AXIS_Y();
     #if DISABLED(Z_LATE_ENABLE)
-      if (block->steps.z) enable_Z();
+      if (block->steps.z) ENABLE_AXIS_Z();
     #endif
   #endif
 
@@ -1945,27 +1945,27 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
 
         #if HAS_DUPLICATION_MODE
           if (extruder_duplication_enabled && extruder == 0) {
-            enable_E1();
+            ENABLE_AXIS_E1();
             g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2;
           }
         #endif
 
         #define ENABLE_ONE_E(N) do{ \
           if (extruder == N) { \
-            enable_E##N(); \
+            ENABLE_AXIS_E##N(); \
             g_uc_extruder_last_move[N] = (BLOCK_BUFFER_SIZE) * 2; \
           } \
           else if (!g_uc_extruder_last_move[N]) \
-            disable_E##N(); \
+            DISABLE_AXIS_E##N(); \
         }while(0);
 
       #else
 
-        #define ENABLE_ONE_E(N) enable_E##N();
+        #define ENABLE_ONE_E(N) ENABLE_AXIS_E##N();
 
       #endif
 
-      REPEAT(EXTRUDERS, ENABLE_ONE_E);
+      REPEAT(EXTRUDERS, ENABLE_ONE_E); // (ENABLE_ONE_E must end with semicolon)
     }
   #endif // EXTRUDERS
 
diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp
index 31c1128369..5710614e00 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -251,7 +251,7 @@ xyz_pos_t probe_offset; // Initialized by settings.load()
     #if ENABLED(PROBING_STEPPERS_OFF)
       disable_e_steppers();
       #if NONE(DELTA, HOME_AFTER_DEACTIVATE)
-        disable_X(); disable_Y();
+        DISABLE_AXIS_X(); DISABLE_AXIS_Y();
       #endif
     #endif
     if (p) safe_delay(
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index 6e4977984f..4e46ea56cd 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -1927,7 +1927,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
         // If delayed Z enable, enable it now. This option will severely interfere with
         // timing between pulses when chaining motion between blocks, and it could lead
         // to lost steps in both X and Y axis, so avoid using it unless strictly necessary!!
-        if (current_block->steps.z) enable_Z();
+        if (current_block->steps.z) ENABLE_AXIS_Z();
       #endif
 
       // Mark the time_nominal as not calculated yet
@@ -2215,12 +2215,12 @@ void Stepper::init() {
 
   #define _STEP_INIT(AXIS) AXIS ##_STEP_INIT()
   #define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
-  #define _DISABLE(AXIS) disable_## AXIS()
+  #define _DISABLE_AXIS(AXIS) DISABLE_AXIS_## AXIS()
 
   #define AXIS_INIT(AXIS, PIN) \
     _STEP_INIT(AXIS); \
     _WRITE_STEP(AXIS, _INVERT_STEP_PIN(PIN)); \
-    _DISABLE(AXIS)
+    _DISABLE_AXIS(AXIS)
 
   #define E_AXIS_INIT(NUM) AXIS_INIT(E## NUM, E)
 
@@ -2437,7 +2437,7 @@ void Stepper::report_positions() {
   #endif
   #define EXTRA_CYCLES_BABYSTEP (STEP_PULSE_CYCLES - (CYCLES_EATEN_BABYSTEP))
 
-  #define _ENABLE(AXIS) enable_## AXIS()
+  #define _ENABLE_AXIS(AXIS) ENABLE_AXIS_## AXIS()
   #define _READ_DIR(AXIS) AXIS ##_DIR_READ()
   #define _INVERT_DIR(AXIS) INVERT_## AXIS ##_DIR
   #define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true)
@@ -2460,7 +2460,7 @@ void Stepper::report_positions() {
 
   #define BABYSTEP_AXIS(AXIS, INVERT, DIR) {            \
       const uint8_t old_dir = _READ_DIR(AXIS);          \
-      _ENABLE(AXIS);                                    \
+      _ENABLE_AXIS(AXIS);                                    \
       DELAY_NS(MINIMUM_STEPPER_PRE_DIR_DELAY);              \
       _APPLY_DIR(AXIS, _INVERT_DIR(AXIS)^DIR^INVERT);   \
       DELAY_NS(MINIMUM_STEPPER_POST_DIR_DELAY);              \
@@ -2523,9 +2523,9 @@ void Stepper::report_positions() {
 
           const bool z_direction = direction ^ BABYSTEP_INVERT_Z;
 
-          enable_X();
-          enable_Y();
-          enable_Z();
+          ENABLE_AXIS_X();
+          ENABLE_AXIS_Y();
+          ENABLE_AXIS_Z();
 
           #if MINIMUM_STEPPER_PRE_DIR_DELAY > 0
             DELAY_NS(MINIMUM_STEPPER_PRE_DIR_DELAY);
diff --git a/Marlin/src/module/stepper/L64xx.h b/Marlin/src/module/stepper/L64xx.h
index 35b3d723de..919e966940 100644
--- a/Marlin/src/module/stepper/L64xx.h
+++ b/Marlin/src/module/stepper/L64xx.h
@@ -55,6 +55,9 @@
     #define X_DIR_INIT()        NOOP
     #define X_DIR_WRITE(STATE)  L64XX_DIR_WRITE(X, STATE)
     #define X_DIR_READ()        (stepper##X.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_X(L6470)
+      #define DISABLE_STEPPER_X() stepperX.free()
+    #endif
   #endif
 #endif
 
@@ -72,6 +75,9 @@
     #define Y_DIR_INIT()        NOOP
     #define Y_DIR_WRITE(STATE)  L64XX_DIR_WRITE(Y, STATE)
     #define Y_DIR_READ()        (stepper##Y.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_Y(L6470)
+      #define DISABLE_STEPPER_Y() stepperY.free()
+    #endif
   #endif
 #endif
 
@@ -89,6 +95,9 @@
     #define Z_DIR_INIT()        NOOP
     #define Z_DIR_WRITE(STATE)  L64XX_DIR_WRITE(Z, STATE)
     #define Z_DIR_READ()        (stepper##Z.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_Z(L6470)
+      #define DISABLE_STEPPER_Z() stepperZ.free()
+    #endif
   #endif
 #endif
 
@@ -109,6 +118,10 @@
   #endif
 #endif
 
+#if AXIS_DRIVER_TYPE_X2(L6470)
+  #define DISABLE_STEPPER_X2() stepperX2.free()
+#endif
+
 // Y2 Stepper
 #if HAS_Y2_ENABLE && AXIS_IS_L64XX(Y2)
   extern L64XX_CLASS(Y2)         stepperY2;
@@ -126,6 +139,10 @@
   #endif
 #endif
 
+#if AXIS_DRIVER_TYPE_Y2(L6470)
+  #define DISABLE_STEPPER_Y2() stepperY2.free()
+#endif
+
 // Z2 Stepper
 #if HAS_Z2_ENABLE && AXIS_IS_L64XX(Z2)
   extern L64XX_CLASS(Z2)         stepperZ2;
@@ -143,6 +160,10 @@
   #endif
 #endif
 
+#if AXIS_DRIVER_TYPE_Z2(L6470)
+  #define DISABLE_STEPPER_Z2() stepperZ2.free()
+#endif
+
 // Z3 Stepper
 #if HAS_Z3_ENABLE && AXIS_IS_L64XX(Z3)
   extern L64XX_CLASS(Z3)         stepperZ3;
@@ -160,6 +181,10 @@
   #endif
 #endif
 
+#if AXIS_DRIVER_TYPE_Z3(L6470)
+  #define DISABLE_STEPPER_Z3() stepperZ3.free()
+#endif
+
 // Z4 Stepper
 #if HAS_Z4_ENABLE && AXIS_IS_L64XX(Z4)
   extern L64XX_CLASS(Z4)         stepperZ4;
@@ -177,6 +202,10 @@
   #endif
 #endif
 
+#if AXIS_DRIVER_TYPE_Z4(L6470)
+  #define DISABLE_STEPPER_Z4() stepperZ4.free()
+#endif
+
 // E0 Stepper
 #if AXIS_IS_L64XX(E0)
   extern L64XX_CLASS(E0)         stepperE0;
@@ -191,6 +220,9 @@
     #define E0_DIR_INIT()        NOOP
     #define E0_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E0, STATE)
     #define E0_DIR_READ()        (stepper##E0.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E0(L6470)
+      #define DISABLE_STEPPER_E0() do{ stepperE0.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
 
@@ -208,6 +240,9 @@
     #define E1_DIR_INIT()        NOOP
     #define E1_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E1, STATE)
     #define E1_DIR_READ()        (stepper##E1.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E1(L6470)
+      #define DISABLE_STEPPER_E1() do{ stepperE1.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
 
@@ -225,6 +260,9 @@
     #define E2_DIR_INIT()        NOOP
     #define E2_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E2, STATE)
     #define E2_DIR_READ()        (stepper##E2.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E2(L6470)
+      #define DISABLE_STEPPER_E2() do{ stepperE2.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
 
@@ -259,6 +297,9 @@
     #define E4_DIR_INIT()        NOOP
     #define E4_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E4, STATE)
     #define E4_DIR_READ()        (stepper##E4.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E4(L6470)
+      #define DISABLE_STEPPER_E4() do{ stepperE4.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
 
@@ -276,6 +317,9 @@
     #define E5_DIR_INIT()        NOOP
     #define E5_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E5, STATE)
     #define E5_DIR_READ()        (stepper##E5.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E5(L6470)
+      #define DISABLE_STEPPER_E5() do{ stepperE5.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
 
@@ -293,6 +337,9 @@
     #define E6_DIR_INIT()        NOOP
     #define E6_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E6, STATE)
     #define E6_DIR_READ()        (stepper##E6.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E6(L6470)
+      #define DISABLE_STEPPER_E6() do{ stepperE6.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
 
@@ -310,5 +357,8 @@
     #define E7_DIR_INIT()        NOOP
     #define E7_DIR_WRITE(STATE)  L64XX_DIR_WRITE(E7, STATE)
     #define E7_DIR_READ()        (stepper##E7.getStatus() & STATUS_DIR);
+    #if AXIS_DRIVER_TYPE_E7(L6470)
+      #define DISABLE_STEPPER_E7() do{ stepperE7.free(); CBI(axis_known_position, E_AXIS); }while(0)
+    #endif
   #endif
 #endif
diff --git a/Marlin/src/module/stepper/indirection.h b/Marlin/src/module/stepper/indirection.h
index d05c7e3db3..55e44fbe04 100644
--- a/Marlin/src/module/stepper/indirection.h
+++ b/Marlin/src/module/stepper/indirection.h
@@ -594,320 +594,412 @@ void reset_stepper_drivers();    // Called by settings.load / settings.reset
 #endif
 
 //
-// X, Y, Z Stepper enable / disable
-//
-#if AXIS_DRIVER_TYPE_X(L6470)
-  extern L6470 stepperX;
-  #define X_enable()  NOOP
-  #define X_disable() stepperX.free()
-#elif HAS_X_ENABLE
-  #define X_enable()  X_ENABLE_WRITE( X_ENABLE_ON)
-  #define X_disable() X_ENABLE_WRITE(!X_ENABLE_ON)
-#else
-  #define X_enable()  NOOP
-  #define X_disable() NOOP
-#endif
-
-#if AXIS_DRIVER_TYPE_X2(L6470)
-  extern L6470 stepperX2;
-  #define X2_enable()  NOOP
-  #define X2_disable() stepperX2.free()
-#elif HAS_X2_ENABLE
-  #define X2_enable()  X2_ENABLE_WRITE( X_ENABLE_ON)
-  #define X2_disable() X2_ENABLE_WRITE(!X_ENABLE_ON)
-#else
-  #define X2_enable()  NOOP
-  #define X2_disable() NOOP
-#endif
-
-#define  enable_X() do{ X_enable(); X2_enable(); }while(0)
-#define disable_X() do{ X_disable(); X2_disable(); CBI(axis_known_position, X_AXIS); }while(0)
-
-#if AXIS_DRIVER_TYPE_Y(L6470)
-  extern L6470 stepperY;
-  #define Y_enable()  NOOP
-  #define Y_disable() stepperY.free()
-#elif HAS_Y_ENABLE
-  #define Y_enable()  Y_ENABLE_WRITE( Y_ENABLE_ON)
-  #define Y_disable() Y_ENABLE_WRITE(!Y_ENABLE_ON)
-#else
-  #define Y_enable()  NOOP
-  #define Y_disable() NOOP
-#endif
-
-#if AXIS_DRIVER_TYPE_Y2(L6470)
-  extern L6470 stepperY2;
-  #define Y2_enable()  NOOP
-  #define Y2_disable() stepperY2.free()
-#elif HAS_Y2_ENABLE
-  #define Y2_enable()  Y2_ENABLE_WRITE( Y_ENABLE_ON)
-  #define Y2_disable() Y2_ENABLE_WRITE(!Y_ENABLE_ON)
-#else
-  #define Y2_enable()  NOOP
-  #define Y2_disable() NOOP
-#endif
-
-#define  enable_Y() do{ Y_enable(); Y2_enable(); }while(0)
-#define disable_Y() do{ Y_disable(); Y2_disable(); CBI(axis_known_position, Y_AXIS); }while(0)
-
-#if AXIS_DRIVER_TYPE_Z(L6470)
-  extern L6470 stepperZ;
-  #define Z_enable()  NOOP
-  #define Z_disable() stepperZ.free()
-#elif HAS_Z_ENABLE
-  #define Z_enable()  Z_ENABLE_WRITE( Z_ENABLE_ON)
-  #define Z_disable() Z_ENABLE_WRITE(!Z_ENABLE_ON)
-#else
-  #define Z_enable()  NOOP
-  #define Z_disable() NOOP
-#endif
-
-#if AXIS_DRIVER_TYPE_Z2(L6470)
-  extern L6470 stepperZ2;
-  #define Z2_enable()  NOOP
-  #define Z2_disable() stepperZ2.free()
-#elif HAS_Z2_ENABLE
-  #define Z2_enable()  Z2_ENABLE_WRITE( Z_ENABLE_ON)
-  #define Z2_disable() Z2_ENABLE_WRITE(!Z_ENABLE_ON)
-#else
-  #define Z2_enable()  NOOP
-  #define Z2_disable() NOOP
-#endif
-
-#if AXIS_DRIVER_TYPE_Z3(L6470)
-  extern L6470 stepperZ3;
-  #define Z3_enable()  NOOP
-  #define Z3_disable() stepperZ3.free()
-#elif HAS_Z3_ENABLE
-  #define Z3_enable()  Z3_ENABLE_WRITE( Z_ENABLE_ON)
-  #define Z3_disable() Z3_ENABLE_WRITE(!Z_ENABLE_ON)
-#else
-  #define Z3_enable()  NOOP
-  #define Z3_disable() NOOP
-#endif
-
-#if AXIS_DRIVER_TYPE_Z4(L6470)
-  extern L6470 stepperZ4;
-  #define Z4_enable()  NOOP
-  #define Z4_disable() stepperZ4.free()
-#elif HAS_Z4_ENABLE
-  #define Z4_enable()  Z4_ENABLE_WRITE( Z_ENABLE_ON)
-  #define Z4_disable() Z4_ENABLE_WRITE(!Z_ENABLE_ON)
-#else
-  #define Z4_enable()  NOOP
-  #define Z4_disable() NOOP
-#endif
-
-#define  enable_Z() do{ Z_enable();  Z2_enable();  Z3_enable();  Z4_enable(); }while(0)
-#define disable_Z() do{ Z_disable(); Z2_disable(); Z3_disable(); Z4_disable(); CBI(axis_known_position, Z_AXIS); }while(0)
-
-//
-// Extruder Stepper enable / disable
+// Individual stepper enable / disable macros
 //
 
-// define the individual enables/disables
-#if AXIS_DRIVER_TYPE_E0(L6470)
-  extern L6470 stepperE0;
-  #define  E0_enable() NOOP
-  #define E0_disable() do{ stepperE0.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif HAS_E0_ENABLE
-  #define  E0_enable() E0_ENABLE_WRITE( E_ENABLE_ON)
-  #define E0_disable() E0_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E0_enable() NOOP
-  #define E0_disable() NOOP
+#ifndef ENABLE_STEPPER_X
+  #if HAS_X_ENABLE
+    #define  ENABLE_STEPPER_X() X_ENABLE_WRITE( X_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_X() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_X
+  #if HAS_X_ENABLE
+    #define DISABLE_STEPPER_X() X_ENABLE_WRITE(!X_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_X() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E1(L6470)
-  extern L6470 stepperE1;
-  #define  E1_enable() NOOP
-  #define E1_disable() do{ stepperE1.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 1 && HAS_E1_ENABLE
-  #define  E1_enable() E1_ENABLE_WRITE( E_ENABLE_ON)
-  #define E1_disable() E1_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E1_enable() NOOP
-  #define E1_disable() NOOP
+#ifndef ENABLE_STEPPER_X2
+  #if HAS_X2_ENABLE
+    #define  ENABLE_STEPPER_X2() X2_ENABLE_WRITE( X_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_X2() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_X2
+  #if HAS_X2_ENABLE
+    #define DISABLE_STEPPER_X2() X2_ENABLE_WRITE(!X_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_X2() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E2(L6470)
-  extern L6470 stepperE2;
-  #define  E2_enable() NOOP
-  #define E2_disable() do{ stepperE2.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 2 && HAS_E2_ENABLE
-  #define  E2_enable() E2_ENABLE_WRITE( E_ENABLE_ON)
-  #define E2_disable() E2_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E2_enable() NOOP
-  #define E2_disable() NOOP
+#ifndef ENABLE_STEPPER_Y
+  #if HAS_Y_ENABLE
+    #define  ENABLE_STEPPER_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_Y() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_Y
+  #if HAS_Y_ENABLE
+    #define DISABLE_STEPPER_Y() Y_ENABLE_WRITE(!Y_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_Y() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E3(L6470)
-  extern L6470 stepperE3;
-  #define  E3_enable() NOOP
-  #define E3_disable() do{ stepperE3.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 3 && HAS_E3_ENABLE
-  #define  E3_enable() E3_ENABLE_WRITE( E_ENABLE_ON)
-  #define E3_disable() E3_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E3_enable() NOOP
-  #define E3_disable() NOOP
+#ifndef ENABLE_STEPPER_Y2
+  #if HAS_Y2_ENABLE
+    #define  ENABLE_STEPPER_Y2() Y2_ENABLE_WRITE( Y_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_Y2() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_Y2
+  #if HAS_Y2_ENABLE
+    #define DISABLE_STEPPER_Y2() Y2_ENABLE_WRITE(!Y_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_Y2() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E4(L6470)
-  extern L6470 stepperE4;
-  #define  E4_enable() NOOP
-  #define E4_disable() do{ stepperE4.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 4 && HAS_E4_ENABLE
-  #define  E4_enable() E4_ENABLE_WRITE( E_ENABLE_ON)
-  #define E4_disable() E4_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E4_enable() NOOP
-  #define E4_disable() NOOP
+#ifndef ENABLE_STEPPER_Z
+  #if HAS_Z_ENABLE
+    #define  ENABLE_STEPPER_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_Z() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_Z
+  #if HAS_Z_ENABLE
+    #define DISABLE_STEPPER_Z() Z_ENABLE_WRITE(!Z_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_Z() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E5(L6470)
-  extern L6470 stepperE5;
-  #define  E5_enable() NOOP
-  #define E5_disable() do{ stepperE5.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 5 && HAS_E5_ENABLE
-  #define  E5_enable() E5_ENABLE_WRITE( E_ENABLE_ON)
-  #define E5_disable() E5_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E5_enable() NOOP
-  #define E5_disable() NOOP
+#ifndef ENABLE_STEPPER_Z2
+  #if HAS_Z2_ENABLE
+    #define  ENABLE_STEPPER_Z2() Z2_ENABLE_WRITE( Z_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_Z2() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_Z2
+  #if HAS_Z2_ENABLE
+    #define DISABLE_STEPPER_Z2() Z2_ENABLE_WRITE(!Z_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_Z2() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E6(L6470)
-  extern L6470 stepperE6;
-  #define  E6_enable() NOOP
-  #define E6_disable() do{ stepperE6.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 6 && HAS_E6_ENABLE
-  #define  E6_enable() E6_ENABLE_WRITE( E_ENABLE_ON)
-  #define E6_disable() E6_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E6_enable() NOOP
-  #define E6_disable() NOOP
+#ifndef ENABLE_STEPPER_Z3
+  #if HAS_Z3_ENABLE
+    #define  ENABLE_STEPPER_Z3() Z3_ENABLE_WRITE( Z_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_Z3() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_Z3
+  #if HAS_Z3_ENABLE
+    #define DISABLE_STEPPER_Z3() Z3_ENABLE_WRITE(!Z_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_Z3() NOOP
+  #endif
 #endif
 
-#if AXIS_DRIVER_TYPE_E7(L6470)
-  extern L6470 stepperE7;
-  #define  E7_enable() NOOP
-  #define E7_disable() do{ stepperE7.free(); CBI(axis_known_position, E_AXIS); }while(0)
-#elif E_STEPPERS > 7 && HAS_E7_ENABLE
-  #define  E7_enable() E7_ENABLE_WRITE( E_ENABLE_ON)
-  #define E7_disable() E7_ENABLE_WRITE(!E_ENABLE_ON)
-#else
-  #define  E7_enable() NOOP
-  #define E7_disable() NOOP
+#ifndef ENABLE_STEPPER_Z4
+  #if HAS_Z4_ENABLE
+    #define  ENABLE_STEPPER_Z4() Z4_ENABLE_WRITE( Z_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_Z4() NOOP
+  #endif
 #endif
+#ifndef DISABLE_STEPPER_Z4
+  #if HAS_Z4_ENABLE
+    #define DISABLE_STEPPER_Z4() Z4_ENABLE_WRITE(!Z_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_Z4() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E0
+  #if HAS_E0_ENABLE
+    #define  ENABLE_STEPPER_E0() E0_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E0() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E0
+  #if HAS_E0_ENABLE
+    #define DISABLE_STEPPER_E0() E0_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E0() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E1
+  #if E_STEPPERS > 1 && HAS_E1_ENABLE
+    #define  ENABLE_STEPPER_E1() E1_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E1() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E1
+  #if E_STEPPERS > 1 && HAS_E1_ENABLE
+    #define DISABLE_STEPPER_E1() E1_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E1() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E2
+  #if E_STEPPERS > 2 && HAS_E2_ENABLE
+    #define  ENABLE_STEPPER_E2() E2_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E2() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E2
+  #if E_STEPPERS > 2 && HAS_E2_ENABLE
+    #define DISABLE_STEPPER_E2() E2_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E2() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E3
+  #if E_STEPPERS > 3 && HAS_E3_ENABLE
+    #define  ENABLE_STEPPER_E3() E3_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E3() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E3
+  #if E_STEPPERS > 3 && HAS_E3_ENABLE
+    #define DISABLE_STEPPER_E3() E3_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E3() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E4
+  #if E_STEPPERS > 4 && HAS_E4_ENABLE
+    #define  ENABLE_STEPPER_E4() E4_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E4() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E4
+  #if E_STEPPERS > 4 && HAS_E4_ENABLE
+    #define DISABLE_STEPPER_E4() E4_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E4() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E5
+  #if E_STEPPERS > 5 && HAS_E5_ENABLE
+    #define  ENABLE_STEPPER_E5() E5_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E5() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E5
+  #if E_STEPPERS > 5 && HAS_E5_ENABLE
+    #define DISABLE_STEPPER_E5() E5_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E5() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E6
+  #if E_STEPPERS > 6 && HAS_E6_ENABLE
+    #define  ENABLE_STEPPER_E6() E6_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E6() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E6
+  #if E_STEPPERS > 6 && HAS_E6_ENABLE
+    #define DISABLE_STEPPER_E6() E6_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E6() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_STEPPER_E7
+  #if E_STEPPERS > 7 && HAS_E7_ENABLE
+    #define  ENABLE_STEPPER_E7() E7_ENABLE_WRITE( E_ENABLE_ON)
+  #else
+    #define  ENABLE_STEPPER_E7() NOOP
+  #endif
+#endif
+#ifndef DISABLE_STEPPER_E7
+  #if E_STEPPERS > 7 && HAS_E7_ENABLE
+    #define DISABLE_STEPPER_E7() E7_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define DISABLE_STEPPER_E7() NOOP
+  #endif
+#endif
+
+//
+// Axis steppers enable / disable macros
+//
+
+#define  ENABLE_AXIS_X() do{ ENABLE_STEPPER_X(); ENABLE_STEPPER_X2(); }while(0)
+#define DISABLE_AXIS_X() do{ DISABLE_STEPPER_X(); DISABLE_STEPPER_X2(); CBI(axis_known_position, X_AXIS); }while(0)
+
+#define  ENABLE_AXIS_Y() do{ ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); }while(0)
+#define DISABLE_AXIS_Y() do{ DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); CBI(axis_known_position, Y_AXIS); }while(0)
+
+#define  ENABLE_AXIS_Z() do{ ENABLE_STEPPER_Z();  ENABLE_STEPPER_Z2();  ENABLE_STEPPER_Z3();  ENABLE_STEPPER_Z4(); }while(0)
+#define DISABLE_AXIS_Z() do{ DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); CBI(axis_known_position, Z_AXIS); }while(0)
+
+//
+// Extruder steppers enable / disable macros
+//
 
 #if ENABLED(MIXING_EXTRUDER)
 
   /**
-   * Mixing steppers synchronize their enable (and direction) together
+   * Mixing steppers keep all their enable (and direction) states synchronized
    */
   #if MIXING_STEPPERS > 7
-    #define  enable_E0() { E0_enable();  E1_enable();  E2_enable();  E3_enable();  E4_enable();  E5_enable();  E6_enable();  E7_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); E4_disable(); E5_disable(); E6_disable(); E7_disable(); }
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1();  ENABLE_STEPPER_E2();  ENABLE_STEPPER_E3();  ENABLE_STEPPER_E4();  ENABLE_STEPPER_E5();  ENABLE_STEPPER_E6();  ENABLE_STEPPER_E7(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); DISABLE_STEPPER_E2(); DISABLE_STEPPER_E3(); DISABLE_STEPPER_E4(); DISABLE_STEPPER_E5(); DISABLE_STEPPER_E6(); DISABLE_STEPPER_E7(); }
   #elif MIXING_STEPPERS > 6
-    #define  enable_E0() { E0_enable();  E1_enable();  E2_enable();  E3_enable();  E4_enable();  E5_enable();  E6_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); E4_disable(); E5_disable(); E6_disable(); }
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1();  ENABLE_STEPPER_E2();  ENABLE_STEPPER_E3();  ENABLE_STEPPER_E4();  ENABLE_STEPPER_E5();  ENABLE_STEPPER_E6(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); DISABLE_STEPPER_E2(); DISABLE_STEPPER_E3(); DISABLE_STEPPER_E4(); DISABLE_STEPPER_E5(); DISABLE_STEPPER_E6(); }
   #elif MIXING_STEPPERS > 5
-    #define  enable_E0() { E0_enable();  E1_enable();  E2_enable();  E3_enable();  E4_enable();  E5_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); E4_disable(); E5_disable(); }
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1();  ENABLE_STEPPER_E2();  ENABLE_STEPPER_E3();  ENABLE_STEPPER_E4();  ENABLE_STEPPER_E5(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); DISABLE_STEPPER_E2(); DISABLE_STEPPER_E3(); DISABLE_STEPPER_E4(); DISABLE_STEPPER_E5(); }
   #elif MIXING_STEPPERS > 4
-    #define  enable_E0() { E0_enable();  E1_enable();  E2_enable();  E3_enable();  E4_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); E4_disable(); }
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1();  ENABLE_STEPPER_E2();  ENABLE_STEPPER_E3();  ENABLE_STEPPER_E4(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); DISABLE_STEPPER_E2(); DISABLE_STEPPER_E3(); DISABLE_STEPPER_E4(); }
   #elif MIXING_STEPPERS > 3
-    #define  enable_E0() { E0_enable();  E1_enable();  E2_enable();  E3_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); }
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1();  ENABLE_STEPPER_E2();  ENABLE_STEPPER_E3(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); DISABLE_STEPPER_E2(); DISABLE_STEPPER_E3(); }
   #elif MIXING_STEPPERS > 2
-    #define  enable_E0() { E0_enable();  E1_enable();  E2_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); E2_disable(); }
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1();  ENABLE_STEPPER_E2(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); DISABLE_STEPPER_E2(); }
   #else
-    #define  enable_E0() { E0_enable();  E1_enable(); }
-    #define disable_E0() { E0_disable(); E1_disable(); }
-  #endif
-  #define  enable_E1() NOOP
-  #define disable_E1() NOOP
-  #define  enable_E2() NOOP
-  #define disable_E2() NOOP
-  #define  enable_E3() NOOP
-  #define disable_E3() NOOP
-  #define  enable_E4() NOOP
-  #define disable_E4() NOOP
-  #define  enable_E5() NOOP
-  #define disable_E5() NOOP
-  #define  enable_E6() NOOP
-  #define disable_E6() NOOP
-  #define  enable_E7() NOOP
-  #define disable_E7() NOOP
-
-#else // !MIXING_EXTRUDER
-
-  #if HAS_E0_ENABLE
-    #define  enable_E0() E0_enable()
-    #define disable_E0() E0_disable()
-  #else
-    #define  enable_E0() NOOP
-    #define disable_E0() NOOP
-  #endif
-
-  #if E_STEPPERS > 1 && HAS_E1_ENABLE
-    #define  enable_E1() E1_enable()
-    #define disable_E1() E1_disable()
-  #else
-    #define  enable_E1() NOOP
-    #define disable_E1() NOOP
-  #endif
-
-  #if E_STEPPERS > 2 && HAS_E2_ENABLE
-    #define  enable_E2() E2_enable()
-    #define disable_E2() E2_disable()
-  #else
-    #define  enable_E2() NOOP
-    #define disable_E2() NOOP
-  #endif
-
-  #if E_STEPPERS > 3 && HAS_E3_ENABLE
-    #define  enable_E3() E3_enable()
-    #define disable_E3() E3_disable()
-  #else
-    #define  enable_E3() NOOP
-    #define disable_E3() NOOP
-  #endif
-
-  #if E_STEPPERS > 4 && HAS_E4_ENABLE
-    #define  enable_E4() E4_enable()
-    #define disable_E4() E4_disable()
-  #else
-    #define  enable_E4() NOOP
-    #define disable_E4() NOOP
-  #endif
-
-  #if E_STEPPERS > 5 && HAS_E5_ENABLE
-    #define  enable_E5() E5_enable()
-    #define disable_E5() E5_disable()
-  #else
-    #define  enable_E5() NOOP
-    #define disable_E5() NOOP
-  #endif
-
-  #if E_STEPPERS > 6 && HAS_E6_ENABLE
-    #define  enable_E6() E6_enable()
-    #define disable_E6() E6_disable()
-  #else
-    #define  enable_E6() NOOP
-    #define disable_E6() NOOP
-  #endif
-
-  #if E_STEPPERS > 7 && HAS_E7_ENABLE
-    #define  enable_E7() E7_enable()
-    #define disable_E7() E7_disable()
-  #else
-    #define  enable_E7() NOOP
-    #define disable_E7() NOOP
+    #define  ENABLE_AXIS_E0() { ENABLE_STEPPER_E0();  ENABLE_STEPPER_E1(); }
+    #define DISABLE_AXIS_E0() { DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); }
   #endif
 
 #endif // !MIXING_EXTRUDER
+
+#ifndef ENABLE_AXIS_E0
+  #if E_STEPPERS > 0 && HAS_E0_ENABLE
+    #define  ENABLE_AXIS_E0() ENABLE_STEPPER_E0()
+  #else
+    #define  ENABLE_AXIS_E0() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E0
+  #if E_STEPPERS > 0 && HAS_E0_DISABLE
+    #define DISABLE_AXIS_E0() DISABLE_STEPPER_E0()
+  #else
+    #define DISABLE_AXIS_E0() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E1
+  #if E_STEPPERS > 1 && HAS_E1_ENABLE
+    #define  ENABLE_AXIS_E1() ENABLE_STEPPER_E1()
+  #else
+    #define  ENABLE_AXIS_E1() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E1
+  #if E_STEPPERS > 1 && HAS_E1_DISABLE
+    #define DISABLE_AXIS_E1() DISABLE_STEPPER_E1()
+  #else
+    #define DISABLE_AXIS_E1() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E2
+  #if E_STEPPERS > 2 && HAS_E2_ENABLE
+    #define  ENABLE_AXIS_E2() ENABLE_STEPPER_E2()
+  #else
+    #define  ENABLE_AXIS_E2() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E2
+  #if E_STEPPERS > 2 && HAS_E2_DISABLE
+    #define DISABLE_AXIS_E2() DISABLE_STEPPER_E2()
+  #else
+    #define DISABLE_AXIS_E2() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E3
+  #if E_STEPPERS > 3 && HAS_E3_ENABLE
+    #define  ENABLE_AXIS_E3() ENABLE_STEPPER_E3()
+  #else
+    #define  ENABLE_AXIS_E3() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E3
+  #if E_STEPPERS > 3 && HAS_E3_DISABLE
+    #define DISABLE_AXIS_E3() DISABLE_STEPPER_E3()
+  #else
+    #define DISABLE_AXIS_E3() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E4
+  #if E_STEPPERS > 4 && HAS_E4_ENABLE
+    #define  ENABLE_AXIS_E4() ENABLE_STEPPER_E4()
+  #else
+    #define  ENABLE_AXIS_E4() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E4
+  #if E_STEPPERS > 4 && HAS_E4_DISABLE
+    #define DISABLE_AXIS_E4() DISABLE_STEPPER_E4()
+  #else
+    #define DISABLE_AXIS_E4() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E5
+  #if E_STEPPERS > 5 && HAS_E5_ENABLE
+    #define  ENABLE_AXIS_E5() ENABLE_STEPPER_E5()
+  #else
+    #define  ENABLE_AXIS_E5() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E5
+  #if E_STEPPERS > 5 && HAS_E5_DISABLE
+    #define DISABLE_AXIS_E5() DISABLE_STEPPER_E5()
+  #else
+    #define DISABLE_AXIS_E5() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E6
+  #if E_STEPPERS > 6 && HAS_E6_ENABLE
+    #define  ENABLE_AXIS_E6() ENABLE_STEPPER_E6()
+  #else
+    #define  ENABLE_AXIS_E6() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E6
+  #if E_STEPPERS > 6 && HAS_E6_DISABLE
+    #define DISABLE_AXIS_E6() DISABLE_STEPPER_E6()
+  #else
+    #define DISABLE_AXIS_E6() NOOP
+  #endif
+#endif
+
+#ifndef ENABLE_AXIS_E7
+  #if E_STEPPERS > 7 && HAS_E7_ENABLE
+    #define  ENABLE_AXIS_E7() ENABLE_STEPPER_E7()
+  #else
+    #define  ENABLE_AXIS_E7() NOOP
+  #endif
+#endif
+#ifndef DISABLE_AXIS_E7
+  #if E_STEPPERS > 7 && HAS_E7_DISABLE
+    #define DISABLE_AXIS_E7() DISABLE_STEPPER_E7()
+  #else
+    #define DISABLE_AXIS_E7() NOOP
+  #endif
+#endif