From d3c56a76e73f8e126f1cf579f552e671efa9005b Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Tue, 1 Jun 2021 20:23:37 -0500
Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Patches=20for=20Zero=20Ext?=
 =?UTF-8?q?ruders=20(with=20TMC)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Marlin/src/core/types.h                    |   4 +-
 Marlin/src/feature/tmc_util.cpp            |  88 +--
 Marlin/src/gcode/feature/L6470/M906.cpp    | 101 +--
 Marlin/src/gcode/feature/trinamic/M569.cpp |  99 +--
 Marlin/src/gcode/feature/trinamic/M906.cpp | 101 +--
 Marlin/src/inc/Conditionals_LCD.h          |   4 +
 Marlin/src/inc/SanityCheck.h               |   4 +
 Marlin/src/module/planner_bezier.cpp       |   8 +-
 Marlin/src/module/stepper.cpp              |   6 +-
 Marlin/src/pins/pins_postprocess.h         | 770 +++++++++++----------
 10 files changed, 618 insertions(+), 567 deletions(-)

diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h
index 41cb39f1630..abb709d7313 100644
--- a/Marlin/src/core/types.h
+++ b/Marlin/src/core/types.h
@@ -360,7 +360,7 @@ struct XYZval {
   FI void set(const XYval<T> pxy, const T pz)          { x = pxy.x; y = pxy.y; z = pz; }
   FI void set(const T (&arr)[XY])                      { x = arr[0]; y = arr[1]; }
   FI void set(const T (&arr)[LINEAR_AXES])             { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2]); }
-  #if LINEAR_AXES >= XYZ
+  #if HAS_Z_AXIS
     FI void set(LINEAR_AXIS_LIST(const T px, const T py, const T pz))
                                                        { LINEAR_AXIS_CODE(x = px, y = py, z = pz); }
   #endif
@@ -475,7 +475,7 @@ struct XYZEval {
   FI void set(const T px, const T py)                         { x = px;    y = py;    }
   FI void set(const XYval<T> pxy)                             { x = pxy.x; y = pxy.y; }
   FI void set(const XYZval<T> pxyz)                           { set(LINEAR_AXIS_LIST(pxyz.x, pxyz.y, pxyz.z)); }
-  #if LINEAR_AXES >= XYZ
+  #if HAS_Z_AXIS
     FI void set(LINEAR_AXIS_LIST(const T px, const T py, const T pz)) {
       LINEAR_AXIS_CODE(x = px, y = py, z = pz);
     }
diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp
index e244a33eee4..021317ea89d 100644
--- a/Marlin/src/feature/tmc_util.cpp
+++ b/Marlin/src/feature/tmc_util.cpp
@@ -770,16 +770,18 @@
       #endif
     }
 
-    if (print_y) {
-      #if AXIS_IS_TMC(Y)
-        tmc_status(stepperY, i);
-      #endif
-      #if AXIS_IS_TMC(Y2)
-        tmc_status(stepperY2, i);
-      #endif
-    }
+    #if LINEAR_AXES >= XY
+      if (print_y) {
+        #if AXIS_IS_TMC(Y)
+          tmc_status(stepperY, i);
+        #endif
+        #if AXIS_IS_TMC(Y2)
+          tmc_status(stepperY2, i);
+        #endif
+      }
+    #endif
 
