diff --git a/.gitignore b/.gitignore
index 0a12acfd7cf9aa712d2982af008920b55873bb4f..a24cf93707c4e8d75dfdd62f45f1c8acf93fb62b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ applet/
 *~
 *.orig
 *.rej
+*.bak
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 58e8b2e6f3f5dc0d87d283d564e40ca039cc55a3..3cbe131c958f3a8cc2ba6ea5f46d088d53612f61 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -155,8 +155,8 @@
 // Configuration for second X-carriage
 // Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
 // the second x-carriage always homes to the maximum endstop.
-#define X2_MIN_POS 88     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
-#define X2_MAX_POS 350.45 // set maximum to the distance between toolheads when both heads are homed 
+#define X2_MIN_POS 80     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
+#define X2_MAX_POS 353    // set maximum to the distance between toolheads when both heads are homed 
 #define X2_HOME_DIR 1     // the second X-carriage always homes to the maximum endstop position
 #define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position 
     // However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software 
@@ -169,7 +169,29 @@
 #define X2_STEP_PIN 25
 #define X2_DIR_PIN 23
 
-#endif // DUAL_X_CARRIAGE
+// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
+//    Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
+//                           as long as it supports dual x-carriages. (M605 S0)
+//    Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
+//                           that additional slicer support is not required. (M605 S1)
+//    Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all  
+//                           actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
+//                           once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
+
+// This is the default power-up mode which can be later using M605. 
+#define DEFAULT_DUAL_X_CARRIAGE_MODE 0 
+
+// As the x-carriages are independent we can now account for any relative Z offset
+#define EXTRUDER1_Z_OFFSET 0.0           // z offset relative to extruder 0
+
+// Default settings in "Auto-park Mode" 
+#define TOOLCHANGE_PARK_ZLIFT   0.2      // the distance to raise Z axis when parking an extruder
+#define TOOLCHANGE_UNPARK_ZLIFT 1        // the distance to raise Z axis when unparking an extruder
+
+// Default x offset in duplication mode (typically set to half print bed width)
+#define DEFAULT_DUPLICATION_X_OFFSET 100
+
+#endif //DUAL_X_CARRIAGE
     
 //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
 #define X_HOME_RETRACT_MM 5 
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index e15ffdf4e0e14fb0f2a3353bbc2fba1d8b498695..4609ce818e6e29bfb83717590308a8701c78b568 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -139,6 +139,7 @@
 // M503 - print the current settings (from memory not from eeprom)
 // M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
 // M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
+// M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
 // M907 - Set digital trimpot motor current using axis codes.
 // M908 - Control digital trimpot directly.
 // M350 - Set microstepping mode.
@@ -168,9 +169,15 @@ float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 };
 float add_homeing[3]={0,0,0};
 float min_pos[3] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS };
 float max_pos[3] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS };
-// Extruder offset, only in XY plane
+
+// Extruder offset
 #if EXTRUDERS > 1
