From d6cd7d924cbfe480d22454204a820b50db0dedf0 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Mon, 28 May 2018 19:33:54 -0500
Subject: [PATCH] Modify E-stepping macros for use in LINEAR_ADVANCE (#10887)

---
 Marlin/stepper.cpp           | 134 ++++++-----------------------------
 Marlin/stepper_indirection.h |  97 ++++++++++---------------
 2 files changed, 60 insertions(+), 171 deletions(-)

diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index 60c325342e..74cd423a62 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -246,7 +246,7 @@ volatile int32_t Stepper::endstops_trigsteps[XYZ];
 #endif
 
 #if DISABLED(MIXING_EXTRUDER)
-  #define E_APPLY_STEP(v,Q) E_STEP_WRITE(v)
+  #define E_APPLY_STEP(v,Q) E_STEP_WRITE(current_block->active_extruder, v)
 #endif
 
 // intRes = longIn1 * longIn2 >> 24
@@ -364,11 +364,11 @@ void Stepper::set_directions() {
 
   #if DISABLED(LIN_ADVANCE)
     if (motor_direction(E_AXIS)) {
-      REV_E_DIR();
+      REV_E_DIR(current_block->active_extruder);
       count_direction[E_AXIS] = -1;
     }
     else {
-      NORM_E_DIR();
+      NORM_E_DIR(current_block->active_extruder);
       count_direction[E_AXIS] = 1;
     }
   #endif // !LIN_ADVANCE
@@ -402,7 +402,7 @@ void Stepper::set_directions() {
    *
    *        V_f(t) = A*t^5 + B*t^4 + C*t^3 + D*t^2 + E*t + F
    *
-   *   Looking at the above B_0(t) through B_5(t) expanded forms, if we take the coefficients of t^5
+   *  Looking at the above B_0(t) through B_5(t) expanded forms, if we take the coefficients of t^5
    *  through t of the Bézier form of V(t), we can determine that:
    *
    *        A =    -P_0 +  5*P_1 - 10*P_2 + 10*P_3 -  5*P_4 +  P_5
@@ -1386,7 +1386,7 @@ void Stepper::stepper_pulse_phase_isr() {
           // Step mixing steppers (proportionally)
           counter_m[j] += current_block->steps[E_AXIS];
           // Step when the counter goes over zero
-          if (counter_m[j] >= 0) En_STEP_WRITE(j, !INVERT_E_STEP_PIN);
+          if (counter_m[j] >= 0) E_STEP_WRITE(j, !INVERT_E_STEP_PIN);
         }
       #else // !MIXING_EXTRUDER
         PULSE_START(E);
@@ -1428,7 +1428,7 @@ void Stepper::stepper_pulse_phase_isr() {
         MIXING_STEPPERS_LOOP(j) {
           if (counter_m[j] >= 0) {
             counter_m[j] -= current_block->mix_event_count[j];
-            En_STEP_WRITE(j, INVERT_E_STEP_PIN);
+            E_STEP_WRITE(j, INVERT_E_STEP_PIN);
           }
         }
       #else // !MIXING_EXTRUDER
@@ -1709,10 +1709,10 @@ uint32_t Stepper::stepper_block_phase_isr() {
       #endif
 
       // Initialize Bresenham counters to 1/2 the ceiling, with proper roundup (as explained in the article linked above)
-      counter_X = counter_Y = counter_Z = counter_E = -int32_t((current_block->step_event_count >> 1) + (current_block->step_event_count & 1));
+      counter_X = counter_Y = counter_Z = counter_E = -int32_t((current_block->step_event_count + 1) >> 1);
       #if ENABLED(MIXING_EXTRUDER)
         MIXING_STEPPERS_LOOP(i)
-          counter_m[i] = -int32_t((current_block->mix_event_count[i] >> 1) + (current_block->mix_event_count[i] & 1));
+          counter_m[i] = -int32_t((current_block->mix_event_count[i] + 1) >> 1);
       #endif
 
       #if ENABLED(Z_LATE_ENABLE)
@@ -1737,61 +1737,6 @@ uint32_t Stepper::stepper_block_phase_isr() {
   uint32_t Stepper::advance_isr() {
     uint32_t interval;
 
-    #if ENABLED(MK2_MULTIPLEXER) // For SNMM even-numbered steppers are reversed
-      #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) E0_DIR_WRITE(e_steps < 0 ? !INVERT_E## INDEX ##_DIR ^ TEST(INDEX, 0) : INVERT_E## INDEX ##_DIR ^ TEST(INDEX, 0)); }while(0)
-    #elif ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
-      #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) { if (e_steps < 0) REV_E_DIR(); else NORM_E_DIR(); } }while(0)
-    #elif ENABLED(SWITCHING_EXTRUDER)
-      #if EXTRUDERS > 4
-        #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) { switch (INDEX) { \
-            case 0: case 1: E0_DIR_WRITE(!INVERT_E0_DIR ^ TEST(INDEX, 0) ^ (e_steps < 0)); break; \
-            case 2: case 3: E1_DIR_WRITE(!INVERT_E1_DIR ^ TEST(INDEX, 0) ^ (e_steps < 0)); break; \
-                    case 4: E2_DIR_WRITE(!INVERT_E2_DIR ^ TEST(INDEX, 0) ^ (e_steps < 0)); \
-        } } }while(0)
-      #elif EXTRUDERS > 2
-        #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) { switch (INDEX) { \
-            case 0: case 1: E0_DIR_WRITE(!INVERT_E0_DIR ^ TEST(INDEX, 0) ^ (e_steps < 0)); break; \
-            case 2: case 3: E1_DIR_WRITE(!INVERT_E1_DIR ^ TEST(INDEX, 0) ^ (e_steps < 0)); break; \
-        } } }while(0)
-      #else
-        #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) E0_DIR_WRITE(!INVERT_E0_DIR ^ TEST(INDEX, 0) ^ (e_steps < 0)); }while(0)
-      #endif
-    #else
-      #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) E## INDEX ##_DIR_WRITE(!INVERT_E## INDEX ##_DIR ^ (e_steps < 0)); }while(0)
-    #endif
-
-    #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
-      #define START_E_PULSE(INDEX) do{ if (e_steps) E_STEP_WRITE(!INVERT_E_STEP_PIN); }while(0)
-      #define STOP_E_PULSE(INDEX) do{ if (e_steps) { e_steps < 0 ? ++e_steps : --e_steps; E_STEP_WRITE(INVERT_E_STEP_PIN); } }while(0)
-    #elif ENABLED(SWITCHING_EXTRUDER)
-      #if EXTRUDERS > 4
-        #define START_E_PULSE(INDEX) do{ if (e_steps) { switch (INDEX) { \
-            case 0: case 1: E0_STEP_WRITE(!INVERT_E_STEP_PIN); break; \
-            case 2: case 3: E1_STEP_WRITE(!INVERT_E_STEP_PIN); break; \
-                    case 4: E2_STEP_WRITE(!INVERT_E_STEP_PIN); } \
-        } }while(0)
-        #define STOP_E_PULSE(INDEX) do{ if (e_steps) { \
-          e_steps < 0 ? ++e_steps : --e_steps; \
-          switch (INDEX) { \
-            case 0: case 1: E0_STEP_WRITE( INVERT_E_STEP_PIN); break; \
-            case 2: case 3: E1_STEP_WRITE( INVERT_E_STEP_PIN); break; \
-                    case 4: E2_STEP_WRITE( INVERT_E_STEP_PIN); } \
-        } }while(0)
-      #elif EXTRUDERS > 2
-        #define START_E_PULSE(INDEX) do{ if (e_steps) { if (INDEX < 2) E0_STEP_WRITE(!INVERT_E_STEP_PIN); else E1_STEP_WRITE(!INVERT_E_STEP_PIN); } }while(0)
-        #define STOP_E_PULSE(INDEX) do{ if (e_steps) { \
-          e_steps < 0 ? ++e_steps : --e_steps; \
-          if (INDEX < 2) E0_STEP_WRITE(INVERT_E_STEP_PIN); else E1_STEP_WRITE(INVERT_E_STEP_PIN); \
-        } }while(0)
-      #else
-        #define START_E_PULSE(INDEX) do{ if (e_steps) E0_STEP_WRITE(!INVERT_E_STEP_PIN); }while(0)
-        #define STOP_E_PULSE(INDEX) do{ if (e_steps) { e_steps < 0 ? ++e_steps : --e_steps; E0_STEP_WRITE(INVERT_E_STEP_PIN); }while(0)
-      #endif
-    #else
-      #define START_E_PULSE(INDEX) do{ if (e_steps) E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN); }while(0)
-      #define STOP_E_PULSE(INDEX) do { if (e_steps) { e_steps < 0 ? ++e_steps : --e_steps; E## INDEX ##_STEP_WRITE(INVERT_E_STEP_PIN); } }while(0)
-    #endif
-
     if (use_advance_lead) {
       if (step_events_completed > LA_decelerate_after && current_adv_steps > final_adv_steps) {
         e_steps--;
@@ -1810,21 +1755,10 @@ uint32_t Stepper::stepper_block_phase_isr() {
     else
       interval = ADV_NEVER;
 
-    switch (LA_active_extruder) {
-      case 0: SET_E_STEP_DIR(0); break;
-      #if EXTRUDERS > 1
-        case 1: SET_E_STEP_DIR(1); break;
-        #if EXTRUDERS > 2
-          case 2: SET_E_STEP_DIR(2); break;
-          #if EXTRUDERS > 3
-            case 3: SET_E_STEP_DIR(3); break;
-            #if EXTRUDERS > 4
-              case 4: SET_E_STEP_DIR(4); break;
-            #endif // EXTRUDERS > 4
-          #endif // EXTRUDERS > 3
-        #endif // EXTRUDERS > 2
-      #endif // EXTRUDERS > 1
-    }
+    if (e_steps >= 0)
+      NORM_E_DIR(LA_active_extruder);
+    else
+      REV_E_DIR(LA_active_extruder);
 
     // Step E stepper if we have steps
     while (e_steps) {
@@ -1833,21 +1767,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
         hal_timer_t pulse_start = HAL_timer_get_count(PULSE_TIMER_NUM);
       #endif
 
-      switch (LA_active_extruder) {
-        case 0: START_E_PULSE(0); break;
-        #if EXTRUDERS > 1
-          case 1: START_E_PULSE(1); break;
-          #if EXTRUDERS > 2
-            case 2: START_E_PULSE(2); break;
-            #if EXTRUDERS > 3
-              case 3: START_E_PULSE(3); break;
-              #if EXTRUDERS > 4
-                case 4: START_E_PULSE(4); break;
-              #endif // EXTRUDERS > 4
-            #endif // EXTRUDERS > 3
-          #endif // EXTRUDERS > 2
-        #endif // EXTRUDERS > 1
-      }
+      E_STEP_WRITE(LA_active_extruder, !INVERT_E_STEP_PIN);
 
       // For minimum pulse time wait before stopping pulses
       #if EXTRA_CYCLES_E > 20
@@ -1857,21 +1777,9 @@ uint32_t Stepper::stepper_block_phase_isr() {
         DELAY_NS(EXTRA_CYCLES_E * NANOSECONDS_PER_CYCLE);
       #endif
 
-      switch (LA_active_extruder) {
-        case 0: STOP_E_PULSE(0); break;
-        #if EXTRUDERS > 1
-          case 1: STOP_E_PULSE(1); break;
-          #if EXTRUDERS > 2
-            case 2: STOP_E_PULSE(2); break;
-            #if EXTRUDERS > 3
-              case 3: STOP_E_PULSE(3); break;
-              #if EXTRUDERS > 4
-                case 4: STOP_E_PULSE(4); break;
-              #endif // EXTRUDERS > 4
-            #endif // EXTRUDERS > 3
-          #endif // EXTRUDERS > 2
-        #endif // EXTRUDERS > 1
-      }
+      e_steps < 0 ? ++e_steps : --e_steps;
+
+      E_STEP_WRITE(LA_active_extruder, INVERT_E_STEP_PIN);
 
       // For minimum pulse time wait before looping
       #if EXTRA_CYCLES_E > 20
@@ -2015,19 +1923,19 @@ void Stepper::init() {
     AXIS_INIT(Z, Z);
   #endif
 
-  #if HAS_E0_STEP
+  #if E_STEPPERS > 0 && HAS_E0_STEP
     E_AXIS_INIT(0);
   #endif
-  #if HAS_E1_STEP
+  #if E_STEPPERS > 1 && HAS_E1_STEP
     E_AXIS_INIT(1);
   #endif
-  #if HAS_E2_STEP
+  #if E_STEPPERS > 2 && HAS_E2_STEP
     E_AXIS_INIT(2);
   #endif
-  #if HAS_E3_STEP
+  #if E_STEPPERS > 3 && HAS_E3_STEP
     E_AXIS_INIT(3);
   #endif
-  #if HAS_E4_STEP
+  #if E_STEPPERS > 4 && HAS_E4_STEP
     E_AXIS_INIT(4);
   #endif
 
diff --git a/Marlin/stepper_indirection.h b/Marlin/stepper_indirection.h
index 34a2582d00..3e67118d86 100644
--- a/Marlin/stepper_indirection.h
+++ b/Marlin/stepper_indirection.h
@@ -446,73 +446,54 @@ void reset_stepper_drivers();    // Called by settings.load / settings.reset
 /**
  * Extruder indirection for the single E axis
  */
-#if ENABLED(SWITCHING_EXTRUDER)
+#if ENABLED(SWITCHING_EXTRUDER) // One stepper driver per two extruders, reversed on odd index
   #if EXTRUDERS > 4
-    #define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else if (current_block->active_extruder < 4) { E1_STEP_WRITE(v); } else { E2_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
-    #define REV_E_DIR()  do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 4: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
+    #define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else if (E < 4) { E1_STEP_WRITE(V); } else { E2_STEP_WRITE(V); } }while(0)
+    #define   NORM_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
+    #define    REV_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 4: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
   #elif EXTRUDERS > 3
-    #define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
-    #define REV_E_DIR()  do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
+    #define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
+    #define   NORM_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
+    #define    REV_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
   #elif EXTRUDERS > 2
-    #define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
-    #define REV_E_DIR()  do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
+    #define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
+    #define   NORM_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
+    #define    REV_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
   #else
-    #define E_STEP_WRITE(v) E0_STEP_WRITE(v)
-    #define NORM_E_DIR() do{ E0_DIR_WRITE(current_block->active_extruder ?  INVERT_E0_DIR : !INVERT_E0_DIR); }while(0)
-    #define REV_E_DIR()  do{ E0_DIR_WRITE(current_block->active_extruder ? !INVERT_E0_DIR :  INVERT_E0_DIR); }while(0)
+    #define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
+    #define   NORM_E_DIR(E)   do{ E0_DIR_WRITE(E ?  INVERT_E0_DIR : !INVERT_E0_DIR); }while(0)
+    #define    REV_E_DIR(E)   do{ E0_DIR_WRITE(E ? !INVERT_E0_DIR :  INVERT_E0_DIR); }while(0)
   #endif
-#elif ENABLED(MK2_MULTIPLEXER) // Even-numbered steppers are reversed
-  #define E_STEP_WRITE(v) E0_STEP_WRITE(v)
-  #define NORM_E_DIR() do{ E0_DIR_WRITE(TEST(current_block->active_extruder, 0) ? !INVERT_E0_DIR: INVERT_E0_DIR); }while(0)
-  #define REV_E_DIR()  do{ E0_DIR_WRITE(TEST(current_block->active_extruder, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
-#elif EXTRUDERS > 4
-  #define E_STEP_WRITE(v) do{ switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); break; case 4: E4_STEP_WRITE(v); } }while(0)
-  #define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; case 4: E4_DIR_WRITE(!INVERT_E4_DIR); } }while(0)
-  #define REV_E_DIR()  do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; case 4: E4_DIR_WRITE( INVERT_E4_DIR); } }while(0)
-#elif EXTRUDERS > 3
-  #define E_STEP_WRITE(v) do{ switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); } }while(0)
-  #define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); } }while(0)
-  #define REV_E_DIR()  do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); } }while(0)
-#elif EXTRUDERS > 2
-  #define E_STEP_WRITE(v) do{ switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); } }while(0)
-  #define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
-  #define REV_E_DIR()  do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
-#elif EXTRUDERS > 1
+#elif ENABLED(MK2_MULTIPLEXER) // One multiplexed stepper driver, reversed on odd index
+  #define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
+  #define   NORM_E_DIR(E)   do{ E0_DIR_WRITE(TEST(E, 0) ? !INVERT_E0_DIR:  INVERT_E0_DIR); }while(0)
+  #define    REV_E_DIR(E)   do{ E0_DIR_WRITE(TEST(E, 0) ?  INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
+#elif E_STEPPERS > 4
+  #define E_STEP_WRITE(E,V) do{ switch (E) { case 0: E0_STEP_WRITE(V); break; case 1: E1_STEP_WRITE(V); break; case 2: E2_STEP_WRITE(V); break; case 3: E3_STEP_WRITE(V); break; case 4: E4_STEP_WRITE(V); } }while(0)
+  #define   NORM_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; case 4: E4_DIR_WRITE(!INVERT_E4_DIR); } }while(0)
+  #define    REV_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; case 4: E4_DIR_WRITE( INVERT_E4_DIR); } }while(0)
+#elif E_STEPPERS > 3
+  #define E_STEP_WRITE(E,V) do{ switch (E) { case 0: E0_STEP_WRITE(V); break; case 1: E1_STEP_WRITE(V); break; case 2: E2_STEP_WRITE(V); break; case 3: E3_STEP_WRITE(V); } }while(0)
+  #define   NORM_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); } }while(0)
+  #define    REV_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); } }while(0)
+#elif E_STEPPERS > 2
+  #define E_STEP_WRITE(E,V) do{ switch (E) { case 0: E0_STEP_WRITE(V); break; case 1: E1_STEP_WRITE(V); break; case 2: E2_STEP_WRITE(V); } }while(0)
+  #define   NORM_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
+  #define    REV_E_DIR(E)   do{ switch (E) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
+#elif E_STEPPERS > 1
   #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
-    #define E_STEP_WRITE(v) do{ if (extruder_duplication_enabled) { E0_STEP_WRITE(v); E1_STEP_WRITE(v); } else if (current_block->active_extruder == 0) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ if (extruder_duplication_enabled) { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
-    #define REV_E_DIR()  do{ if (extruder_duplication_enabled) { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
+    #define E_STEP_WRITE(E,V) do{ if (extruder_duplication_enabled) { E0_STEP_WRITE(V); E1_STEP_WRITE(V); } else if (E == 0) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
+    #define   NORM_E_DIR(E)   do{ if (extruder_duplication_enabled) { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); } else if (E == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
+    #define    REV_E_DIR(E)   do{ if (extruder_duplication_enabled) { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); } else if (E == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
   #else
-    #define E_STEP_WRITE(v) do{ if (current_block->active_extruder == 0) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ if (current_block->active_extruder == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
-    #define REV_E_DIR()  do{ if (current_block->active_extruder == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
-  #endif
-#elif ENABLED(MIXING_EXTRUDER)
-  #define E_STEP_WRITE(v) NOOP /* not used for mixing extruders! */
-  #if MIXING_STEPPERS > 4
-    #define En_STEP_WRITE(n,v) do{ switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); break; case 4: E4_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); E2_DIR_WRITE(!INVERT_E2_DIR); E3_DIR_WRITE(!INVERT_E3_DIR); E4_DIR_WRITE(!INVERT_E4_DIR); }while(0)
-    #define REV_E_DIR()  do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); E2_DIR_WRITE( INVERT_E2_DIR); E3_DIR_WRITE( INVERT_E3_DIR); E4_DIR_WRITE( INVERT_E4_DIR); }while(0)
-  #elif MIXING_STEPPERS > 3
-    #define En_STEP_WRITE(n,v) do{ switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); E2_DIR_WRITE(!INVERT_E2_DIR); E3_DIR_WRITE(!INVERT_E3_DIR); }while(0)
-    #define REV_E_DIR()  do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); E2_DIR_WRITE( INVERT_E2_DIR); E3_DIR_WRITE( INVERT_E3_DIR); }while(0)
-  #elif MIXING_STEPPERS > 2
-    #define En_STEP_WRITE(n,v) do{ switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); E2_DIR_WRITE(!INVERT_E2_DIR); }while(0)
-    #define REV_E_DIR()  do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); E2_DIR_WRITE( INVERT_E2_DIR); }while(0)
-  #else
-    #define En_STEP_WRITE(n,v) do{ switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); } }while(0)
-    #define NORM_E_DIR() do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); }while(0)
-    #define REV_E_DIR()  do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); }while(0)
+    #define E_STEP_WRITE(E,V) do{ if (E == 0) { E0_STEP_WRITE(V); } else { E1_STEP_WRITE(V); } }while(0)
+    #define   NORM_E_DIR(E)   do{ if (E == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
+    #define    REV_E_DIR(E)   do{ if (E == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
   #endif
 #else
-  #define E_STEP_WRITE(v) E0_STEP_WRITE(v)
-  #define NORM_E_DIR() E0_DIR_WRITE(!INVERT_E0_DIR)
-  #define REV_E_DIR() E0_DIR_WRITE( INVERT_E0_DIR)
+  #define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
+  #define   NORM_E_DIR(E)   E0_DIR_WRITE(!INVERT_E0_DIR)
+  #define    REV_E_DIR(E)   E0_DIR_WRITE( INVERT_E0_DIR)
 #endif
 
 #endif // STEPPER_INDIRECTION_H