-    if (print_z) {
+    if (TERN0(HAS_Z_AXIS, print_z)) {
       #if AXIS_IS_TMC(Z)
         tmc_status(stepperZ, i);
       #endif
@@ -794,7 +796,7 @@
       #endif
     }
 
-    if (print_e) {
+    if (TERN0(HAS_EXTRUDERS, print_e)) {
       #if AXIS_IS_TMC(E0)
         tmc_status(stepperE0, i);
       #endif
@@ -837,16 +839,18 @@
       #endif
     }
 
-    if (print_y) {
-      #if AXIS_IS_TMC(Y)
-        tmc_parse_drv_status(stepperY, i);
-      #endif
-      #if AXIS_IS_TMC(Y2)
-        tmc_parse_drv_status(stepperY2, i);
-      #endif
-    }
+    #if LINEAR_AXES >= XY
+      if (print_y) {
+        #if AXIS_IS_TMC(Y)
+          tmc_parse_drv_status(stepperY, i);
+        #endif
+        #if AXIS_IS_TMC(Y2)
+          tmc_parse_drv_status(stepperY2, i);
+        #endif
+      }
+    #endif
 
-    if (print_z) {
+    if (TERN0(HAS_Z_AXIS, print_z)) {
       #if AXIS_IS_TMC(Z)
         tmc_parse_drv_status(stepperZ, i);
       #endif
@@ -861,7 +865,7 @@
       #endif
     }
 
-    if (print_e) {
+    if (TERN0(HAS_EXTRUDERS, print_e)) {
       #if AXIS_IS_TMC(E0)
         tmc_parse_drv_status(stepperE0, i);
       #endif
@@ -1037,16 +1041,18 @@
       #endif
     }
 
-    if (print_y) {
-      #if AXIS_IS_TMC(Y)
-        tmc_get_registers(stepperY, i);
-      #endif
-      #if AXIS_IS_TMC(Y2)
-        tmc_get_registers(stepperY2, i);
-      #endif
-    }
+    #if LINEAR_AXES >= XY
+      if (print_y) {
+        #if AXIS_IS_TMC(Y)
+          tmc_get_registers(stepperY, i);
+        #endif
+        #if AXIS_IS_TMC(Y2)
+          tmc_get_registers(stepperY2, i);
+        #endif
+      }
+    #endif
 
-    if (print_z) {
+    if (TERN0(HAS_Z_AXIS, print_z)) {
       #if AXIS_IS_TMC(Z)
         tmc_get_registers(stepperZ, i);
       #endif
@@ -1061,7 +1067,7 @@
       #endif
     }
 
-    if (print_e) {
+    if (TERN0(HAS_EXTRUDERS, print_e)) {
       #if AXIS_IS_TMC(E0)
         tmc_get_registers(stepperE0, i);
       #endif
@@ -1242,16 +1248,18 @@ void test_tmc_connection(
     #endif
   }
 
-  if (test_y) {
-    #if AXIS_IS_TMC(Y)
-      axis_connection += test_connection(stepperY);
-    #endif
-    #if AXIS_IS_TMC(Y2)
-      axis_connection += test_connection(stepperY2);
-    #endif
-  }
+  #if LINEAR_AXES >= XY
+    if (test_y) {
+      #if AXIS_IS_TMC(Y)
+        axis_connection += test_connection(stepperY);
+      #endif
+      #if AXIS_IS_TMC(Y2)
+        axis_connection += test_connection(stepperY2);
+      #endif
+    }
+  #endif
 
-  if (test_z) {
+  if (TERN0(HAS_Z_AXIS, test_z)) {
     #if AXIS_IS_TMC(Z)
       axis_connection += test_connection(stepperZ);
     #endif
@@ -1266,7 +1274,7 @@ void test_tmc_connection(
     #endif
   }
 
-  if (test_e) {
+  if (TERN0(HAS_EXTRUDERS, test_e)) {
     #if AXIS_IS_TMC(E0)
       axis_connection += test_connection(stepperE0);
     #endif
diff --git a/Marlin/src/gcode/feature/L6470/M906.cpp b/Marlin/src/gcode/feature/L6470/M906.cpp
index 87614e9c73d..05631e99d29 100644
--- a/Marlin/src/gcode/feature/L6470/M906.cpp
+++ b/Marlin/src/gcode/feature/L6470/M906.cpp
@@ -252,58 +252,67 @@ void GcodeSuite::M906() {
           if (index == 1) L6470_SET_KVAL_HOLD(X2);
         #endif
         break;
-      case Y_AXIS:
-        #if AXIS_IS_L64XX(Y)
-          if (index == 0) L6470_SET_KVAL_HOLD(Y);
-        #endif
-        #if AXIS_IS_L64XX(Y2)
-          if (index == 1) L6470_SET_KVAL_HOLD(Y2);
-        #endif
-        break;
-      case Z_AXIS:
-        #if AXIS_IS_L64XX(Z)
-          if (index == 0) L6470_SET_KVAL_HOLD(Z);
-        #endif
-        #if AXIS_IS_L64XX(Z2)
-          if (index == 1) L6470_SET_KVAL_HOLD(Z2);
-        #endif
-        #if AXIS_IS_L64XX(Z3)
-          if (index == 2) L6470_SET_KVAL_HOLD(Z3);
-        #endif
-        #if AXIS_DRIVER_TYPE_Z4(L6470)
-          if (index == 3) L6470_SET_KVAL_HOLD(Z4);
-        #endif
-        break;
-      case E_AXIS: {
-        const int8_t target_extruder = get_target_extruder_from_command();
-        if (target_extruder < 0) return;
-        switch (target_extruder) {
-          #if AXIS_IS_L64XX(E0)
-            case 0: L6470_SET_KVAL_HOLD(E0); break;
+
+      #if LINEAR_AXES >= XY
+        case Y_AXIS:
+          #if AXIS_IS_L64XX(Y)
+            if (index == 0) L6470_SET_KVAL_HOLD(Y);
           #endif
-          #if AXIS_IS_L64XX(E1)
-            case 1: L6470_SET_KVAL_HOLD(E1); break;
+          #if AXIS_IS_L64XX(Y2)
+            if (index == 1) L6470_SET_KVAL_HOLD(Y2);
           #endif
-          #if AXIS_IS_L64XX(E2)
-            case 2: L6470_SET_KVAL_HOLD(E2); break;
+          break;
+      #endif
+
+      #if HAS_Z_AXIS
+        case Z_AXIS:
+          #if AXIS_IS_L64XX(Z)
+            if (index == 0) L6470_SET_KVAL_HOLD(Z);
           #endif
-          #if AXIS_IS_L64XX(E3)
-            case 3: L6470_SET_KVAL_HOLD(E3); break;
+          #if AXIS_IS_L64XX(Z2)
+            if (index == 1) L6470_SET_KVAL_HOLD(Z2);
           #endif
-          #if AXIS_IS_L64XX(E4)
-            case 4: L6470_SET_KVAL_HOLD(E4); break;
+          #if AXIS_IS_L64XX(Z3)
+            if (index == 2) L6470_SET_KVAL_HOLD(Z3);
           #endif
-          #if AXIS_IS_L64XX(E5)
-            case 5: L6470_SET_KVAL_HOLD(E5); break;
+          #if AXIS_DRIVER_TYPE_Z4(L6470)
+            if (index == 3) L6470_SET_KVAL_HOLD(Z4);
           #endif
-          #if AXIS_IS_L64XX(E6)
-            case 6: L6470_SET_KVAL_HOLD(E6); break;
-          #endif
-          #if AXIS_IS_L64XX(E7)
-            case 7: L6470_SET_KVAL_HOLD(E7); break;
-          #endif
-        }
-      } break;
+          break;
+      #endif
+
+      #if HAS_EXTRUDERS
+        case E_AXIS: {
+          const int8_t target_extruder = get_target_extruder_from_command();
+          if (target_extruder < 0) return;
+          switch (target_extruder) {
+            #if AXIS_IS_L64XX(E0)
+              case 0: L6470_SET_KVAL_HOLD(E0); break;
+            #endif
+            #if AXIS_IS_L64XX(E1)
+              case 1: L6470_SET_KVAL_HOLD(E1); break;
+            #endif
+            #if AXIS_IS_L64XX(E2)
+              case 2: L6470_SET_KVAL_HOLD(E2); break;
+            #endif
+            #if AXIS_IS_L64XX(E3)
+              case 3: L6470_SET_KVAL_HOLD(E3); break;
+            #endif
+            #if AXIS_IS_L64XX(E4)
+              case 4: L6470_SET_KVAL_HOLD(E4); break;
+            #endif
+            #if AXIS_IS_L64XX(E5)
+              case 5: L6470_SET_KVAL_HOLD(E5); break;
+            #endif
+            #if AXIS_IS_L64XX(E6)
+              case 6: L6470_SET_KVAL_HOLD(E6); break;
+            #endif
+            #if AXIS_IS_L64XX(E7)
+              case 7: L6470_SET_KVAL_HOLD(E7); break;
+            #endif
+          }
+        } break;
+      #endif
     }
   }
 
diff --git a/Marlin/src/gcode/feature/trinamic/M569.cpp b/Marlin/src/gcode/feature/trinamic/M569.cpp
index 8f1c0ed8192..46596164678 100644
--- a/Marlin/src/gcode/feature/trinamic/M569.cpp
+++ b/Marlin/src/gcode/feature/trinamic/M569.cpp
@@ -60,57 +60,66 @@ static void set_stealth_status(const bool enable, const int8_t target_extruder)
           if (index == 1) TMC_SET_STEALTH(X2);
         #endif
         break;
-      case Y_AXIS:
-        #if AXIS_HAS_STEALTHCHOP(Y)
-          if (index == 0) TMC_SET_STEALTH(Y);
-        #endif
-        #if AXIS_HAS_STEALTHCHOP(Y2)
-          if (index == 1) TMC_SET_STEALTH(Y2);
-        #endif
-        break;
-      case Z_AXIS:
-        #if AXIS_HAS_STEALTHCHOP(Z)
-          if (index == 0) TMC_SET_STEALTH(Z);
-        #endif
-        #if AXIS_HAS_STEALTHCHOP(Z2)
-          if (index == 1) TMC_SET_STEALTH(Z2);
-        #endif
-        #if AXIS_HAS_STEALTHCHOP(Z3)
-          if (index == 2) TMC_SET_STEALTH(Z3);
-        #endif
-        #if AXIS_HAS_STEALTHCHOP(Z4)
-          if (index == 3) TMC_SET_STEALTH(Z4);
-        #endif
-        break;
-      case E_AXIS: {
-        if (target_extruder < 0) return;
-        switch (target_extruder) {
-          #if AXIS_HAS_STEALTHCHOP(E0)
-            case 0: TMC_SET_STEALTH(E0); break;
+
+      #if LINEAR_AXES >= XY
+        case Y_AXIS:
+          #if AXIS_HAS_STEALTHCHOP(Y)
+            if (index == 0) TMC_SET_STEALTH(Y);
           #endif
-          #if AXIS_HAS_STEALTHCHOP(E1)
-            case 1: TMC_SET_STEALTH(E1); break;
+          #if AXIS_HAS_STEALTHCHOP(Y2)
+            if (index == 1) TMC_SET_STEALTH(Y2);
           #endif
-          #if AXIS_HAS_STEALTHCHOP(E2)
-            case 2: TMC_SET_STEALTH(E2); break;
+          break;
+      #endif
+
+      #if HAS_Z_AXIS
+        case Z_AXIS:
+          #if AXIS_HAS_STEALTHCHOP(Z)
+            if (index == 0) TMC_SET_STEALTH(Z);
           #endif
-          #if AXIS_HAS_STEALTHCHOP(E3)
-            case 3: TMC_SET_STEALTH(E3); break;
+          #if AXIS_HAS_STEALTHCHOP(Z2)
+            if (index == 1) TMC_SET_STEALTH(Z2);
           #endif
-          #if AXIS_HAS_STEALTHCHOP(E4)
-            case 4: TMC_SET_STEALTH(E4); break;
+          #if AXIS_HAS_STEALTHCHOP(Z3)
+            if (index == 2) TMC_SET_STEALTH(Z3);
           #endif
-          #if AXIS_HAS_STEALTHCHOP(E5)
-            case 5: TMC_SET_STEALTH(E5); break;
+          #if AXIS_HAS_STEALTHCHOP(Z4)
+            if (index == 3) TMC_SET_STEALTH(Z4);
           #endif
-          #if AXIS_HAS_STEALTHCHOP(E6)
-            case 6: TMC_SET_STEALTH(E6); break;
-          #endif
-          #if AXIS_HAS_STEALTHCHOP(E7)
-            case 7: TMC_SET_STEALTH(E7); break;
-          #endif
-        }
-      } break;
+          break;
+      #endif
+
+      #if HAS_EXTRUDERS
+        case E_AXIS: {
+          if (target_extruder < 0) return;
+          switch (target_extruder) {
+            #if AXIS_HAS_STEALTHCHOP(E0)
+              case 0: TMC_SET_STEALTH(E0); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E1)
+              case 1: TMC_SET_STEALTH(E1); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E2)
+              case 2: TMC_SET_STEALTH(E2); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E3)
+              case 3: TMC_SET_STEALTH(E3); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E4)
+              case 4: TMC_SET_STEALTH(E4); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E5)
+              case 5: TMC_SET_STEALTH(E5); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E6)
+              case 6: TMC_SET_STEALTH(E6); break;
+            #endif
+            #if AXIS_HAS_STEALTHCHOP(E7)
+              case 7: TMC_SET_STEALTH(E7); break;
+            #endif
+          }
+        } break;
+      #endif
     }
   }
 }
diff --git a/Marlin/src/gcode/feature/trinamic/M906.cpp b/Marlin/src/gcode/feature/trinamic/M906.cpp
index 86e0cd29871..848735b900b 100644
--- a/Marlin/src/gcode/feature/trinamic/M906.cpp
+++ b/Marlin/src/gcode/feature/trinamic/M906.cpp
@@ -63,58 +63,67 @@ void GcodeSuite::M906() {
           if (index == 1) TMC_SET_CURRENT(X2);
         #endif
         break;
-      case Y_AXIS:
-        #if AXIS_IS_TMC(Y)
-          if (index == 0) TMC_SET_CURRENT(Y);
-        #endif
-        #if AXIS_IS_TMC(Y2)
-          if (index == 1) TMC_SET_CURRENT(Y2);
-        #endif
-        break;
-      case Z_AXIS:
-        #if AXIS_IS_TMC(Z)
-          if (index == 0) TMC_SET_CURRENT(Z);
-        #endif
-        #if AXIS_IS_TMC(Z2)
-          if (index == 1) TMC_SET_CURRENT(Z2);
-        #endif
-        #if AXIS_IS_TMC(Z3)
-          if (index == 2) TMC_SET_CURRENT(Z3);
-        #endif
-        #if AXIS_IS_TMC(Z4)
-          if (index == 3) TMC_SET_CURRENT(Z4);
-        #endif
-        break;
-      case E_AXIS: {
-        const int8_t target_extruder = get_target_extruder_from_command();
-        if (target_extruder < 0) return;
-        switch (target_extruder) {
-          #if AXIS_IS_TMC(E0)
-            case 0: TMC_SET_CURRENT(E0); break;
+
+      #if LINEAR_AXES >= XY
+        case Y_AXIS:
+          #if AXIS_IS_TMC(Y)
+            if (index == 0) TMC_SET_CURRENT(Y);
           #endif
-          #if AXIS_IS_TMC(E1)
-            case 1: TMC_SET_CURRENT(E1); break;
+          #if AXIS_IS_TMC(Y2)
+            if (index == 1) TMC_SET_CURRENT(Y2);
           #endif
-          #if AXIS_IS_TMC(E2)
-            case 2: TMC_SET_CURRENT(E2); break;
+          break;
+      #endif
+
+      #if HAS_Z_AXIS
+        case Z_AXIS:
+          #if AXIS_IS_TMC(Z)
+            if (index == 0) TMC_SET_CURRENT(Z);
           #endif
-          #if AXIS_IS_TMC(E3)
-            case 3: TMC_SET_CURRENT(E3); break;
+          #if AXIS_IS_TMC(Z2)
+            if (index == 1) TMC_SET_CURRENT(Z2);
           #endif
-          #if AXIS_IS_TMC(E4)
-            case 4: TMC_SET_CURRENT(E4); break;
+          #if AXIS_IS_TMC(Z3)
+            if (index == 2) TMC_SET_CURRENT(Z3);
           #endif
-          #if AXIS_IS_TMC(E5)
-            case 5: TMC_SET_CURRENT(E5); break;
+          #if AXIS_IS_TMC(Z4)
+            if (index == 3) TMC_SET_CURRENT(Z4);
           #endif
-          #if AXIS_IS_TMC(E6)
-            case 6: TMC_SET_CURRENT(E6); break;
-          #endif
-          #if AXIS_IS_TMC(E7)
-            case 7: TMC_SET_CURRENT(E7); break;
-          #endif
-        }
-      } break;
+          break;
+      #endif
+
+      #if HAS_EXTRUDERS
+        case E_AXIS: {
+          const int8_t target_extruder = get_target_extruder_from_command();
+          if (target_extruder < 0) return;
+          switch (target_extruder) {
+            #if AXIS_IS_TMC(E0)
+              case 0: TMC_SET_CURRENT(E0); break;
+            #endif
+            #if AXIS_IS_TMC(E1)
+              case 1: TMC_SET_CURRENT(E1); break;
+            #endif
+            #if AXIS_IS_TMC(E2)
+              case 2: TMC_SET_CURRENT(E2); break;
+            #endif
+            #if AXIS_IS_TMC(E3)
+              case 3: TMC_SET_CURRENT(E3); break;
+            #endif
+            #if AXIS_IS_TMC(E4)
+              case 4: TMC_SET_CURRENT(E4); break;
+            #endif
+            #if AXIS_IS_TMC(E5)
+              case 5: TMC_SET_CURRENT(E5); break;
+            #endif
+            #if AXIS_IS_TMC(E6)
+              case 6: TMC_SET_CURRENT(E6); break;
+            #endif
+            #if AXIS_IS_TMC(E7)
+              case 7: TMC_SET_CURRENT(E7); break;
+            #endif
+          }
+        } break;
+      #endif
     }
   }
 
diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 5fac7dc2642..8e4241bf648 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -624,6 +624,10 @@
   #define LOGICAL_AXES LINEAR_AXES
 #endif
 
+#if LINEAR_AXES >= XYZ
+  #define HAS_Z_AXIS 1
+#endif
+
 /**
  * DISTINCT_E_FACTORS is set to give extruders (some) individual settings.
  *
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 78114db74ff..936f83915f9 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -2959,6 +2959,10 @@ static_assert(   _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
     #error "MECHANICAL_GANTRY_CALIBRATION Requires GANTRY_CALIBRATION_EXTRA_HEIGHT to be set."
   #elif !defined(GANTRY_CALIBRATION_FEEDRATE)
     #error "MECHANICAL_GANTRY_CALIBRATION Requires GANTRY_CALIBRATION_FEEDRATE to be set."
+  #elif ENABLED(Z_MULTI_ENDSTOPS)
+    #error "Sorry! MECHANICAL_GANTRY_CALIBRATION cannot be used with Z_MULTI_ENDSTOPS."
+  #elif ENABLED(Z_STEPPER_AUTO_ALIGN)
+    #error "Sorry! MECHANICAL_GANTRY_CALIBRATION cannot be used with Z_STEPPER_AUTO_ALIGN."
   #endif
   #if defined(GANTRY_CALIBRATION_SAFE_POSITION) && !defined(GANTRY_CALIBRATION_XY_PARK_FEEDRATE)
     #error "GANTRY_CALIBRATION_SAFE_POSITION Requires GANTRY_CALIBRATION_XY_PARK_FEEDRATE to be set."
diff --git a/Marlin/src/module/planner_bezier.cpp b/Marlin/src/module/planner_bezier.cpp
index be5ce4bbb46..a5e7696e0b7 100644
--- a/Marlin/src/module/planner_bezier.cpp
+++ b/Marlin/src/module/planner_bezier.cpp
@@ -181,11 +181,11 @@ void cubic_b_spline(
     t = new_t;
 
     // Compute and send new position
-    xyze_pos_t new_bez = {
+    xyze_pos_t new_bez = LOGICAL_AXIS_ARRAY(
+      interp(position.e, target.e, t),  // FIXME. These two are wrong, since the parameter t is not linear in the distance.
       new_pos0, new_pos1,
-      interp(position.z, target.z, t),   // FIXME. These two are wrong, since the parameter t is
-      interp(position.e, target.e, t)    // not linear in the distance.
-    };
+      interp(position.z, target.z, t)
+    );
     apply_motion_limits(new_bez);
     bez_target = new_bez;
 
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index bc6dbeaf255..05286a65662 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -259,7 +259,7 @@ xyze_int8_t Stepper::count_direction{0};
 
 #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                        \
   if (separate_multi_axis) {                                                                                                \
-    if (A##_HOME_TO_MIN) {                                                                                                  \
+    if (ENABLED(A##_HOME_TO_MIN)) {                                                                                         \
       if (TERN0(HAS_##A##_MIN, !(TEST(endstops.state(), A##_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##_motor)) A##_STEP_WRITE(V);     \
       if (TERN0(HAS_##A##2_MIN, !(TEST(endstops.state(), A##2_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##2_motor)) A##2_STEP_WRITE(V); \
     }                                                                                                                       \
@@ -285,7 +285,7 @@ xyze_int8_t Stepper::count_direction{0};
 
 #define TRIPLE_ENDSTOP_APPLY_STEP(A,V)                                                                                      \
   if (separate_multi_axis) {                                                                                                \
-    if (A##_HOME_TO_MIN) {                                                                                                  \
+    if (ENABLED(A##_HOME_TO_MIN)) {                                                                                         \
       if (!(TEST(endstops.state(), A##_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##_motor) A##_STEP_WRITE(V);    \
       if (!(TEST(endstops.state(), A##2_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##2_motor) A##2_STEP_WRITE(V); \
       if (!(TEST(endstops.state(), A##3_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##3_motor) A##3_STEP_WRITE(V); \
@@ -316,7 +316,7 @@ xyze_int8_t Stepper::count_direction{0};
 
 #define QUAD_ENDSTOP_APPLY_STEP(A,V)                                                                                        \
   if (separate_multi_axis) {                                                                                                \
-    if (A##_HOME_TO_MIN) {                                                                                                  \
+    if (ENABLED(A##_HOME_TO_MIN)) {                                                                                         \
       if (!(TEST(endstops.state(), A##_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##_motor) A##_STEP_WRITE(V);    \
       if (!(TEST(endstops.state(), A##2_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##2_motor) A##2_STEP_WRITE(V); \
       if (!(TEST(endstops.state(), A##3_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##3_motor) A##3_STEP_WRITE(V); \
diff --git a/Marlin/src/pins/pins_postprocess.h b/Marlin/src/pins/pins_postprocess.h
index 37ebbd47add..8cc19678f1e 100644
--- a/Marlin/src/pins/pins_postprocess.h
+++ b/Marlin/src/pins/pins_postprocess.h
@@ -438,6 +438,392 @@
   #define Z_STOP_PIN Z_MAX_PIN
 #endif
 
+// Filament Sensor first pin alias
+#if HAS_FILAMENT_SENSOR
+  #define FIL_RUNOUT1_PIN FIL_RUNOUT_PIN
+#else
+  #undef FIL_RUNOUT_PIN
+  #undef FIL_RUNOUT1_PIN
+#endif
+
+#ifndef LCD_PINS_D4
+  #define LCD_PINS_D4 -1
+#endif
+
+#if HAS_MARLINUI_HD44780 || TOUCH_UI_ULTIPANEL
+  #ifndef LCD_PINS_D5
+    #define LCD_PINS_D5 -1
+  #endif
+  #ifndef LCD_PINS_D6
+    #define LCD_PINS_D6 -1
+  #endif
+  #ifndef LCD_PINS_D7
+    #define LCD_PINS_D7 -1
+  #endif
+#endif
+
+/**
+ * Auto-Assignment for Dual X, Dual Y, Multi-Z Steppers
+ *
+ * By default X2 is assigned to the next open E plug
+ * on the board, then in order, Y2, Z2, Z3. These can be
+ * overridden in Configuration.h or Configuration_adv.h.
+ */
+
+#define __PEXI(p,q) PIN_EXISTS(E##p##_##q)
+#define _PEXI(p,q) __PEXI(p,q)
+#define __EPIN(p,q) E##p##_##q##_PIN
+#define _EPIN(p,q) __EPIN(p,q)
+#define DIAG_REMAPPED(p,q) (PIN_EXISTS(q) && _EPIN(p##_E_INDEX, DIAG) == q##_PIN)
+
+// The X2 axis, if any, should be the next open extruder port
+#define X2_E_INDEX E_STEPPERS
+
+#if EITHER(DUAL_X_CARRIAGE, X_DUAL_STEPPER_DRIVERS)
+  #ifndef X2_STEP_PIN
+    #define X2_STEP_PIN   _EPIN(X2_E_INDEX, STEP)
+    #define X2_DIR_PIN    _EPIN(X2_E_INDEX, DIR)
+    #define X2_ENABLE_PIN _EPIN(X2_E_INDEX, ENABLE)
+    #if X2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(X2_STEP)
+      #error "No E stepper plug left for X2!"
+    #endif
+  #endif
+  #ifndef X2_MS1_PIN
+    #define X2_MS1_PIN    _EPIN(X2_E_INDEX, MS1)
+  #endif
+  #ifndef X2_MS2_PIN
+    #define X2_MS2_PIN    _EPIN(X2_E_INDEX, MS2)
+  #endif
+  #ifndef X2_MS3_PIN
+    #define X2_MS3_PIN    _EPIN(X2_E_INDEX, MS3)
+  #endif
+  #if AXIS_HAS_SPI(X2) && !defined(X2_CS_PIN)
+    #define X2_CS_PIN     _EPIN(X2_E_INDEX, CS)
+  #endif
+  #if AXIS_HAS_UART(X2)
+    #ifndef X2_SERIAL_TX_PIN
+      #define X2_SERIAL_TX_PIN _EPIN(X2_E_INDEX, SERIAL_TX)
+    #endif
+    #ifndef X2_SERIAL_RX_PIN
+      #define X2_SERIAL_RX_PIN _EPIN(X2_E_INDEX, SERIAL_RX)
+    #endif
+  #endif
+
+  //
+  // Auto-assign pins for stallGuard sensorless homing
+  //
+  #if !defined(X2_USE_ENDSTOP) && defined(X2_STALL_SENSITIVITY) && ENABLED(X_DUAL_ENDSTOPS) && _PEXI(X2_E_INDEX, DIAG)
+    #define X2_DIAG_PIN _EPIN(X2_E_INDEX, DIAG)
+    #if   DIAG_REMAPPED(X2, X_MIN)      // If already remapped in the pins file...
+      #define X2_USE_ENDSTOP _XMIN_
+    #elif DIAG_REMAPPED(X2, Y_MIN)
+      #define X2_USE_ENDSTOP _YMIN_
+    #elif DIAG_REMAPPED(X2, Z_MIN)
+      #define X2_USE_ENDSTOP _ZMIN_
+    #elif DIAG_REMAPPED(X2, X_MAX)
+      #define X2_USE_ENDSTOP _XMAX_
+    #elif DIAG_REMAPPED(X2, Y_MAX)
+      #define X2_USE_ENDSTOP _YMAX_
+    #elif DIAG_REMAPPED(X2, Z_MAX)
+      #define X2_USE_ENDSTOP _ZMAX_
+    #else                               // Otherwise use the driver DIAG_PIN directly
+      #define _X2_USE_ENDSTOP(P) _E##P##_DIAG_
+      #define X2_USE_ENDSTOP _X2_USE_ENDSTOP(X2_E_INDEX)
+    #endif
+    #undef X2_DIAG_PIN
+  #endif
+
+  #define Y2_E_INDEX INCREMENT(X2_E_INDEX)
+#else
+  #define Y2_E_INDEX X2_E_INDEX
+#endif
+
+#ifndef X2_CS_PIN
+  #define X2_CS_PIN  -1
+#endif
+#ifndef X2_MS1_PIN
+  #define X2_MS1_PIN -1
+#endif
+#ifndef X2_MS2_PIN
+  #define X2_MS2_PIN -1
+#endif
+#ifndef X2_MS3_PIN
+  #define X2_MS3_PIN -1
+#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)
+    #define Y2_DIR_PIN    _EPIN(Y2_E_INDEX, DIR)
+    #define Y2_ENABLE_PIN _EPIN(Y2_E_INDEX, ENABLE)
+    #if Y2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Y2_STEP)
+      #error "No E stepper plug left for Y2!"
+    #endif
+  #endif
+  #ifndef Y2_MS1_PIN
+    #define Y2_MS1_PIN    _EPIN(Y2_E_INDEX, MS1)
+  #endif
+  #ifndef Y2_MS2_PIN
+    #define Y2_MS2_PIN    _EPIN(Y2_E_INDEX, MS2)
+  #endif
+  #ifndef Y2_MS3_PIN
+    #define Y2_MS3_PIN    _EPIN(Y2_E_INDEX, MS3)
+  #endif
+  #if AXIS_HAS_SPI(Y2) && !defined(Y2_CS_PIN)
+    #define Y2_CS_PIN     _EPIN(Y2_E_INDEX, CS)
+  #endif
+  #if AXIS_HAS_UART(Y2)
+    #ifndef Y2_SERIAL_TX_PIN
+      #define Y2_SERIAL_TX_PIN _EPIN(Y2_E_INDEX, SERIAL_TX)
+    #endif
+    #ifndef Y2_SERIAL_RX_PIN
+      #define Y2_SERIAL_RX_PIN _EPIN(Y2_E_INDEX, SERIAL_RX)
+    #endif
+  #endif
+  // Auto-assign pins for stallGuard sensorless homing
+  #if !defined(Y2_USE_ENDSTOP) && defined(Y2_STALL_SENSITIVITY) && ENABLED(Y_DUAL_ENDSTOPS) && _PEXI(Y2_E_INDEX, DIAG)
+    #define Y2_DIAG_PIN _EPIN(Y2_E_INDEX, DIAG)
+    #if   DIAG_REMAPPED(Y2, X_MIN)
+      #define Y2_USE_ENDSTOP _XMIN_
+    #elif DIAG_REMAPPED(Y2, Y_MIN)
+      #define Y2_USE_ENDSTOP _YMIN_
+    #elif DIAG_REMAPPED(Y2, Z_MIN)
+      #define Y2_USE_ENDSTOP _ZMIN_
+    #elif DIAG_REMAPPED(Y2, X_MAX)
+      #define Y2_USE_ENDSTOP _XMAX_
+    #elif DIAG_REMAPPED(Y2, Y_MAX)
+      #define Y2_USE_ENDSTOP _YMAX_
+    #elif DIAG_REMAPPED(Y2, Z_MAX)
+      #define Y2_USE_ENDSTOP _ZMAX_
+    #else
+      #define _Y2_USE_ENDSTOP(P) _E##P##_DIAG_
+      #define Y2_USE_ENDSTOP _Y2_USE_ENDSTOP(Y2_E_INDEX)
+    #endif
+    #undef Y2_DIAG_PIN
+  #endif
+  #define Z2_E_INDEX INCREMENT(Y2_E_INDEX)
+#else
+  #define Z2_E_INDEX Y2_E_INDEX
+#endif
+
+#ifndef Y2_CS_PIN
+  #define Y2_CS_PIN  -1
+#endif
+#ifndef Y2_MS1_PIN
+  #define Y2_MS1_PIN -1
+#endif
+#ifndef Y2_MS2_PIN
+  #define Y2_MS2_PIN -1
+#endif
+#ifndef Y2_MS3_PIN
+  #define Y2_MS3_PIN -1
+#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)
+    #define Z2_DIR_PIN    _EPIN(Z2_E_INDEX, DIR)
+    #define Z2_ENABLE_PIN _EPIN(Z2_E_INDEX, ENABLE)
+    #if Z2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z2_STEP)
+      #error "No E stepper plug left for Z2!"
+    #endif
+  #endif
+  #ifndef Z2_MS1_PIN
+    #define Z2_MS1_PIN    _EPIN(Z2_E_INDEX, MS1)
+  #endif
+  #ifndef Z2_MS2_PIN
+    #define Z2_MS2_PIN    _EPIN(Z2_E_INDEX, MS2)
+  #endif
+  #ifndef Z2_MS3_PIN
+    #define Z2_MS3_PIN    _EPIN(Z2_E_INDEX, MS3)
+  #endif
+  #if AXIS_HAS_SPI(Z2) && !defined(Z2_CS_PIN)
+    #define Z2_CS_PIN     _EPIN(Z2_E_INDEX, CS)
+  #endif
+  #if AXIS_HAS_UART(Z2)
+    #ifndef Z2_SERIAL_TX_PIN
+      #define Z2_SERIAL_TX_PIN _EPIN(Z2_E_INDEX, SERIAL_TX)
+    #endif
+    #ifndef Z2_SERIAL_RX_PIN
+      #define Z2_SERIAL_RX_PIN _EPIN(Z2_E_INDEX, SERIAL_RX)
+    #endif
+  #endif
+  // Auto-assign pins for stallGuard sensorless homing
+  #if !defined(Z2_USE_ENDSTOP) && defined(Z2_STALL_SENSITIVITY) && ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 2 && _PEXI(Z2_E_INDEX, DIAG)
+    #define Z2_DIAG_PIN _EPIN(Z2_E_INDEX, DIAG)
+    #if   DIAG_REMAPPED(Z2, X_MIN)
+      #define Z2_USE_ENDSTOP _XMIN_
+    #elif DIAG_REMAPPED(Z2, Y_MIN)
+      #define Z2_USE_ENDSTOP _YMIN_
+    #elif DIAG_REMAPPED(Z2, Z_MIN)
+      #define Z2_USE_ENDSTOP _ZMIN_
+    #elif DIAG_REMAPPED(Z2, X_MAX)
+      #define Z2_USE_ENDSTOP _XMAX_
+    #elif DIAG_REMAPPED(Z2, Y_MAX)
+      #define Z2_USE_ENDSTOP _YMAX_
+    #elif DIAG_REMAPPED(Z2, Z_MAX)
+      #define Z2_USE_ENDSTOP _ZMAX_
+    #else
+      #define _Z2_USE_ENDSTOP(P) _E##P##_DIAG_
+      #define Z2_USE_ENDSTOP _Z2_USE_ENDSTOP(Z2_E_INDEX)
+    #endif
+    #undef Z2_DIAG_PIN
+  #endif
+  #define Z3_E_INDEX INCREMENT(Z2_E_INDEX)
+#else
+  #define Z3_E_INDEX Z2_E_INDEX
+#endif
+
+#ifndef Z2_CS_PIN
+  #define Z2_CS_PIN  -1
+#endif
+#ifndef Z2_MS1_PIN
+  #define Z2_MS1_PIN -1
+#endif
+#ifndef Z2_MS2_PIN
+  #define Z2_MS2_PIN -1
+#endif
+#ifndef Z2_MS3_PIN
+  #define Z2_MS3_PIN -1
+#endif
+
+#if NUM_Z_STEPPER_DRIVERS >= 3
+  #ifndef Z3_STEP_PIN
+    #define Z3_STEP_PIN   _EPIN(Z3_E_INDEX, STEP)
+    #define Z3_DIR_PIN    _EPIN(Z3_E_INDEX, DIR)
+    #define Z3_ENABLE_PIN _EPIN(Z3_E_INDEX, ENABLE)
+    #if Z3_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z3_STEP)
+      #error "No E stepper plug left for Z3!"
+    #endif
+  #endif
+  #if AXIS_HAS_SPI(Z3)
+    #ifndef Z3_CS_PIN
+      #define Z3_CS_PIN   _EPIN(Z3_E_INDEX, CS)
+    #endif
+  #endif
+  #ifndef Z3_MS1_PIN
+    #define Z3_MS1_PIN    _EPIN(Z3_E_INDEX, MS1)
+  #endif
+  #ifndef Z3_MS2_PIN
+    #define Z3_MS2_PIN    _EPIN(Z3_E_INDEX, MS2)
+  #endif
+  #ifndef Z3_MS3_PIN
+    #define Z3_MS3_PIN    _EPIN(Z3_E_INDEX, MS3)
+  #endif
+  #if AXIS_HAS_UART(Z3)
+    #ifndef Z3_SERIAL_TX_PIN
+      #define Z3_SERIAL_TX_PIN _EPIN(Z3_E_INDEX, SERIAL_TX)
+    #endif
+    #ifndef Z3_SERIAL_RX_PIN
+      #define Z3_SERIAL_RX_PIN _EPIN(Z3_E_INDEX, SERIAL_RX)
+    #endif
+  #endif
+  // Auto-assign pins for stallGuard sensorless homing
+  #if !defined(Z3_USE_ENDSTOP) && defined(Z3_STALL_SENSITIVITY) && ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 3 && _PEXI(Z3_E_INDEX, DIAG)
+    #define Z3_DIAG_PIN _EPIN(Z3_E_INDEX, DIAG)
+    #if   DIAG_REMAPPED(Z3, X_MIN)
+      #define Z3_USE_ENDSTOP _XMIN_
+    #elif DIAG_REMAPPED(Z3, Y_MIN)
+      #define Z3_USE_ENDSTOP _YMIN_
+    #elif DIAG_REMAPPED(Z3, Z_MIN)
+      #define Z3_USE_ENDSTOP _ZMIN_
+    #elif DIAG_REMAPPED(Z3, X_MAX)
+      #define Z3_USE_ENDSTOP _XMAX_
+    #elif DIAG_REMAPPED(Z3, Y_MAX)
+      #define Z3_USE_ENDSTOP _YMAX_
+    #elif DIAG_REMAPPED(Z3, Z_MAX)
+      #define Z3_USE_ENDSTOP _ZMAX_
+    #else
+      #define _Z3_USE_ENDSTOP(P) _E##P##_DIAG_
+      #define Z3_USE_ENDSTOP _Z3_USE_ENDSTOP(Z3_E_INDEX)
+    #endif
+    #undef Z3_DIAG_PIN
+  #endif
+  #define Z4_E_INDEX INCREMENT(Z3_E_INDEX)
+#endif
+
+#ifndef Z3_CS_PIN
+  #define Z3_CS_PIN  -1
+#endif
+#ifndef Z3_MS1_PIN
+  #define Z3_MS1_PIN -1
+#endif
+#ifndef Z3_MS2_PIN
+  #define Z3_MS2_PIN -1
+#endif
+#ifndef Z3_MS3_PIN
+  #define Z3_MS3_PIN -1
+#endif
+
+#if NUM_Z_STEPPER_DRIVERS >= 4
+  #ifndef Z4_STEP_PIN
+    #define Z4_STEP_PIN   _EPIN(Z4_E_INDEX, STEP)
+    #define Z4_DIR_PIN    _EPIN(Z4_E_INDEX, DIR)
+    #define Z4_ENABLE_PIN _EPIN(Z4_E_INDEX, ENABLE)
+    #if Z4_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z4_STEP)
+      #error "No E stepper plug left for Z4!"
+    #endif
+  #endif
+  #if AXIS_HAS_SPI(Z4)
+    #ifndef Z4_CS_PIN
+      #define Z4_CS_PIN     _EPIN(Z4_E_INDEX, CS)
+    #endif
+  #endif
+  #ifndef Z4_MS1_PIN
+    #define Z4_MS1_PIN    _EPIN(Z4_E_INDEX, MS1)
+  #endif
+  #ifndef Z4_MS2_PIN
+    #define Z4_MS2_PIN    _EPIN(Z4_E_INDEX, MS2)
+  #endif
+  #ifndef Z4_MS3_PIN
+    #define Z4_MS3_PIN    _EPIN(Z4_E_INDEX, MS3)
+  #endif
+  #if AXIS_HAS_UART(Z4)
+    #ifndef Z4_SERIAL_TX_PIN
+      #define Z4_SERIAL_TX_PIN _EPIN(Z4_E_INDEX, SERIAL_TX)
+    #endif
+    #ifndef Z4_SERIAL_RX_PIN
+      #define Z4_SERIAL_RX_PIN _EPIN(Z4_E_INDEX, SERIAL_RX)
+    #endif
+  #endif
+  // Auto-assign pins for stallGuard sensorless homing
+  #if !defined(Z4_USE_ENDSTOP) && defined(Z4_STALL_SENSITIVITY) && ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 4 && _PEXI(Z4_E_INDEX, DIAG)
+    #define Z4_DIAG_PIN _EPIN(Z4_E_INDEX, DIAG)
+    #if   DIAG_REMAPPED(Z4, X_MIN)
+      #define Z4_USE_ENDSTOP _XMIN_
+    #elif DIAG_REMAPPED(Z4, Y_MIN)
+      #define Z4_USE_ENDSTOP _YMIN_
+    #elif DIAG_REMAPPED(Z4, Z_MIN)
+      #define Z4_USE_ENDSTOP _ZMIN_
+    #elif DIAG_REMAPPED(Z4, X_MAX)
+      #define Z4_USE_ENDSTOP _XMAX_
+    #elif DIAG_REMAPPED(Z4, Y_MAX)
+      #define Z4_USE_ENDSTOP _YMAX_
+    #elif DIAG_REMAPPED(Z4, Z_MAX)
+      #define Z4_USE_ENDSTOP _ZMAX_
+    #else
+      #define _Z4_USE_ENDSTOP(P) _E##P##_DIAG_
+      #define Z4_USE_ENDSTOP _Z4_USE_ENDSTOP(Z4_E_INDEX)
+    #endif
+    #undef Z4_DIAG_PIN
+  #endif
+#endif
+
+#ifndef Z4_CS_PIN
+  #define Z4_CS_PIN  -1
+#endif
+#ifndef Z4_MS1_PIN
+  #define Z4_MS1_PIN -1
+#endif
+#ifndef Z4_MS2_PIN
+  #define Z4_MS2_PIN -1
+#endif
+#ifndef Z4_MS3_PIN
+  #define Z4_MS3_PIN -1
+#endif
+
 //
 // Disable unused endstop / probe pins
 //