-float extruder_offset[2][EXTRUDERS] = {
+#ifndef DUAL_X_CARRIAGE
+  #define NUM_EXTRUDER_OFFSETS 2 // only in XY plane
+#else
+  #define NUM_EXTRUDER_OFFSETS 3 // supports offsets in XYZ plane
+#endif
+float extruder_offset[NUM_EXTRUDER_OFFSETS][EXTRUDERS] = {
 #if defined(EXTRUDER_OFFSET_X) && defined(EXTRUDER_OFFSET_Y)
   EXTRUDER_OFFSET_X, EXTRUDER_OFFSET_Y
 #endif
@@ -691,8 +698,13 @@ XYZ_CONSTS_FROM_CONFIG(signed char, home_dir,  HOME_DIR);
   #endif
   #if X_HOME_DIR != -1 || X2_HOME_DIR != 1
     #error "Please use canonical x-carriage assignment" // the x-carriages are defined by their homing directions
-  #endif
+  #endif  
 
+#define DXC_FULL_CONTROL_MODE 0
+#define DXC_AUTO_PARK_MODE    1
+#define DXC_DUPLICATION_MODE  2
+static int dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
+ 
 static float x_home_pos(int extruder) {
   if (extruder == 0)
     return base_home_pos(X_AXIS) + add_homeing[X_AXIS];
@@ -708,16 +720,31 @@ static int x_home_dir(int extruder) {
   return (extruder == 0) ? X_HOME_DIR : X2_HOME_DIR;
 }
 
-static float inactive_x_carriage_pos = X2_MAX_POS;
-#endif
+static float inactive_extruder_x_pos = X2_MAX_POS; // used in mode 0 & 1
+static bool active_extruder_parked = false; // used in mode 1 & 2
+static float raised_parked_position[NUM_AXIS]; // used in mode 1 
+static unsigned long delayed_move_time = 0; // used in mode 1 
+static float duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // used in mode 2
+static float duplicate_extruder_temp_offset = 0; // used in mode 2
+bool extruder_duplication_enabled = false; // used in mode 2
+#endif //DUAL_X_CARRIAGE    
 
 static void axis_is_at_home(int axis) {
 #ifdef DUAL_X_CARRIAGE
-  if (axis == X_AXIS && active_extruder != 0) {
-    current_position[X_AXIS] = x_home_pos(active_extruder);
-    min_pos[X_AXIS] =          X2_MIN_POS;
-    max_pos[X_AXIS] =          max(extruder_offset[X_AXIS][1], X2_MAX_POS);
-    return;
+  if (axis == X_AXIS) {
+    if (active_extruder != 0) {
+      current_position[X_AXIS] = x_home_pos(active_extruder);
+      min_pos[X_AXIS] =          X2_MIN_POS;
+      max_pos[X_AXIS] =          max(extruder_offset[X_AXIS][1], X2_MAX_POS);
+      return;
+    }
+    else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0) {
+      current_position[X_AXIS] = base_home_pos(X_AXIS) + add_homeing[X_AXIS];
+      min_pos[X_AXIS] =          base_min_pos(X_AXIS) + add_homeing[X_AXIS]; 
+      max_pos[X_AXIS] =          min(base_max_pos(X_AXIS) + add_homeing[X_AXIS], 
+                                  max(extruder_offset[X_AXIS][1], X2_MAX_POS) - duplicate_extruder_x_offset);
+      return;
+    }
   }
 #endif
   current_position[axis] = base_home_pos(axis) + add_homeing[axis];
@@ -869,7 +896,7 @@ void process_commands()
       for(int8_t i=0; i < NUM_AXIS; i++) {
         destination[i] = current_position[i];
       }
-          feedrate = 0.0;
+      feedrate = 0.0;
 
 #ifdef DELTA
           // A delta can only safely home all axis at the same time
@@ -920,6 +947,7 @@ void process_commands()
         int x_axis_home_dir = home_dir(X_AXIS);
        #else
         int x_axis_home_dir = x_home_dir(active_extruder);
+        extruder_duplication_enabled = false;
        #endif
 
         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
@@ -950,12 +978,19 @@ void process_commands()
       {
       #ifdef DUAL_X_CARRIAGE
         int tmp_extruder = active_extruder;
+        extruder_duplication_enabled = false;
         active_extruder = !active_extruder;
         HOMEAXIS(X);
-        inactive_x_carriage_pos = current_position[X_AXIS];
+        inactive_extruder_x_pos = current_position[X_AXIS];
         active_extruder = tmp_extruder;
-      #endif
         HOMEAXIS(X);
+        // reset state used by the different modes
+        memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
+        delayed_move_time = 0;
+        active_extruder_parked = true; 
+      #else      
+        HOMEAXIS(X);
+      #endif         
       }
 
       if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) {
@@ -1199,6 +1234,10 @@ void process_commands()
         break;
       }
       if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder);
+#ifdef DUAL_X_CARRIAGE
+      if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
+        setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
+#endif          
       setWatch();
       break;
     case 140: // M140 set bed temp
@@ -1252,9 +1291,17 @@ void process_commands()
       #endif
       if (code_seen('S')) {
         setTargetHotend(code_value(), tmp_extruder);
+#ifdef DUAL_X_CARRIAGE
+        if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
+          setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
+#endif          
         CooldownNoWait = true;
       } else if (code_seen('R')) {
         setTargetHotend(code_value(), tmp_extruder);
+#ifdef DUAL_X_CARRIAGE
+        if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
+          setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
+#endif          
         CooldownNoWait = false;
       }
       #ifdef AUTOTEMP
@@ -1671,6 +1718,12 @@ void process_commands()
       {
         extruder_offset[Y_AXIS][tmp_extruder] = code_value();
       }
+      #ifdef DUAL_X_CARRIAGE
+      if(code_seen('Z'))
+      {
+        extruder_offset[Z_AXIS][tmp_extruder] = code_value();
+      }
+      #endif       
       SERIAL_ECHO_START;
       SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
       for(tmp_extruder = 0; tmp_extruder < EXTRUDERS; tmp_extruder++)
@@ -1679,6 +1732,10 @@ void process_commands()
          SERIAL_ECHO(extruder_offset[X_AXIS][tmp_extruder]);
          SERIAL_ECHO(",");
          SERIAL_ECHO(extruder_offset[Y_AXIS][tmp_extruder]);
+      #ifdef DUAL_X_CARRIAGE
+         SERIAL_ECHO(",");
+         SERIAL_ECHO(extruder_offset[Z_AXIS][tmp_extruder]);
+      #endif
       }
       SERIAL_ECHOLN("");
     }break;
