From 45e738876ac3b08af1b702d87435899005c043bc Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Thu, 11 Oct 2018 00:56:26 -0500
Subject: [PATCH] Add stepper MS3 support

Co-Authored-By: TheLongAndOnly <thelongandonly@users.noreply.github.com>
---
 Marlin/src/gcode/control/M350_M351.cpp |  14 +-
 Marlin/src/inc/Conditionals_post.h     |  46 +++--
 Marlin/src/module/stepper.cpp          | 264 ++++++++++++++++++++++---
 Marlin/src/module/stepper.h            |   2 +-
 Marlin/src/pins/pins.h                 | 103 ++++++----
 Marlin/src/pins/pinsDebug_list.h       |  36 ++++
 Marlin/src/pins/pins_RURAMPS4D_11.h    |   3 -
 7 files changed, 372 insertions(+), 96 deletions(-)

diff --git a/Marlin/src/gcode/control/M350_M351.cpp b/Marlin/src/gcode/control/M350_M351.cpp
index cd75e7b2b1..a83823f315 100644
--- a/Marlin/src/gcode/control/M350_M351.cpp
+++ b/Marlin/src/gcode/control/M350_M351.cpp
@@ -41,17 +41,21 @@ void GcodeSuite::M350() {
 
 /**
  * M351: Toggle MS1 MS2 pins directly with axis codes X Y Z E B
- *       S# determines MS1 or MS2, X# sets the pin high/low.
+ *       S# determines MS1, MS2 or MS3, X# sets the pin high/low.
  */
 void GcodeSuite::M351() {
   if (parser.seenval('S')) switch (parser.value_byte()) {
     case 1:
-      LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, parser.value_byte(), -1);
-      if (parser.seenval('B')) stepper.microstep_ms(4, parser.value_byte(), -1);
+      LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, parser.value_byte(), -1, -1);
+      if (parser.seenval('B')) stepper.microstep_ms(4, parser.value_byte(), -1, -1);
       break;
     case 2:
-      LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, parser.value_byte());
-      if (parser.seenval('B')) stepper.microstep_ms(4, -1, parser.value_byte());
+      LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, parser.value_byte(), -1);
+      if (parser.seenval('B')) stepper.microstep_ms(4, -1, parser.value_byte(), -1);
+      break;
+    case 3:
+      LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, -1, parser.value_byte());
+      if (parser.seenval('B')) stepper.microstep_ms(4, -1, -1, parser.value_byte());
       break;
   }
   stepper.microstep_readings();
diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h
index 326a701af5..969a7021c0 100644
--- a/Marlin/src/inc/Conditionals_post.h
+++ b/Marlin/src/inc/Conditionals_post.h
@@ -236,26 +236,37 @@
   #define MAX_AUTORETRACT 99
 #endif
 
-// MS1 MS2 Stepper Driver Microstepping mode table
-#define MICROSTEP1 LOW,LOW
-#if ENABLED(HEROIC_STEPPER_DRIVERS)
-  #define MICROSTEP128 LOW,HIGH
-#else
-  #define MICROSTEP2 HIGH,LOW
-  #define MICROSTEP4 LOW,HIGH
-#endif
-#define MICROSTEP8 HIGH,HIGH
-#ifdef __SAM3X8E__
-  #if MB(ALLIGATOR)
-    #define MICROSTEP16 LOW,LOW
-    #define MICROSTEP32 HIGH,HIGH
+// MS1 MS2 MS3 Stepper Driver Microstepping mode table
+#if DISABLED(MICROSTEP_CUSTOM)
+  #define MICROSTEP1 LOW,LOW,LOW
+  #if ENABLED(HEROIC_STEPPER_DRIVERS)
+    #define MICROSTEP128 LOW,HIGH,LOW
   #else
-    #define MICROSTEP16 HIGH,HIGH
+    #define MICROSTEP2 HIGH,LOW,LOW
+    #define MICROSTEP4 LOW,HIGH,LOW
+  #endif
+  #define MICROSTEP8 HIGH,HIGH,LOW
+  #ifdef __SAM3X8E__
+    #if MB(ALLIGATOR)
+      #define MICROSTEP16 LOW,LOW,LOW
+      #define MICROSTEP32 HIGH,HIGH,LOW
+    #else
+      #define MICROSTEP16 HIGH,HIGH,LOW
+    #endif
+  #else
+    #define MICROSTEP16 HIGH,HIGH,LOW
   #endif
-#else
-  #define MICROSTEP16 HIGH,HIGH
 #endif
 