@@ -520,387 +906,9 @@
   #undef Z4_MAX_PIN
 #endif
 
-#if HAS_FILAMENT_SENSOR
-  #define FIL_RUNOUT1_PIN FIL_RUNOUT_PIN
-#else
-  #undef FIL_RUNOUT_PIN
-  #undef FIL_RUNOUT1_PIN
-#endif
-
-#ifndef LCD_PINS_D4
-  #define LCD_PINS_D4 -1
-#endif
-
-#if HAS_MARLINUI_HD44780 || TOUCH_UI_ULTIPANEL
-  #ifndef LCD_PINS_D5
-    #define LCD_PINS_D5 -1
-  #endif
-  #ifndef LCD_PINS_D6
-    #define LCD_PINS_D6 -1
-  #endif
-  #ifndef LCD_PINS_D7
-    #define LCD_PINS_D7 -1
-  #endif
-#endif
-
-/**
- * Auto-Assignment for Dual X, Dual Y, Multi-Z Steppers
- *
- * By default X2 is assigned to the next open E plug
- * on the board, then in order, Y2, Z2, Z3. These can be
- * overridden in Configuration.h or Configuration_adv.h.
- */
-
-#define __PEXI(p,q) PIN_EXISTS(E##p##_##q)
-#define _PEXI(p,q) __PEXI(p,q)
-#define __EPIN(p,q) E##p##_##q##_PIN
-#define _EPIN(p,q) __EPIN(p,q)
-#define DIAG_REMAPPED(p,q) (PIN_EXISTS(q) && _EPIN(p##_E_INDEX, DIAG) == q##_PIN)
-
-// The X2 axis, if any, should be the next open extruder port
-#define X2_E_INDEX E_STEPPERS
-
-#if EITHER(DUAL_X_CARRIAGE, X_DUAL_STEPPER_DRIVERS)
-  #ifndef X2_STEP_PIN
-    #define X2_STEP_PIN   _EPIN(X2_E_INDEX, STEP)
-    #define X2_DIR_PIN    _EPIN(X2_E_INDEX, DIR)
-    #define X2_ENABLE_PIN _EPIN(X2_E_INDEX, ENABLE)
-    #if X2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(X2_STEP)
-      #error "No E stepper plug left for X2!"
-    #endif
-  #endif
-  #ifndef X2_MS1_PIN
-    #define X2_MS1_PIN    _EPIN(X2_E_INDEX, MS1)
-  #endif
-  #ifndef X2_MS2_PIN
-    #define X2_MS2_PIN    _EPIN(X2_E_INDEX, MS2)
-  #endif
-  #ifndef X2_MS3_PIN
-    #define X2_MS3_PIN    _EPIN(X2_E_INDEX, MS3)
-  #endif
-  #if AXIS_HAS_SPI(X2) && !defined(X2_CS_PIN)
-    #define X2_CS_PIN     _EPIN(X2_E_INDEX, CS)
-  #endif
-  #if AXIS_HAS_UART(X2)
-    #ifndef X2_SERIAL_TX_PIN
-      #define X2_SERIAL_TX_PIN _EPIN(X2_E_INDEX, SERIAL_TX)
-    #endif
-    #ifndef X2_SERIAL_RX_PIN
-      #define X2_SERIAL_RX_PIN _EPIN(X2_E_INDEX, SERIAL_RX)
-    #endif
-  #endif
-
-  //
-  // Auto-assign pins for stallGuard sensorless homing
-  //
-  #if defined(X2_STALL_SENSITIVITY) && ENABLED(X_DUAL_ENDSTOPS) && _PEXI(X2_E_INDEX, DIAG)
-    #define X2_DIAG_PIN _EPIN(X2_E_INDEX, DIAG)
-    #if   DIAG_REMAPPED(X2, X_MIN)      // If already remapped in the pins file...
-      #define X2_USE_ENDSTOP _XMIN_
-    #elif DIAG_REMAPPED(X2, Y_MIN)
-      #define X2_USE_ENDSTOP _YMIN_
-    #elif DIAG_REMAPPED(X2, Z_MIN)
-      #define X2_USE_ENDSTOP _ZMIN_
-    #elif DIAG_REMAPPED(X2, X_MAX)
-      #define X2_USE_ENDSTOP _XMAX_
-    #elif DIAG_REMAPPED(X2, Y_MAX)
-      #define X2_USE_ENDSTOP _YMAX_
-    #elif DIAG_REMAPPED(X2, Z_MAX)
-      #define X2_USE_ENDSTOP _ZMAX_
-    #else                               // Otherwise use the driver DIAG_PIN directly
-      #define _X2_USE_ENDSTOP(P) _E##P##_DIAG_
-      #define X2_USE_ENDSTOP _X2_USE_ENDSTOP(X2_E_INDEX)
-    #endif
-    #undef X2_DIAG_PIN
-  #endif
-
-  #define Y2_E_INDEX INCREMENT(X2_E_INDEX)
-#else
-  #define Y2_E_INDEX X2_E_INDEX
-#endif
-
-#ifndef X2_CS_PIN
-  #define X2_CS_PIN  -1
-#endif
-#ifndef X2_MS1_PIN
-  #define X2_MS1_PIN -1
-#endif
-#ifndef X2_MS2_PIN
-  #define X2_MS2_PIN -1
-#endif
-#ifndef X2_MS3_PIN
-  #define X2_MS3_PIN -1
-#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)
-    #define Y2_DIR_PIN    _EPIN(Y2_E_INDEX, DIR)
-    #define Y2_ENABLE_PIN _EPIN(Y2_E_INDEX, ENABLE)
-    #if Y2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Y2_STEP)
-      #error "No E stepper plug left for Y2!"
-    #endif
-  #endif
-  #ifndef Y2_MS1_PIN
-    #define Y2_MS1_PIN    _EPIN(Y2_E_INDEX, MS1)
-  #endif
-  #ifndef Y2_MS2_PIN
-    #define Y2_MS2_PIN    _EPIN(Y2_E_INDEX, MS2)
-  #endif
-  #ifndef Y2_MS3_PIN
-    #define Y2_MS3_PIN    _EPIN(Y2_E_INDEX, MS3)
-  #endif
-  #if AXIS_HAS_SPI(Y2) && !defined(Y2_CS_PIN)
-    #define Y2_CS_PIN     _EPIN(Y2_E_INDEX, CS)
-  #endif
-  #if AXIS_HAS_UART(Y2)
-    #ifndef Y2_SERIAL_TX_PIN
-      #define Y2_SERIAL_TX_PIN _EPIN(Y2_E_INDEX, SERIAL_TX)
-    #endif
-    #ifndef Y2_SERIAL_RX_PIN
-      #define Y2_SERIAL_RX_PIN _EPIN(Y2_E_INDEX, SERIAL_RX)
-    #endif
-  #endif
-  #if defined(Y2_STALL_SENSITIVITY) && ENABLED(Y_DUAL_ENDSTOPS) && _PEXI(Y2_E_INDEX, DIAG)
-    #define Y2_DIAG_PIN _EPIN(Y2_E_INDEX, DIAG)
-    #if   DIAG_REMAPPED(Y2, X_MIN)
-      #define Y2_USE_ENDSTOP _XMIN_
-    #elif DIAG_REMAPPED(Y2, Y_MIN)
-      #define Y2_USE_ENDSTOP _YMIN_
-    #elif DIAG_REMAPPED(Y2, Z_MIN)
-      #define Y2_USE_ENDSTOP _ZMIN_
-    #elif DIAG_REMAPPED(Y2, X_MAX)
-      #define Y2_USE_ENDSTOP _XMAX_
-    #elif DIAG_REMAPPED(Y2, Y_MAX)
-      #define Y2_USE_ENDSTOP _YMAX_
-    #elif DIAG_REMAPPED(Y2, Z_MAX)
-      #define Y2_USE_ENDSTOP _ZMAX_
-    #else
-      #define _Y2_USE_ENDSTOP(P) _E##P##_DIAG_
-      #define Y2_USE_ENDSTOP _Y2_USE_ENDSTOP(Y2_E_INDEX)
-    #endif
-    #undef Y2_DIAG_PIN
-  #endif
-  #define Z2_E_INDEX INCREMENT(Y2_E_INDEX)
-#else
-  #define Z2_E_INDEX Y2_E_INDEX
-#endif
-
-#ifndef Y2_CS_PIN
-  #define Y2_CS_PIN  -1
-#endif
-#ifndef Y2_MS1_PIN
-  #define Y2_MS1_PIN -1
-#endif
-#ifndef Y2_MS2_PIN
-  #define Y2_MS2_PIN -1
-#endif
-#ifndef Y2_MS3_PIN
-  #define Y2_MS3_PIN -1
-#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)
-    #define Z2_DIR_PIN    _EPIN(Z2_E_INDEX, DIR)
-    #define Z2_ENABLE_PIN _EPIN(Z2_E_INDEX, ENABLE)
-    #if Z2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z2_STEP)
-      #error "No E stepper plug left for Z2!"
-    #endif
-  #endif
-  #ifndef Z2_MS1_PIN
-    #define Z2_MS1_PIN    _EPIN(Z2_E_INDEX, MS1)
-  #endif
-  #ifndef Z2_MS2_PIN
-    #define Z2_MS2_PIN    _EPIN(Z2_E_INDEX, MS2)
-  #endif
-  #ifndef Z2_MS3_PIN
-    #define Z2_MS3_PIN    _EPIN(Z2_E_INDEX, MS3)
-  #endif
-  #if AXIS_HAS_SPI(Z2) && !defined(Z2_CS_PIN)
-    #define Z2_CS_PIN     _EPIN(Z2_E_INDEX, CS)
-  #endif
-  #if AXIS_HAS_UART(Z2)
-    #ifndef Z2_SERIAL_TX_PIN
-      #define Z2_SERIAL_TX_PIN _EPIN(Z2_E_INDEX, SERIAL_TX)
-    #endif
-    #ifndef Z2_SERIAL_RX_PIN
-      #define Z2_SERIAL_RX_PIN _EPIN(Z2_E_INDEX, SERIAL_RX)
-    #endif
-  #endif
-  #if defined(Z2_STALL_SENSITIVITY) && ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 2 && _PEXI(Z2_E_INDEX, DIAG)
-    #define Z2_DIAG_PIN _EPIN(Z2_E_INDEX, DIAG)
-    #if   DIAG_REMAPPED(Z2, X_MIN)
-      #define Z2_USE_ENDSTOP _XMIN_
-    #elif DIAG_REMAPPED(Z2, Y_MIN)
-      #define Z2_USE_ENDSTOP _YMIN_
-    #elif DIAG_REMAPPED(Z2, Z_MIN)
-      #define Z2_USE_ENDSTOP _ZMIN_
-    #elif DIAG_REMAPPED(Z2, X_MAX)
-      #define Z2_USE_ENDSTOP _XMAX_
-    #elif DIAG_REMAPPED(Z2, Y_MAX)
-      #define Z2_USE_ENDSTOP _YMAX_
-    #elif DIAG_REMAPPED(Z2, Z_MAX)
-      #define Z2_USE_ENDSTOP _ZMAX_
-    #else
-      #define _Z2_USE_ENDSTOP(P) _E##P##_DIAG_
-      #define Z2_USE_ENDSTOP _Z2_USE_ENDSTOP(Z2_E_INDEX)
-    #endif
-    #undef Z2_DIAG_PIN
-  #endif
-  #define Z3_E_INDEX INCREMENT(Z2_E_INDEX)
-#else
-  #define Z3_E_INDEX Z2_E_INDEX
-#endif
-
-#ifndef Z2_CS_PIN
-  #define Z2_CS_PIN  -1
-#endif
-#ifndef Z2_MS1_PIN
-  #define Z2_MS1_PIN -1
-#endif
-#ifndef Z2_MS2_PIN
-  #define Z2_MS2_PIN -1
-#endif
-#ifndef Z2_MS3_PIN
-  #define Z2_MS3_PIN -1
-#endif
-
-#if NUM_Z_STEPPER_DRIVERS >= 3
-  #ifndef Z3_STEP_PIN
-    #define Z3_STEP_PIN   _EPIN(Z3_E_INDEX, STEP)
-    #define Z3_DIR_PIN    _EPIN(Z3_E_INDEX, DIR)
-    #define Z3_ENABLE_PIN _EPIN(Z3_E_INDEX, ENABLE)
-    #if Z3_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z3_STEP)
-      #error "No E stepper plug left for Z3!"
-    #endif
-  #endif
-  #if AXIS_HAS_SPI(Z3)
-    #ifndef Z3_CS_PIN
-      #define Z3_CS_PIN   _EPIN(Z3_E_INDEX, CS)
-    #endif
-  #endif
-  #ifndef Z3_MS1_PIN
-    #define Z3_MS1_PIN    _EPIN(Z3_E_INDEX, MS1)
-  #endif
-  #ifndef Z3_MS2_PIN
-    #define Z3_MS2_PIN    _EPIN(Z3_E_INDEX, MS2)
-  #endif
-  #ifndef Z3_MS3_PIN
-    #define Z3_MS3_PIN    _EPIN(Z3_E_INDEX, MS3)
-  #endif
-  #if AXIS_HAS_UART(Z3)
-    #ifndef Z3_SERIAL_TX_PIN
-      #define Z3_SERIAL_TX_PIN _EPIN(Z3_E_INDEX, SERIAL_TX)
-    #endif
-    #ifndef Z3_SERIAL_RX_PIN
-      #define Z3_SERIAL_RX_PIN _EPIN(Z3_E_INDEX, SERIAL_RX)
-    #endif
-  #endif
-  #if defined(Z3_STALL_SENSITIVITY) && ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 3 && _PEXI(Z3_E_INDEX, DIAG)
-    #define Z3_DIAG_PIN _EPIN(Z3_E_INDEX, DIAG)
-    #if   DIAG_REMAPPED(Z3, X_MIN)
-      #define Z3_USE_ENDSTOP _XMIN_
-    #elif DIAG_REMAPPED(Z3, Y_MIN)
-      #define Z3_USE_ENDSTOP _YMIN_
-    #elif DIAG_REMAPPED(Z3, Z_MIN)
-      #define Z3_USE_ENDSTOP _ZMIN_
-    #elif DIAG_REMAPPED(Z3, X_MAX)
-      #define Z3_USE_ENDSTOP _XMAX_
-    #elif DIAG_REMAPPED(Z3, Y_MAX)
-      #define Z3_USE_ENDSTOP _YMAX_
-    #elif DIAG_REMAPPED(Z3, Z_MAX)
-      #define Z3_USE_ENDSTOP _ZMAX_
-    #else
-      #define _Z3_USE_ENDSTOP(P) _E##P##_DIAG_
-      #define Z3_USE_ENDSTOP _Z3_USE_ENDSTOP(Z3_E_INDEX)
-    #endif
-    #undef Z3_DIAG_PIN
-  #endif
-  #define Z4_E_INDEX INCREMENT(Z3_E_INDEX)
-#endif
-
-#ifndef Z3_CS_PIN
-  #define Z3_CS_PIN  -1
-#endif
-#ifndef Z3_MS1_PIN
-  #define Z3_MS1_PIN -1
-#endif
-#ifndef Z3_MS2_PIN
-  #define Z3_MS2_PIN -1
-#endif
-#ifndef Z3_MS3_PIN
-  #define Z3_MS3_PIN -1
-#endif
-
-#if NUM_Z_STEPPER_DRIVERS >= 4
-  #ifndef Z4_STEP_PIN
-    #define Z4_STEP_PIN   _EPIN(Z4_E_INDEX, STEP)
-    #define Z4_DIR_PIN    _EPIN(Z4_E_INDEX, DIR)
-    #define Z4_ENABLE_PIN _EPIN(Z4_E_INDEX, ENABLE)
-    #if Z4_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z4_STEP)
-      #error "No E stepper plug left for Z4!"
-    #endif
-  #endif
-  #if AXIS_HAS_SPI(Z4)
-    #ifndef Z4_CS_PIN
-      #define Z4_CS_PIN     _EPIN(Z4_E_INDEX, CS)
-    #endif
-  #endif
-  #ifndef Z4_MS1_PIN
-    #define Z4_MS1_PIN    _EPIN(Z4_E_INDEX, MS1)
-  #endif
-  #ifndef Z4_MS2_PIN
-    #define Z4_MS2_PIN    _EPIN(Z4_E_INDEX, MS2)
-  #endif
-  #ifndef Z4_MS3_PIN
-    #define Z4_MS3_PIN    _EPIN(Z4_E_INDEX, MS3)
-  #endif
-  #if AXIS_HAS_UART(Z4)
-    #ifndef Z4_SERIAL_TX_PIN
-      #define Z4_SERIAL_TX_PIN _EPIN(Z4_E_INDEX, SERIAL_TX)
-    #endif
-    #ifndef Z4_SERIAL_RX_PIN
-      #define Z4_SERIAL_RX_PIN _EPIN(Z4_E_INDEX, SERIAL_RX)
-    #endif
-  #endif
-  #if defined(Z4_STALL_SENSITIVITY) && ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 4 && _PEXI(Z4_E_INDEX, DIAG)
-    #define Z4_DIAG_PIN _EPIN(Z4_E_INDEX, DIAG)
-    #if   DIAG_REMAPPED(Z4, X_MIN)
-      #define Z4_USE_ENDSTOP _XMIN_
-    #elif DIAG_REMAPPED(Z4, Y_MIN)
-      #define Z4_USE_ENDSTOP _YMIN_
-    #elif DIAG_REMAPPED(Z4, Z_MIN)
-      #define Z4_USE_ENDSTOP _ZMIN_
-    #elif DIAG_REMAPPED(Z4, X_MAX)
-      #define Z4_USE_ENDSTOP _XMAX_
-    #elif DIAG_REMAPPED(Z4, Y_MAX)
-      #define Z4_USE_ENDSTOP _YMAX_
-    #elif DIAG_REMAPPED(Z4, Z_MAX)
-      #define Z4_USE_ENDSTOP _ZMAX_
-    #else
-      #define _Z4_USE_ENDSTOP(P) _E##P##_DIAG_
-      #define Z4_USE_ENDSTOP _Z4_USE_ENDSTOP(Z4_E_INDEX)
-    #endif
-    #undef Z4_DIAG_PIN
-  #endif
-#endif
-
-#ifndef Z4_CS_PIN
-  #define Z4_CS_PIN  -1
-#endif
-#ifndef Z4_MS1_PIN
-  #define Z4_MS1_PIN -1
-#endif
-#ifndef Z4_MS2_PIN
-  #define Z4_MS2_PIN -1
-#endif
-#ifndef Z4_MS3_PIN
-  #define Z4_MS3_PIN -1
-#endif
-
+//
+// Default DOGLCD SPI delays
+//
 #if HAS_MARLINUI_U8GLIB
   #if !defined(ST7920_DELAY_1) && defined(BOARD_ST7920_DELAY_1)
     #define ST7920_DELAY_1 BOARD_ST7920_DELAY_1