@@ -2013,6 +2070,53 @@ void process_commands()
     }
     break;
     #endif //FILAMENTCHANGEENABLE
+    #ifdef DUAL_X_CARRIAGE
+    case 605: // Set dual x-carriage movement mode:
+              //    M605 S0: Full control mode. The slicer has full control over x-carriage movement
+              //    M605 S1: Auto-park mode. The inactive head will auto park/unpark without slicer involvement
+              //    M605 S2 [Xnnn] [Rmmm]: Duplication mode. The second extruder will duplicate the first with nnn
+              //                         millimeters x-offset and an optional differential hotend temperature of 
+              //                         mmm degrees. E.g., with "M605 S2 X100 R2" the second extruder will duplicate
+              //                         the first with a spacing of 100mm in the x direction and 2 degrees hotter.
+              //
+              //    Note: the X axis should be homed after changing dual x-carriage mode.
+    {
+        st_synchronize();
+        
+        if (code_seen('S'))
+          dual_x_carriage_mode = code_value();
+
+        if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
+        {
+          if (code_seen('X'))
+            duplicate_extruder_x_offset = max(code_value(),X2_MIN_POS - x_home_pos(0));
+
+          if (code_seen('R'))
+            duplicate_extruder_temp_offset = code_value();
+            
+          SERIAL_ECHO_START;
+          SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
+          SERIAL_ECHO(" ");
+          SERIAL_ECHO(extruder_offset[X_AXIS][0]);
+          SERIAL_ECHO(",");
+          SERIAL_ECHO(extruder_offset[Y_AXIS][0]);
+          SERIAL_ECHO(" ");
+          SERIAL_ECHO(duplicate_extruder_x_offset);
+          SERIAL_ECHO(",");
+          SERIAL_ECHOLN(extruder_offset[Y_AXIS][1]);
+        }
+        else if (dual_x_carriage_mode != DXC_FULL_CONTROL_MODE && dual_x_carriage_mode != DXC_AUTO_PARK_MODE)
+        {
+          dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
+        }
+        
+        active_extruder_parked = false;
+        extruder_duplication_enabled = false;
+        delayed_move_time = 0;
+    }
+    break;
+    #endif //DUAL_X_CARRIAGE         
+
     case 907: // M907 Set digital trimpot motor current using axis codes.
     {
       #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
@@ -2092,19 +2196,56 @@ void process_commands()
         // Save current position to return to after applying extruder offset
         memcpy(destination, current_position, sizeof(destination));
       #ifdef DUAL_X_CARRIAGE
-        // only apply Y extruder offset in dual x carriage mode (x offset is already used in determining home pos)
+        if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && Stopped == false && 
+            (delayed_move_time != 0 || current_position[X_AXIS] != x_home_pos(active_extruder)))
+        {
+          // Park old head: 1) raise 2) move to park position 3) lower
+          plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT, 
+                current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
+          plan_buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT, 
+                current_position[E_AXIS], max_feedrate[X_AXIS], active_extruder);
+          plan_buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS], 
+                current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
+          st_synchronize();
+        }
+        
+        // apply Y & Z extruder offset (x offset is already used in determining home pos)
         current_position[Y_AXIS] = current_position[Y_AXIS] -
                      extruder_offset[Y_AXIS][active_extruder] +
                      extruder_offset[Y_AXIS][tmp_extruder];