+#define HAS_MICROSTEP1 defined(MICROSTEP1)
+#define HAS_MICROSTEP2 defined(MICROSTEP2)
+#define HAS_MICROSTEP4 defined(MICROSTEP4)
+#define HAS_MICROSTEP8 defined(MICROSTEP8)
+#define HAS_MICROSTEP16 defined(MICROSTEP16)
+#define HAS_MICROSTEP32 defined(MICROSTEP32)
+#define HAS_MICROSTEP64 defined(MICROSTEP64)
+#define HAS_MICROSTEP128 defined(MICROSTEP128)
+
 /**
  * Override here because this is set in Configuration_adv.h
  */
@@ -828,6 +839,7 @@
 #define HAS_Z3_ENABLE     (PIN_EXISTS(Z3_ENABLE))
 #define HAS_Z3_DIR        (PIN_EXISTS(Z3_DIR))
 #define HAS_Z3_STEP       (PIN_EXISTS(Z3_STEP))
+#define HAS_Z3_MICROSTEPS (PIN_EXISTS(Z3_MS1))
 
 // Extruder steppers and solenoids
 #define HAS_E0_ENABLE     (PIN_EXISTS(E0_ENABLE))
@@ -1003,7 +1015,7 @@
 #define HAS_CASE_LIGHT (PIN_EXISTS(CASE_LIGHT) && ENABLED(CASE_LIGHT_ENABLE))
 
 // Digital control