+        current_position[Z_AXIS] = current_position[Z_AXIS] -
+                     extruder_offset[Z_AXIS][active_extruder] +
+                     extruder_offset[Z_AXIS][tmp_extruder];
+                     
+        active_extruder = tmp_extruder;
 
-        float tmp_x_pos = current_position[X_AXIS];
+        // This function resets the max/min values - the current position may be overwritten below.
+        axis_is_at_home(X_AXIS);
 
-        // Set the new active extruder and position
-        active_extruder = tmp_extruder;
-        axis_is_at_home(X_AXIS); //this function updates X min/max values.
-        current_position[X_AXIS] = inactive_x_carriage_pos;
-        inactive_x_carriage_pos = tmp_x_pos;
-      #else
+        if (dual_x_carriage_mode == DXC_FULL_CONTROL_MODE)
+        {
+          current_position[X_AXIS] = inactive_extruder_x_pos; 
+          inactive_extruder_x_pos = destination[X_AXIS];
+        }
+        else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
+        {
+          active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
+          if (active_extruder == 0 || active_extruder_parked)
+            current_position[X_AXIS] = inactive_extruder_x_pos; 
+          else
+            current_position[X_AXIS] = destination[X_AXIS] + duplicate_extruder_x_offset; 
+          inactive_extruder_x_pos = destination[X_AXIS];
+          extruder_duplication_enabled = false; 
+        }
+        else
+        {
+          // record raised toolhead position for use by unpark
+          memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
+          raised_parked_position[Z_AXIS] += TOOLCHANGE_UNPARK_ZLIFT;
+          active_extruder_parked = true;
+          delayed_move_time = 0;
+        }
+      #else    
         // Offset extruder (only by XY)
         int i;
         for(i = 0; i < 2; i++) {
@@ -2309,6 +2450,48 @@ void prepare_move()
                      active_extruder);
   }
 #else
+
+#ifdef DUAL_X_CARRIAGE
+  if (active_extruder_parked)
+  {
+    if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0)
+    {
+      // move duplicate extruder into correct duplication position.
+      plan_set_position(inactive_extruder_x_pos, current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+      plan_buffer_line(current_position[X_AXIS] + duplicate_extruder_x_offset, current_position[Y_AXIS], current_position[Z_AXIS], 
+          current_position[E_AXIS], max_feedrate[X_AXIS], 1);
+      plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+      st_synchronize();
+      extruder_duplication_enabled = true;
+      active_extruder_parked = false;
+    }  
+    else if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE) // handle unparking of head
+    {
+      if (current_position[E_AXIS] == destination[E_AXIS])
+      {
+        // this is a travel move - skit it but keep track of current position (so that it can later
+        // be used as start of first non-travel move)
+        if (delayed_move_time != 0xFFFFFFFFUL)
+        {
+          memcpy(current_position, destination, sizeof(current_position)); 
+          if (destination[Z_AXIS] > raised_parked_position[Z_AXIS])
+            raised_parked_position[Z_AXIS] = destination[Z_AXIS];
+          delayed_move_time = millis();
+          return;
+        }
+      }
+      delayed_move_time = 0;
+      // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower
+      plan_buffer_line(raised_parked_position[X_AXIS], raised_parked_position[Y_AXIS], raised_parked_position[Z_AXIS],    current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
+      plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], raised_parked_position[Z_AXIS], 
+          current_position[E_AXIS], min(max_feedrate[X_AXIS],max_feedrate[Y_AXIS]), active_extruder);
+      plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], 
+          current_position[E_AXIS], max_feedrate[Z_AXIS], active_extruder);
+      active_extruder_parked = false;
+    }
+  }
+#endif //DUAL_X_CARRIAGE
+
   // Do not use feedmultiply for E or Z only moves
   if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) {
       plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
@@ -2316,7 +2499,7 @@ void prepare_move()
   else {
     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder);
   }
-#endif
+#endif //else DELTA
   for(int8_t i=0; i < NUM_AXIS; i++) {
     current_position[i] = destination[i];
   }
@@ -2428,6 +2611,16 @@ void manage_inactivity()
      WRITE(E0_ENABLE_PIN,oldstatus);
     }
   #endif
+  #if defined(DUAL_X_CARRIAGE)
+    // handle delayed move timeout
+    if (delayed_move_time != 0 && (millis() - delayed_move_time) > 1000 && Stopped == false)
+    {
+      // travel moves have been received so enact them
+      delayed_move_time = 0xFFFFFFFFUL; // force moves to be done
+      memcpy(destination,current_position,sizeof(destination));
+      prepare_move(); 
+    }
+  #endif  
   check_axes_activity();
 }
 
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index 0ba1001395752379e0cf156e07374f4bac32ae6e..7d738ac5e944b07d3bbcace67a11fa7ee559380a 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -349,20 +349,36 @@ ISR(TIMER1_COMPA_vect)
     // Set the direction bits (X_AXIS=A_AXIS and Y_AXIS=B_AXIS for COREXY)
     if((out_bits & (1<<X_AXIS))!=0){
       #ifdef DUAL_X_CARRIAGE
-      if (active_extruder != 0)
-        WRITE(X2_DIR_PIN,INVERT_X_DIR);
-      else
-      #endif
+        if (extruder_duplication_enabled){
+          WRITE(X_DIR_PIN, INVERT_X_DIR);
+          WRITE(X2_DIR_PIN, INVERT_X_DIR);
+        }
+        else{
+          if (current_block->active_extruder != 0)
+            WRITE(X2_DIR_PIN, INVERT_X_DIR);
+          else
+            WRITE(X_DIR_PIN, INVERT_X_DIR);
+        }
+      #else
         WRITE(X_DIR_PIN, INVERT_X_DIR);
+      #endif        
       count_direction[X_AXIS]=-1;
     }
     else{
       #ifdef DUAL_X_CARRIAGE
-      if (active_extruder != 0)
-        WRITE(X2_DIR_PIN,!INVERT_X_DIR);
-      else
-      #endif
+        if (extruder_duplication_enabled){
+          WRITE(X_DIR_PIN, !INVERT_X_DIR);
+          WRITE(X2_DIR_PIN, !INVERT_X_DIR);
+        }
+        else{
+          if (current_block->active_extruder != 0)
+            WRITE(X2_DIR_PIN, !INVERT_X_DIR);
+          else
+            WRITE(X_DIR_PIN, !INVERT_X_DIR);
+        }
+      #else
         WRITE(X_DIR_PIN, !INVERT_X_DIR);
+      #endif        
       count_direction[X_AXIS]=1;
     }
     if((out_bits & (1<<Y_AXIS))!=0){
@@ -384,8 +400,9 @@ ISR(TIMER1_COMPA_vect)
       {
         #ifdef DUAL_X_CARRIAGE
         // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
-        if ((active_extruder == 0 && X_HOME_DIR == -1) || (active_extruder != 0 && X2_HOME_DIR == -1))
-        #endif
+        if ((current_block->active_extruder == 0 && X_HOME_DIR == -1) 
+            || (current_block->active_extruder != 0 && X2_HOME_DIR == -1))
+        #endif          
         {
           #if defined(X_MIN_PIN) && X_MIN_PIN > -1
             bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING);
@@ -404,8 +421,9 @@ ISR(TIMER1_COMPA_vect)
       {
         #ifdef DUAL_X_CARRIAGE
         // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
-        if ((active_extruder == 0 && X_HOME_DIR == 1) || (active_extruder != 0 && X2_HOME_DIR == 1))
-        #endif
+        if ((current_block->active_extruder == 0 && X_HOME_DIR == 1) 
+            || (current_block->active_extruder != 0 && X2_HOME_DIR == 1))
+        #endif          
         {
           #if defined(X_MAX_PIN) && X_MAX_PIN > -1
             bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING);
@@ -455,8 +473,8 @@ ISR(TIMER1_COMPA_vect)
 
     if ((out_bits & (1<<Z_AXIS)) != 0) {   // -direction
       WRITE(Z_DIR_PIN,INVERT_Z_DIR);
-
-	  #ifdef Z_DUAL_STEPPER_DRIVERS
+      
+      #ifdef Z_DUAL_STEPPER_DRIVERS
         WRITE(Z2_DIR_PIN,INVERT_Z_DIR);
       #endif
 
@@ -477,7 +495,7 @@ ISR(TIMER1_COMPA_vect)
     else { // +direction
       WRITE(Z_DIR_PIN,!INVERT_Z_DIR);
 
-	  #ifdef Z_DUAL_STEPPER_DRIVERS
+      #ifdef Z_DUAL_STEPPER_DRIVERS
         WRITE(Z2_DIR_PIN,!INVERT_Z_DIR);
       #endif
 
@@ -529,20 +547,36 @@ ISR(TIMER1_COMPA_vect)
 
         counter_x += current_block->steps_x;
         if (counter_x > 0) {
-          #ifdef DUAL_X_CARRIAGE
-          if (active_extruder != 0)
-            WRITE(X2_STEP_PIN,!INVERT_X_STEP_PIN);
-          else
-          #endif
+        #ifdef DUAL_X_CARRIAGE
+          if (extruder_duplication_enabled){
             WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
+            WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
+          }
+          else {
+            if (current_block->active_extruder != 0)
+              WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
+            else
+              WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
+          }
+        #else
+          WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
+        #endif        
           counter_x -= current_block->step_event_count;
-          count_position[X_AXIS]+=count_direction[X_AXIS];
-          #ifdef DUAL_X_CARRIAGE
-          if (active_extruder != 0)
-            WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
-          else
-          #endif
+          count_position[X_AXIS]+=count_direction[X_AXIS];   
+        #ifdef DUAL_X_CARRIAGE
+          if (extruder_duplication_enabled){
             WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
+            WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
+          }
+          else {
+            if (current_block->active_extruder != 0)
+              WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
+            else
+              WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
+          }
+        #else
+          WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
+        #endif
         }
 
         counter_y += current_block->steps_y;
@@ -556,16 +590,16 @@ ISR(TIMER1_COMPA_vect)
       counter_z += current_block->steps_z;
       if (counter_z > 0) {
         WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN);
-
-		#ifdef Z_DUAL_STEPPER_DRIVERS
+        
+        #ifdef Z_DUAL_STEPPER_DRIVERS
           WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN);
         #endif
 
         counter_z -= current_block->step_event_count;
         count_position[Z_AXIS]+=count_direction[Z_AXIS];
         WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN);
-
-		#ifdef Z_DUAL_STEPPER_DRIVERS
+        
+        #ifdef Z_DUAL_STEPPER_DRIVERS
           WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN);
         #endif
       }
diff --git a/Marlin/stepper.h b/Marlin/stepper.h
index 6e60a332e7093f4fd6110b0526f9eabeca19320e..ac9dd8af592bbb67155736ec80c159774d05066e 100644
--- a/Marlin/stepper.h
+++ b/Marlin/stepper.h
@@ -28,9 +28,16 @@
   #define NORM_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}}
   #define REV_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}}
 #elif EXTRUDERS > 1
-  #define WRITE_E_STEP(v) { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
-  #define NORM_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
-  #define REV_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
+  #ifndef DUAL_X_CARRIAGE
+    #define WRITE_E_STEP(v) { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
+    #define NORM_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
+    #define REV_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
+  #else
+    extern bool extruder_duplication_enabled;
+    #define WRITE_E_STEP(v) { if(extruder_duplication_enabled) { WRITE(E0_STEP_PIN, v); WRITE(E1_STEP_PIN, v); } else if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
+    #define NORM_E_DIR() { if(extruder_duplication_enabled) { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
+    #define REV_E_DIR() { if(extruder_duplication_enabled) { WRITE(E0_DIR_PIN, INVERT_E0_DIR); WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
+  #endif  
 #else
   #define WRITE_E_STEP(v) WRITE(E0_STEP_PIN, v)
   #define NORM_E_DIR() WRITE(E0_DIR_PIN, !INVERT_E0_DIR)