-#define HAS_MICROSTEPS (HAS_X_MICROSTEPS || HAS_Y_MICROSTEPS || HAS_Z_MICROSTEPS || HAS_E0_MICROSTEPS || HAS_E1_MICROSTEPS || HAS_E2_MICROSTEPS || HAS_E3_MICROSTEPS || HAS_E4_MICROSTEPS || HAS_E5_MICROSTEPS)
+#define HAS_MICROSTEPS (HAS_X_MICROSTEPS || HAS_X2_MICROSTEPS || HAS_Y_MICROSTEPS || HAS_Y2_MICROSTEPS || HAS_Z_MICROSTEPS || HAS_Z2_MICROSTEPS || HAS_Z3_MICROSTEPS || HAS_E0_MICROSTEPS || HAS_E1_MICROSTEPS || HAS_E2_MICROSTEPS || HAS_E3_MICROSTEPS || HAS_E4_MICROSTEPS || HAS_E5_MICROSTEPS)
 #define HAS_STEPPER_RESET (PIN_EXISTS(STEPPER_RESET))
 #define HAS_DIGIPOTSS (PIN_EXISTS(DIGIPOTSS))
 #define HAS_MOTOR_CURRENT_PWM (PIN_EXISTS(MOTOR_CURRENT_PWM_XY) || PIN_EXISTS(MOTOR_CURRENT_PWM_Z) || PIN_EXISTS(MOTOR_CURRENT_PWM_E))
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index ed7ef07931..d3ce5b70a0 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -2504,53 +2504,136 @@ void Stepper::report_positions() {
    */
 
   void Stepper::microstep_init() {
-    SET_OUTPUT(X_MS1_PIN);
-    SET_OUTPUT(X_MS2_PIN);
+    #if HAS_X_MICROSTEPS
+      SET_OUTPUT(X_MS1_PIN);
+      SET_OUTPUT(X_MS2_PIN);
+      #if PIN_EXISTS(X_MS3)
+        SET_OUTPUT(X_MS3_PIN);
+      #endif
+    #endif
+    #if HAS_X2_MICROSTEPS
+      SET_OUTPUT(X2_MS1_PIN);
+      SET_OUTPUT(X2_MS2_PIN);
+      #if PIN_EXISTS(X2_MS3)
+        SET_OUTPUT(X2_MS3_PIN);
+      #endif
+    #endif
     #if HAS_Y_MICROSTEPS
       SET_OUTPUT(Y_MS1_PIN);
       SET_OUTPUT(Y_MS2_PIN);
+      #if PIN_EXISTS(Y_MS3)
+        SET_OUTPUT(Y_MS3_PIN);
+      #endif
+    #endif
+    #if HAS_Y2_MICROSTEPS
+      SET_OUTPUT(Y2_MS1_PIN);
+      SET_OUTPUT(Y2_MS2_PIN);
+      #if PIN_EXISTS(Y2_MS3)
+        SET_OUTPUT(Y2_MS3_PIN);
+      #endif
     #endif
     #if HAS_Z_MICROSTEPS
       SET_OUTPUT(Z_MS1_PIN);
       SET_OUTPUT(Z_MS2_PIN);
+      #if PIN_EXISTS(Z_MS3)
+        SET_OUTPUT(Z_MS3_PIN);
+      #endif
     #endif
+    #if HAS_Z2_MICROSTEPS
+      SET_OUTPUT(Z2_MS1_PIN);
+      SET_OUTPUT(Z2_MS2_PIN);
+      #if PIN_EXISTS(Z2_MS3)
+        SET_OUTPUT(Z2_MS3_PIN);
+      #endif
+    #endif
+    #if HAS_Z3_MICROSTEPS
+      SET_OUTPUT(Z3_MS1_PIN);
+      SET_OUTPUT(Z3_MS2_PIN);
+      #if PIN_EXISTS(Z3_MS3)
+        SET_OUTPUT(Z3_MS3_PIN);
+      #endif
+    #endif    
     #if HAS_E0_MICROSTEPS
       SET_OUTPUT(E0_MS1_PIN);
       SET_OUTPUT(E0_MS2_PIN);
+      #if PIN_EXISTS(E0_MS3)
+        SET_OUTPUT(E0_MS3_PIN);
+      #endif
     #endif
     #if HAS_E1_MICROSTEPS
       SET_OUTPUT(E1_MS1_PIN);
       SET_OUTPUT(E1_MS2_PIN);
+      #if PIN_EXISTS(E1_MS3)
+        SET_OUTPUT(E1_MS3_PIN);
+      #endif
     #endif
     #if HAS_E2_MICROSTEPS
       SET_OUTPUT(E2_MS1_PIN);
       SET_OUTPUT(E2_MS2_PIN);
+      #if PIN_EXISTS(E2_MS3)
+        SET_OUTPUT(E2_MS3_PIN);
+      #endif
     #endif
     #if HAS_E3_MICROSTEPS
       SET_OUTPUT(E3_MS1_PIN);
       SET_OUTPUT(E3_MS2_PIN);
+      #if PIN_EXISTS(E3_MS3)
+        SET_OUTPUT(E3_MS3_PIN);
+      #endif
     #endif
     #if HAS_E4_MICROSTEPS
       SET_OUTPUT(E4_MS1_PIN);
       SET_OUTPUT(E4_MS2_PIN);
+      #if PIN_EXISTS(E4_MS3)
+        SET_OUTPUT(E4_MS3_PIN);
+      #endif
     #endif
     #if HAS_E5_MICROSTEPS
       SET_OUTPUT(E5_MS1_PIN);
       SET_OUTPUT(E5_MS2_PIN);
+      #if PIN_EXISTS(E5_MS3)
+        SET_OUTPUT(E5_MS3_PIN);
+      #endif
     #endif
     static const uint8_t microstep_modes[] = MICROSTEP_MODES;
     for (uint16_t i = 0; i < COUNT(microstep_modes); i++)
       microstep_mode(i, microstep_modes[i]);
   }
 
-  void Stepper::microstep_ms(const uint8_t driver, const int8_t ms1, const int8_t ms2) {
+  void Stepper::microstep_ms(const uint8_t driver, const int8_t ms1, const int8_t ms2, const int8_t ms3) {
     if (ms1 >= 0) switch (driver) {
-      case 0: WRITE(X_MS1_PIN, ms1); break;
-      #if HAS_Y_MICROSTEPS
-        case 1: WRITE(Y_MS1_PIN, ms1); break;
+      #if HAS_X_MICROSTEPS || HAS_X2_MICROSTEPS
+        case 0:
+          #if HAS_X_MICROSTEPS
+            WRITE(X_MS1_PIN, ms1);
+          #endif
+          #if HAS_X2_MICROSTEPS
+            WRITE(X2_MS1_PIN, ms1);
+          #endif
+          break;
       #endif
-      #if HAS_Z_MICROSTEPS
-        case 2: WRITE(Z_MS1_PIN, ms1); break;
+      #if HAS_Y_MICROSTEPS || HAS_Y2_MICROSTEPS
+        case 1:
+          #if HAS_Y_MICROSTEPS
+            WRITE(Y_MS1_PIN, ms1);
+          #endif
+          #if HAS_Y2_MICROSTEPS
+            WRITE(Y2_MS1_PIN, ms1);
+          #endif
+          break;
+      #endif
+      #if HAS_Z_MICROSTEPS || HAS_Z2_MICROSTEPS || HAS_Z3_MICROSTEPS
+        case 2:
+          #if HAS_Z_MICROSTEPS
+            WRITE(Z_MS1_PIN, ms1);
+          #endif
+          #if HAS_Z2_MICROSTEPS
+            WRITE(Z2_MS1_PIN, ms1);
+          #endif
+          #if HAS_Z3_MICROSTEPS
+            WRITE(Z3_MS1_PIN, ms1);
+          #endif
+          break;
       #endif
       #if HAS_E0_MICROSTEPS
         case 3: WRITE(E0_MS1_PIN, ms1); break;
@@ -2572,12 +2655,38 @@ void Stepper::report_positions() {
       #endif
     }
     if (ms2 >= 0) switch (driver) {
-      case 0: WRITE(X_MS2_PIN, ms2); break;
-      #if HAS_Y_MICROSTEPS
-        case 1: WRITE(Y_MS2_PIN, ms2); break;
+      #if HAS_X_MICROSTEPS || HAS_X2_MICROSTEPS
+        case 0:
+          #if HAS_X_MICROSTEPS
+            WRITE(X_MS2_PIN, ms2);
+          #endif
+          #if HAS_X2_MICROSTEPS
+            WRITE(X2_MS2_PIN, ms2);
+          #endif
+          break;
       #endif
-      #if HAS_Z_MICROSTEPS
-        case 2: WRITE(Z_MS2_PIN, ms2); break;
+      #if HAS_Y_MICROSTEPS || HAS_Y2_MICROSTEPS
+        case 1:
+          #if HAS_Y_MICROSTEPS
+            WRITE(Y_MS2_PIN, ms2);
+          #endif
+          #if HAS_Y2_MICROSTEPS
+            WRITE(Y2_MS2_PIN, ms2);
+          #endif
+          break;
+      #endif
+      #if HAS_Z_MICROSTEPS || HAS_Z2_MICROSTEPS || HAS_Z3_MICROSTEPS
+        case 2:
+          #if HAS_Z_MICROSTEPS
+            WRITE(Z_MS2_PIN, ms2);
+          #endif
+          #if HAS_Z2_MICROSTEPS
+            WRITE(Z2_MS2_PIN, ms2);
+          #endif
+          #if HAS_Z3_MICROSTEPS
+            WRITE(Z3_MS2_PIN, ms2);
+          #endif
+          break;
       #endif
       #if HAS_E0_MICROSTEPS
         case 3: WRITE(E0_MS2_PIN, ms2); break;
@@ -2598,70 +2707,165 @@ void Stepper::report_positions() {
         case 8: WRITE(E5_MS2_PIN, ms2); break;
       #endif
     }
+    if (ms3 >= 0) switch (driver) {
+      #if HAS_X_MICROSTEPS || HAS_X2_MICROSTEPS
+        case 0:
+          #if HAS_X_MICROSTEPS && PIN_EXISTS(X_MS3)
+            WRITE(X_MS3_PIN, ms3);
+          #endif
+          #if HAS_X2_MICROSTEPS && PIN_EXISTS(X2_MS3)
+            WRITE(X2_MS3_PIN, ms3);
+          #endif
+          break;
+      #endif
+      #if HAS_Y_MICROSTEPS || HAS_Y2_MICROSTEPS
+        case 1:
+          #if HAS_Y_MICROSTEPS && PIN_EXISTS(Y_MS3)
+            WRITE(Y_MS3_PIN, ms3);
+          #endif
+          #if HAS_Y2_MICROSTEPS && PIN_EXISTS(Y2_MS3)
+            WRITE(Y2_MS3_PIN, ms3);
+          #endif
+          break;
+      #endif
+      #if HAS_Z_MICROSTEPS || HAS_Z2_MICROSTEPS || HAS_Z3_MICROSTEPS
+        case 2:
+          #if HAS_Z_MICROSTEPS && PIN_EXISTS(Z_MS3)
+            WRITE(Z_MS3_PIN, ms3);
+          #endif
+          #if HAS_Z2_MICROSTEPS && PIN_EXISTS(Z2_MS3)
+            WRITE(Z2_MS3_PIN, ms3);
+          #endif
+          #if HAS_Z3_MICROSTEPS && PIN_EXISTS(Z3_MS3)
+            WRITE(Z3_MS3_PIN, ms3);
+          #endif
+          break;
+      #endif
+      #if HAS_E0_MICROSTEPS && PIN_EXISTS(E0_MS3)
+        case 3: WRITE(E0_MS3_PIN, ms3); break;
+      #endif
+      #if HAS_E1_MICROSTEPS && PIN_EXISTS(E1_MS3)
+        case 4: WRITE(E1_MS3_PIN, ms3); break;
+      #endif
+      #if HAS_E2_MICROSTEPS && PIN_EXISTS(E2_MS3)
+        case 5: WRITE(E2_MS3_PIN, ms3); break;
+      #endif
+      #if HAS_E3_MICROSTEPS && PIN_EXISTS(E3_MS3)
+        case 6: WRITE(E3_MS3_PIN, ms3); break;
+      #endif
+      #if HAS_E4_MICROSTEPS && PIN_EXISTS(E4_MS3)
+        case 7: WRITE(E4_MS3_PIN, ms3); break;
+      #endif
+      #if HAS_E5_MICROSTEPS && PIN_EXISTS(E5_MS3)
+        case 8: WRITE(E5_MS3_PIN, ms3); break;
+      #endif    
+    }
   }
 
   void Stepper::microstep_mode(const uint8_t driver, const uint8_t stepping_mode) {
     switch (stepping_mode) {
-      case 1: microstep_ms(driver, MICROSTEP1); break;
-      #if ENABLED(HEROIC_STEPPER_DRIVERS)
-        case 128: microstep_ms(driver, MICROSTEP128); break;
-      #else
+      #if HAS_MICROSTEP1
+        case 1: microstep_ms(driver, MICROSTEP1); break;
+      #endif
+      #if HAS_MICROSTEP2
         case 2: microstep_ms(driver, MICROSTEP2); break;
+      #endif
+      #if HAS_MICROSTEP4
         case 4: microstep_ms(driver, MICROSTEP4); break;
       #endif
-      case 8: microstep_ms(driver, MICROSTEP8); break;
-      case 16: microstep_ms(driver, MICROSTEP16); break;
-      #if MB(ALLIGATOR)
+      #if HAS_MICROSTEP8
+        case 8: microstep_ms(driver, MICROSTEP8); break;
+      #endif
+      #if HAS_MICROSTEP16
+        case 16: microstep_ms(driver, MICROSTEP16); break;
+      #endif
+      #if HAS_MICROSTEP32
         case 32: microstep_ms(driver, MICROSTEP32); break;
       #endif
+      #if HAS_MICROSTEP64
+        case 64: microstep_ms(driver, MICROSTEP64); break;
+      #endif
+      #if HAS_MICROSTEP128
+        case 128: microstep_ms(driver, MICROSTEP128); break;
+      #endif
+
       default: SERIAL_ERROR_START(); SERIAL_ERRORLNPGM("Microsteps unavailable"); break;
     }
   }
 
   void Stepper::microstep_readings() {
-    SERIAL_PROTOCOLLNPGM("MS1,MS2 Pins");
+    SERIAL_PROTOCOLLNPGM("MS1,MS2,MS3 Pins");
     SERIAL_PROTOCOLPGM("X: ");
-    SERIAL_PROTOCOL(READ(X_MS1_PIN));
-    SERIAL_PROTOCOLLN(READ(X_MS2_PIN));
+    #if HAS_X_MICROSTEPS
+      SERIAL_PROTOCOL(READ(X_MS1_PIN));
+      SERIAL_PROTOCOL(READ(X_MS2_PIN));
+      #if PIN_EXISTS(X_MS3)
+        SERIAL_PROTOCOLLN(READ(X_MS3_PIN));
+      #endif
+    #endif
     #if HAS_Y_MICROSTEPS
       SERIAL_PROTOCOLPGM("Y: ");
       SERIAL_PROTOCOL(READ(Y_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(Y_MS2_PIN));
+      SERIAL_PROTOCOL(READ(Y_MS2_PIN));
+      #if PIN_EXISTS(Y_MS3)
+        SERIAL_PROTOCOLLN(READ(Y_MS3_PIN));
+      #endif
     #endif
     #if HAS_Z_MICROSTEPS
       SERIAL_PROTOCOLPGM("Z: ");
       SERIAL_PROTOCOL(READ(Z_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(Z_MS2_PIN));
+      SERIAL_PROTOCOL(READ(Z_MS2_PIN));
+      #if PIN_EXISTS(Z_MS3)
+        SERIAL_PROTOCOLLN(READ(Z_MS3_PIN));
+      #endif
     #endif
     #if HAS_E0_MICROSTEPS
       SERIAL_PROTOCOLPGM("E0: ");
       SERIAL_PROTOCOL(READ(E0_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(E0_MS2_PIN));
+      SERIAL_PROTOCOL(READ(E0_MS2_PIN));
+      #if PIN_EXISTS(E0_MS3)
+        SERIAL_PROTOCOLLN(READ(E0_MS3_PIN));
+      #endif
     #endif
     #if HAS_E1_MICROSTEPS
       SERIAL_PROTOCOLPGM("E1: ");
       SERIAL_PROTOCOL(READ(E1_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(E1_MS2_PIN));
+      SERIAL_PROTOCOL(READ(E1_MS2_PIN));
+      #if PIN_EXISTS(E1_MS3)
+        SERIAL_PROTOCOLLN(READ(E1_MS3_PIN));
+      #endif
     #endif
     #if HAS_E2_MICROSTEPS
       SERIAL_PROTOCOLPGM("E2: ");
       SERIAL_PROTOCOL(READ(E2_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(E2_MS2_PIN));
+      SERIAL_PROTOCOL(READ(E2_MS2_PIN));
+      #if PIN_EXISTS(E2_MS3)
+        SERIAL_PROTOCOLLN(READ(E2_MS3_PIN));
+      #endif
     #endif
     #if HAS_E3_MICROSTEPS
       SERIAL_PROTOCOLPGM("E3: ");
       SERIAL_PROTOCOL(READ(E3_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(E3_MS2_PIN));
+      SERIAL_PROTOCOL(READ(E3_MS2_PIN));
+      #if PIN_EXISTS(E3_MS3)
+        SERIAL_PROTOCOLLN(READ(E3_MS3_PIN));
+      #endif
     #endif
     #if HAS_E4_MICROSTEPS
       SERIAL_PROTOCOLPGM("E4: ");
       SERIAL_PROTOCOL(READ(E4_MS1_PIN));
-      SERIAL_PROTOCOLLN(READ(E4_MS2_PIN));
+      SERIAL_PROTOCOL(READ(E4_MS2_PIN));
+      #if PIN_EXISTS(E4_MS3)
+        SERIAL_PROTOCOLLN(READ(E4_MS3_PIN));
+      #endif
     #endif
     #if HAS_E5_MICROSTEPS
       SERIAL_PROTOCOLPGM("E5: ");
       SERIAL_PROTOCOL(READ(E5_MS1_PIN));
       SERIAL_PROTOCOLLN(READ(E5_MS2_PIN));
+      #if PIN_EXISTS(E5_MS3)
+        SERIAL_PROTOCOLLN(READ(E5_MS3_PIN));
+      #endif      
     #endif
   }
 
diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h
index 0ebe1d6e20..95f28dc914 100644
--- a/Marlin/src/module/stepper.h
+++ b/Marlin/src/module/stepper.h
@@ -413,7 +413,7 @@ class Stepper {
     #endif
 
     #if HAS_MICROSTEPS
-      static void microstep_ms(const uint8_t driver, const int8_t ms1, const int8_t ms2);
+      static void microstep_ms(const uint8_t driver, const int8_t ms1, const int8_t ms2, const int8_t ms3);
       static void microstep_mode(const uint8_t driver, const uint8_t stepping);
       static void microstep_readings();
     #endif
diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h
index 81eacf5df2..b3cd117f48 100644
--- a/Marlin/src/pins/pins.h
+++ b/Marlin/src/pins/pins.h
@@ -427,12 +427,18 @@
 #ifndef X_MS2_PIN
   #define X_MS2_PIN -1
 #endif
+#ifndef X_MS3_PIN
+  #define X_MS3_PIN -1
+#endif
 #ifndef Y_MS1_PIN
   #define Y_MS1_PIN -1
 #endif
 #ifndef Y_MS2_PIN
   #define Y_MS2_PIN -1
 #endif
+#ifndef Y_MS3_PIN
+  #define Y_MS3_PIN -1
+#endif
 #ifndef Z_MS1_PIN
   #define Z_MS1_PIN -1
 #endif
@@ -448,18 +454,27 @@
 #ifndef E0_MS2_PIN
   #define E0_MS2_PIN -1
 #endif
+#ifndef E0_MS3_PIN
+  #define E0_MS3_PIN -1
+#endif
 #ifndef E1_MS1_PIN
   #define E1_MS1_PIN -1
 #endif
 #ifndef E1_MS2_PIN
   #define E1_MS2_PIN -1
 #endif
+#ifndef E1_MS3_PIN
+  #define E1_MS3_PIN -1
+#endif
 #ifndef E2_MS1_PIN
   #define E2_MS1_PIN -1
 #endif
 #ifndef E2_MS2_PIN
   #define E2_MS2_PIN -1
 #endif
+#ifndef E2_MS3_PIN
+  #define E2_MS3_PIN -1
+#endif
 #ifndef E3_MS1_PIN
   #define E3_MS1_PIN -1
 #endif
@@ -907,19 +922,21 @@
     #define X2_STEP_PIN   _EPIN(E_STEPPERS, STEP)
     #define X2_DIR_PIN    _EPIN(E_STEPPERS, DIR)
     #define X2_ENABLE_PIN _EPIN(E_STEPPERS, ENABLE)
-    #ifndef X2_CS_PIN
-      #define X2_CS_PIN   _EPIN(E_STEPPERS, CS)
-    #endif
-    #if E_STEPPERS > MAX_EXTRUDERS || !PIN_EXISTS(X2_ENABLE)
+    #if E_STEPPERS >= MAX_EXTRUDERS || !PIN_EXISTS(X2_STEP)
       #error "No E stepper plug left for X2!"
     #endif
   #endif
-  #undef _X2_PINS
-  #define __X2_PINS X2_STEP_PIN, X2_DIR_PIN, X2_ENABLE_PIN,
-  #ifdef X2_CS_PIN
-    #define _X2_PINS __X2_PINS X2_CS_PIN,
-  #else
-    #define _X2_PINS __X2_PINS
+  #ifndef X2_CS_PIN
+    #define X2_CS_PIN     _EPIN(E_STEPPERS, CS)
+  #endif
+  #ifndef X2_MS1_PIN
+    #define X2_MS1_PIN    _EPIN(E_STEPPERS, MS1)
+  #endif
+  #ifndef X2_MS2_PIN
+    #define X2_MS2_PIN    _EPIN(E_STEPPERS, MS2)
+  #endif
+  #ifndef X2_MS3_PIN
+    #define X2_MS3_PIN    _EPIN(E_STEPPERS, MS3)
   #endif
   #define Y2_E_INDEX INCREMENT(E_STEPPERS)
 #else
@@ -932,19 +949,21 @@
     #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)
-    #ifndef Y2_CS_PIN
-      #define Y2_CS_PIN   _EPIN(Y2_E_INDEX, CS)
-    #endif
-    #if Y2_E_INDEX > MAX_EXTRUDERS || !PIN_EXISTS(Y2_ENABLE)
+    #if Y2_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Y2_STEP)
       #error "No E stepper plug left for Y2!"
     #endif
   #endif
-  #undef _Y2_PINS
-  #define __Y2_PINS Y2_STEP_PIN, Y2_DIR_PIN, Y2_ENABLE_PIN,
-  #ifdef Y2_CS_PIN
-    #define _Y2_PINS __Y2_PINS Y2_CS_PIN,
-  #else
-    #define _Y2_PINS __Y2_PINS
+  #ifndef Y2_CS_PIN
+    #define Y2_CS_PIN     _EPIN(Y2_E_INDEX, CS)
+  #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
   #define Z2_E_INDEX INCREMENT(Y2_E_INDEX)
 #else
@@ -957,19 +976,21 @@
     #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)
-    #ifndef Z2_CS_PIN
-      #define Z2_CS_PIN   _EPIN(Z2_E_INDEX, CS)
-    #endif
-    #if Z2_E_INDEX > MAX_EXTRUDERS || !PIN_EXISTS(Z2_ENABLE)
+    #if Z2_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Z2_STEP)
       #error "No E stepper plug left for Z2!"
     #endif
   #endif
-  #undef _Z2_PINS
-  #define __Z2_PINS Z2_STEP_PIN, Z2_DIR_PIN, Z2_ENABLE_PIN,
-  #ifdef Z2_CS_PIN
-    #define _Z2_PINS __Z2_PINS Z2_CS_PIN,
-  #else
-    #define _Z2_PINS __Z2_PINS
+  #ifndef Z2_CS_PIN
+    #define Z2_CS_PIN     _EPIN(Z2_E_INDEX, CS)
+  #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
   #define Z3_E_INDEX INCREMENT(Z2_E_INDEX)
 #else
@@ -981,19 +1002,21 @@
     #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)
-    #ifndef Z3_CS_PIN
-      #define Z3_CS_PIN   _EPIN(Z3_E_INDEX, CS)
-    #endif
-    #if Z3_E_INDEX > 4 || !PIN_EXISTS(Z3_ENABLE)
+    #if Z3_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Z3_STEP)
       #error "No E stepper plug left for Z3!"
     #endif
   #endif
-  #undef _Z3_PINS
-  #define __Z3_PINS Z3_STEP_PIN, Z3_DIR_PIN, Z3_ENABLE_PIN,
-  #ifdef Z3_CS_PIN
-    #define _Z3_PINS __Z3_PINS Z3_CS_PIN,
-  #else
-    #define _Z3_PINS __Z3_PINS
+  #ifndef Z3_CS_PIN
+    #define Z3_CS_PIN     _EPIN(Z3_E_INDEX, CS)
+  #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
 #endif
 
diff --git a/Marlin/src/pins/pinsDebug_list.h b/Marlin/src/pins/pinsDebug_list.h
index e6ac174c17..df4e163298 100644
--- a/Marlin/src/pins/pinsDebug_list.h
+++ b/Marlin/src/pins/pinsDebug_list.h
@@ -268,6 +268,9 @@
 #if PIN_EXISTS(E0_MS2)
   REPORT_NAME_DIGITAL(__LINE__, E0_MS2_PIN)
 #endif
+#if PIN_EXISTS(E0_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, E0_MS3_PIN)
+#endif
 #if PIN_EXISTS(E0_STEP)
   REPORT_NAME_DIGITAL(__LINE__, E0_STEP_PIN)
 #endif
@@ -289,6 +292,9 @@
 #if PIN_EXISTS(E1_MS2)
   REPORT_NAME_DIGITAL(__LINE__, E1_MS2_PIN)
 #endif
+#if PIN_EXISTS(E1_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, E1_MS3_PIN)
+#endif
 #if PIN_EXISTS(E1_STEP)
   REPORT_NAME_DIGITAL(__LINE__, E1_STEP_PIN)
 #endif
@@ -310,6 +316,9 @@
 #if PIN_EXISTS(E2_MS2)
   REPORT_NAME_DIGITAL(__LINE__, E2_MS2_PIN)
 #endif
+#if PIN_EXISTS(E2_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, E2_MS3_PIN)
+#endif
 #if PIN_EXISTS(E2_STEP)
   REPORT_NAME_DIGITAL(__LINE__, E2_STEP_PIN)
 #endif
@@ -881,6 +890,9 @@
 #if PIN_EXISTS(X_MS2)
   REPORT_NAME_DIGITAL(__LINE__, X_MS2_PIN)
 #endif
+#if PIN_EXISTS(X_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, X_MS3_PIN)
+#endif
 #if PIN_EXISTS(X_STEP)
   REPORT_NAME_DIGITAL(__LINE__, X_STEP_PIN)
 #endif
@@ -893,6 +905,15 @@
 #if PIN_EXISTS(X2_ENABLE)
   REPORT_NAME_DIGITAL(__LINE__, X2_ENABLE_PIN)
 #endif
+#if PIN_EXISTS(X2_MS1)
+  REPORT_NAME_DIGITAL(__LINE__, X2_MS1_PIN)
+#endif
+#if PIN_EXISTS(X2_MS2)
+  REPORT_NAME_DIGITAL(__LINE__, X2_MS2_PIN)
+#endif
+#if PIN_EXISTS(X2_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, X2_MS3_PIN)
+#endif
 #if PIN_EXISTS(X2_STEP)
   REPORT_NAME_DIGITAL(__LINE__, X2_STEP_PIN)
 #endif
@@ -920,6 +941,9 @@
 #if PIN_EXISTS(Y_MS2)
   REPORT_NAME_DIGITAL(__LINE__, Y_MS2_PIN)
 #endif
+#if PIN_EXISTS(Y_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, Y_MS3_PIN)
+#endif
 #if PIN_EXISTS(Y_STEP)
   REPORT_NAME_DIGITAL(__LINE__, Y_STEP_PIN)
 #endif
@@ -932,6 +956,15 @@
 #if PIN_EXISTS(Y2_ENABLE)
   REPORT_NAME_DIGITAL(__LINE__, Y2_ENABLE_PIN)
 #endif
+#if PIN_EXISTS(Y2_MS1)
+  REPORT_NAME_DIGITAL(__LINE__, Y2_MS1_PIN)
+#endif
+#if PIN_EXISTS(Y2_MS2)
+  REPORT_NAME_DIGITAL(__LINE__, Y2_MS2_PIN)
+#endif
+#if PIN_EXISTS(Y2_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, Y2_MS3_PIN)
+#endif
 #if PIN_EXISTS(Y2_STEP)
   REPORT_NAME_DIGITAL(__LINE__, Y2_STEP_PIN)
 #endif
@@ -962,6 +995,9 @@
 #if PIN_EXISTS(Z_MS2)
   REPORT_NAME_DIGITAL(__LINE__, Z_MS2_PIN)
 #endif
+#if PIN_EXISTS(Z_MS3)
+  REPORT_NAME_DIGITAL(__LINE__, Z_MS3_PIN)
+#endif
 #if PIN_EXISTS(Z_STEP)
   REPORT_NAME_DIGITAL(__LINE__, Z_STEP_PIN)
 #endif
diff --git a/Marlin/src/pins/pins_RURAMPS4D_11.h b/Marlin/src/pins/pins_RURAMPS4D_11.h
index d05b74b04c..7b78ffc7b7 100644
--- a/Marlin/src/pins/pins_RURAMPS4D_11.h
+++ b/Marlin/src/pins/pins_RURAMPS4D_11.h
@@ -119,9 +119,6 @@
 //#define E3_MS1_PIN         ?
 //#define E3_MS2_PIN         ?
 //#define E3_MS3_PIN         ?
-//#define Z2_MS1_PIN         ?   // shared with E3_MS1_PIN
-//#define Z2_MS2_PIN         ?   // shared with E3_MS2_PIN
-//#define Z2_MS3_PIN         ?   // shared with E3_MS3_PIN
 
 #if DISABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
   #define Z_MIN_PROBE_PIN  49