From 7ee275b620fa055bb2b7516cf302ac3e531438ac Mon Sep 17 00:00:00 2001
From: Richard Miles <github@fast-chat.couk>
Date: Tue, 17 Sep 2013 19:02:00 +0100
Subject: [PATCH 1/4] Added Y_DUAL_STEPPER_DRIVERS

Enables two stepper drivers to be used for the Y axis (useful for
Shapeoko style machines)
Each Y driver can be stepped either the same way or in opposite
directions, accounting for different hardware setups (leadscrew vs. belt
driven)
---
 Marlin/Configuration_adv.h |  73 +++++++-
 Marlin/Marlin.h            |  30 ++-
 Marlin/stepper.cpp         | 368 ++++++++++++++++++++++++-------------
 3 files changed, 326 insertions(+), 145 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 5f1c77a056..648a9beafc 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -18,12 +18,6 @@
 //#define WATCH_TEMP_PERIOD 40000 //40 seconds
 //#define WATCH_TEMP_INCREASE 10  //Heat up at least 10 degree in 20 seconds
 
-// Wait for Cooldown
-// This defines if the M109 call should not block if it is cooling down.
-// example: From a current temp of 220, you set M109 S200. 
-// if CooldownNoWait is defined M109 will not wait for the cooldown to finish
-#define CooldownNoWait true
-
 #ifdef PIDTEMP
   // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed.
   // if Kc is choosen well, the additional required power due to increased melting should be compensated.
@@ -152,6 +146,68 @@
   #define EXTRUDERS 1
 #endif
 
+// Same again but for Y Axis.
+#define Y_DUAL_STEPPER_DRIVERS
+
+// Define if the two Y drives need to rotate in opposite directions
+#define INVERT_Y2_VS_Y_DIR true
+
+#ifdef Y_DUAL_STEPPER_DRIVERS
+  #undef EXTRUDERS
+  #define EXTRUDERS 1
+#endif
+
+#ifdef Z_DUAL_STEPPER_DRIVERS && Y_DUAL_STEPPER_DRIVERS
+  #error "You cannot have dual drivers for both Y and Z"
+#endif 
+
+// Enable this for dual x-carriage printers. 
+// A dual x-carriage design has the advantage that the inactive extruder can be parked which
+// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
+// allowing faster printing speeds.
+//#define DUAL_X_CARRIAGE
+#ifdef DUAL_X_CARRIAGE
+// 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 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 
+    // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
+    // without modifying the firmware (through the "M218 T1 X???" command).
+    // Remember: you should set the second extruder x-offset to 0 in your slicer.
+
+// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
+#define X2_ENABLE_PIN 29
+#define X2_STEP_PIN 25
+#define X2_DIR_PIN 23
+
+// 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 
 #define Y_HOME_RETRACT_MM 5 
@@ -174,6 +230,11 @@
 #define DEFAULT_MINIMUMFEEDRATE       0.0     // minimum feedrate
 #define DEFAULT_MINTRAVELFEEDRATE     0.0
 
+// Feedrates for manual moves along X, Y, Z, E from panel
+#ifdef ULTIPANEL
+#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60}  // set the speeds for manual moves (mm/min)
+#endif
+
 // minimum time in microseconds that a movement needs to take if the buffer is emptied.
 #define DEFAULT_MINSEGMENTTIME        20000
 
diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index c9759eb219..3066017966 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -51,22 +51,22 @@
   #define MYSERIAL MSerial
 #endif
 
-#define SERIAL_PROTOCOL(x) MYSERIAL.print(x);
-#define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y);
-#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x));
-#define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');}
-#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(PSTR(x));MYSERIAL.write('\n');}
+#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x))
+#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y))
+#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x)))
+#define SERIAL_PROTOCOLLN(x) (MYSERIAL.print(x),MYSERIAL.write('\n'))
+#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.write('\n'))
 
 
 const char errormagic[] PROGMEM ="Error:";
 const char echomagic[] PROGMEM ="echo:";
-#define SERIAL_ERROR_START serialprintPGM(errormagic);
+#define SERIAL_ERROR_START (serialprintPGM(errormagic))
 #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x)
 #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x)
 #define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x)
 #define SERIAL_ERRORLNPGM(x) SERIAL_PROTOCOLLNPGM(x)
 
-#define SERIAL_ECHO_START serialprintPGM(echomagic);
+#define SERIAL_ECHO_START (serialprintPGM(echomagic))
 #define SERIAL_ECHO(x) SERIAL_PROTOCOL(x)
 #define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x)
 #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x)
@@ -96,7 +96,11 @@ void process_commands();
 
 void manage_inactivity();
 
-#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
+#if defined(DUAL_X_CARRIAGE) && defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 \
+    && defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
+  #define  enable_x() do { WRITE(X_ENABLE_PIN, X_ENABLE_ON); WRITE(X2_ENABLE_PIN, X_ENABLE_ON); } while (0)
+  #define disable_x() do { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); WRITE(X2_ENABLE_PIN,!X_ENABLE_ON); } while (0)
+#elif defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
   #define  enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
   #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON)
 #else
@@ -105,8 +109,13 @@ void manage_inactivity();
 #endif
 
 #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
-  #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
-  #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
+  #ifdef Y_DUAL_STEPPER_DRIVERS
+    #define  enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN,  Y_ENABLE_ON); }
+    #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); }
+  #else
+    #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
+    #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
+  #endif
 #else
   #define enable_y() ;
   #define disable_y() ;
@@ -159,6 +168,7 @@ void ClearToSend();
 void get_coordinates();
 #ifdef DELTA
 void calculate_delta(float cartesian[3]);
+extern float delta[3];
 #endif
 void prepare_move();
 void kill();
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index a7991501e9..217030217a 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -48,8 +48,8 @@ block_t *current_block;  // A pointer to the block currently being traced
 // Variables used by The Stepper Driver Interrupt
 static unsigned char out_bits;        // The next stepping-bits to be output
 static long counter_x,       // Counter variables for the bresenham line tracer
-            counter_y, 
-            counter_z,       
+            counter_y,
+            counter_z,
             counter_e;
 volatile static unsigned long step_events_completed; // The number of step events executed in the current block
 #ifdef ADVANCE
@@ -224,27 +224,27 @@ void enable_endstops(bool check)
 //   |               BLOCK 1            |      BLOCK 2          |    d
 //
 //                           time ----->
-// 
-//  The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates 
-//  first block->accelerate_until step_events_completed, then keeps going at constant speed until 
+//
+//  The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
+//  first block->accelerate_until step_events_completed, then keeps going at constant speed until
 //  step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
 //  The slope of acceleration is calculated with the leib ramp alghorithm.
 
 void st_wake_up() {
   //  TCNT1 = 0;
-  ENABLE_STEPPER_DRIVER_INTERRUPT();  
+  ENABLE_STEPPER_DRIVER_INTERRUPT();
 }
 
 void step_wait(){
     for(int8_t i=0; i < 6; i++){
     }
 }
-  
+
 
 FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
   unsigned short timer;
   if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;
-  
+
   if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times
     step_rate = (step_rate >> 2)&0x3fff;
     step_loops = 4;
@@ -255,11 +255,11 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
   }
   else {
     step_loops = 1;
-  } 
-  
+  }
+
   if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000);
   step_rate -= (F_CPU/500000); // Correct for minimal speed
-  if(step_rate >= (8*256)){ // higher step rate 
+  if(step_rate >= (8*256)){ // higher step rate
     unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
     unsigned char tmp_step_rate = (step_rate & 0x00ff);
     unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);
@@ -276,7 +276,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
   return timer;
 }
 
-// Initializes the trapezoid generator from the current block. Called whenever a new 
+// Initializes the trapezoid generator from the current block. Called whenever a new
 // block begins.
 FORCE_INLINE void trapezoid_generator_reset() {
   #ifdef ADVANCE
@@ -284,7 +284,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
     final_advance = current_block->final_advance;
     // Do E steps + advance steps
     e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-    old_advance = advance >>8;  
+    old_advance = advance >>8;
   #endif
   deceleration_time = 0;
   // step_rate to timer interval
@@ -294,7 +294,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
   acc_step_rate = current_block->initial_rate;
   acceleration_time = calc_timer(acc_step_rate);
   OCR1A = acceleration_time;
-  
+
 //    SERIAL_ECHO_START;
 //    SERIAL_ECHOPGM("advance :");
 //    SERIAL_ECHO(current_block->advance/256.0);
@@ -304,13 +304,13 @@ FORCE_INLINE void trapezoid_generator_reset() {
 //  SERIAL_ECHO(current_block->initial_advance/256.0);
 //    SERIAL_ECHOPGM("final advance :");
 //    SERIAL_ECHOLN(current_block->final_advance/256.0);
-    
+
 }
 
-// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.  
-// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. 
+// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
+// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
 ISR(TIMER1_COMPA_vect)
-{    
+{
   // If there is no current block, attempt to pop one from the buffer
   if (current_block == NULL) {
     // Anything in the buffer?
@@ -322,24 +322,24 @@ ISR(TIMER1_COMPA_vect)
       counter_y = counter_x;
       counter_z = counter_x;
       counter_e = counter_x;
-      step_events_completed = 0; 
-      
-      #ifdef Z_LATE_ENABLE 
+      step_events_completed = 0;
+
+      #ifdef Z_LATE_ENABLE
         if(current_block->steps_z > 0) {
           enable_z();
           OCR1A = 2000; //1ms wait
           return;
         }
       #endif
-      
+
 //      #ifdef ADVANCE
 //      e_steps[current_block->active_extruder] = 0;
 //      #endif
-    } 
+    }
     else {
         OCR1A=2000; // 1kHz.
-    }    
-  } 
+    }
+  }
 
   if (current_block != NULL) {
     // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt
@@ -348,22 +348,58 @@ 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){
-      WRITE(X_DIR_PIN, INVERT_X_DIR);
+      #ifdef DUAL_X_CARRIAGE
+        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{
-      WRITE(X_DIR_PIN, !INVERT_X_DIR);
+      #ifdef DUAL_X_CARRIAGE
+        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){
       WRITE(Y_DIR_PIN, INVERT_Y_DIR);
+	  
+	  #ifdef Y_DUAL_STEPPER_DRIVERS
+	    WRITE(Y2_DIR_PIN, !(INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
+	  #endif
+	  
       count_direction[Y_AXIS]=-1;
     }
     else{
       WRITE(Y_DIR_PIN, !INVERT_Y_DIR);
+	  
+	  #ifdef Y_DUAL_STEPPER_DRIVERS
+	    WRITE(Y2_DIR_PIN, (INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
+	  #endif
+	  
       count_direction[Y_AXIS]=1;
     }
-    
+
     // Set direction en check limit switches
     #ifndef COREXY
     if ((out_bits & (1<<X_AXIS)) != 0) {   // stepping along -X axis
@@ -372,29 +408,43 @@ ISR(TIMER1_COMPA_vect)
     #endif
       CHECK_ENDSTOPS
       {
-        #if defined(X_MIN_PIN) && X_MIN_PIN > -1
-          bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING);
-          if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
-            endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
-            endstop_x_hit=true;
-            step_events_completed = current_block->step_event_count;
-          }
-          old_x_min_endstop = x_min_endstop;
-        #endif
+        #ifdef DUAL_X_CARRIAGE
+        // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
+        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);
+            if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
+              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
+              endstop_x_hit=true;
+              step_events_completed = current_block->step_event_count;
+            }
+            old_x_min_endstop = x_min_endstop;
+          #endif
+        }
       }
     }
     else { // +direction
-      CHECK_ENDSTOPS 
+      CHECK_ENDSTOPS
       {
-        #if defined(X_MAX_PIN) && X_MAX_PIN > -1
-          bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING);
-          if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
-            endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
-            endstop_x_hit=true;
-            step_events_completed = current_block->step_event_count;
-          }
-          old_x_max_endstop = x_max_endstop;
-        #endif
+        #ifdef DUAL_X_CARRIAGE
+        // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
+        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);
+            if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
+              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
+              endstop_x_hit=true;
+              step_events_completed = current_block->step_event_count;
+            }
+            old_x_max_endstop = x_max_endstop;
+          #endif
+        }
       }
     }
 
@@ -406,7 +456,7 @@ ISR(TIMER1_COMPA_vect)
       CHECK_ENDSTOPS
       {
         #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
-          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING);
+          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING);
           if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
             endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
             endstop_y_hit=true;
@@ -420,7 +470,7 @@ ISR(TIMER1_COMPA_vect)
       CHECK_ENDSTOPS
       {
         #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
-          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING);
+          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING);
           if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
             endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
             endstop_y_hit=true;
@@ -434,15 +484,15 @@ 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
-      
+
       count_direction[Z_AXIS]=-1;
       CHECK_ENDSTOPS
       {
         #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
-          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING);
+          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
           if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) {
             endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
             endstop_z_hit=true;
@@ -455,7 +505,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
 
@@ -463,7 +513,7 @@ ISR(TIMER1_COMPA_vect)
       CHECK_ENDSTOPS
       {
         #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
-          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING);
+          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
           if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) {
             endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
             endstop_z_hit=true;
@@ -484,10 +534,10 @@ ISR(TIMER1_COMPA_vect)
         count_direction[E_AXIS]=1;
       }
     #endif //!ADVANCE
-    
 
-    
-    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) 
+
+
+    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
       #ifndef AT90USB
       MSerial.checkRx(); // Check for serial chars.
       #endif
@@ -502,38 +552,73 @@ ISR(TIMER1_COMPA_vect)
         else {
           e_steps[current_block->active_extruder]++;
         }
-      }    
+      }
       #endif //ADVANCE
 
         counter_x += current_block->steps_x;
         if (counter_x > 0) {
+        #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 (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;
         if (counter_y > 0) {
           WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN);
-          counter_y -= current_block->step_event_count; 
-          count_position[Y_AXIS]+=count_direction[Y_AXIS]; 
+		  
+		  #ifdef Y_DUAL_STEPPER_DRIVERS
+			WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN);
+		  #endif
+		  
+          counter_y -= current_block->step_event_count;
+          count_position[Y_AXIS]+=count_direction[Y_AXIS];
           WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN);
+		  
+		  #ifdef Y_DUAL_STEPPER_DRIVERS
+			WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN);
+		  #endif
         }
-  
+
       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
       }
@@ -547,17 +632,17 @@ ISR(TIMER1_COMPA_vect)
           WRITE_E_STEP(INVERT_E_STEP_PIN);
         }
       #endif //!ADVANCE
-      step_events_completed += 1;  
+      step_events_completed += 1;
       if(step_events_completed >= current_block->step_event_count) break;
     }
     // Calculare new timer value
     unsigned short timer;
     unsigned short step_rate;
     if (step_events_completed <= (unsigned long int)current_block->accelerate_until) {
-      
+
       MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
       acc_step_rate += current_block->initial_rate;
-      
+
       // upper limit
       if(acc_step_rate > current_block->nominal_rate)
         acc_step_rate = current_block->nominal_rate;
@@ -573,13 +658,13 @@ ISR(TIMER1_COMPA_vect)
         //if(advance > current_block->advance) advance = current_block->advance;
         // Do E steps + advance steps
         e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-        old_advance = advance >>8;  
-        
+        old_advance = advance >>8;
+
       #endif
-    } 
-    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {   
+    }
+    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
       MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
-      
+
       if(step_rate > acc_step_rate) { // Check step_rate stays positive
         step_rate = current_block->final_rate;
       }
@@ -602,7 +687,7 @@ ISR(TIMER1_COMPA_vect)
         if(advance < final_advance) advance = final_advance;
         // Do E steps + advance steps
         e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-        old_advance = advance >>8;  
+        old_advance = advance >>8;
       #endif //ADVANCE
     }
     else {
@@ -611,12 +696,12 @@ ISR(TIMER1_COMPA_vect)
       step_loops = step_loops_nominal;
     }
 
-    // If current block is finished, reset pointer 
+    // If current block is finished, reset pointer
     if (step_events_completed >= current_block->step_event_count) {
       current_block = NULL;
       plan_discard_current_block();
-    }   
-  } 
+    }
+  }
 }
 
 #ifdef ADVANCE
@@ -635,7 +720,7 @@ ISR(TIMER1_COMPA_vect)
           WRITE(E0_DIR_PIN, INVERT_E0_DIR);
           e_steps[0]++;
           WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
-        } 
+        }
         else if (e_steps[0] > 0) {
           WRITE(E0_DIR_PIN, !INVERT_E0_DIR);
           e_steps[0]--;
@@ -649,7 +734,7 @@ ISR(TIMER1_COMPA_vect)
           WRITE(E1_DIR_PIN, INVERT_E1_DIR);
           e_steps[1]++;
           WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
-        } 
+        }
         else if (e_steps[1] > 0) {
           WRITE(E1_DIR_PIN, !INVERT_E1_DIR);
           e_steps[1]--;
@@ -664,7 +749,7 @@ ISR(TIMER1_COMPA_vect)
           WRITE(E2_DIR_PIN, INVERT_E2_DIR);
           e_steps[2]++;
           WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
-        } 
+        }
         else if (e_steps[2] > 0) {
           WRITE(E2_DIR_PIN, !INVERT_E2_DIR);
           e_steps[2]--;
@@ -680,22 +765,29 @@ void st_init()
 {
   digipot_init(); //Initialize Digipot Motor Current
   microstep_init(); //Initialize Microstepping Pins
-  
+
   //Initialize Dir Pins
   #if defined(X_DIR_PIN) && X_DIR_PIN > -1
     SET_OUTPUT(X_DIR_PIN);
   #endif
-  #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 
-    SET_OUTPUT(Y_DIR_PIN);
+  #if defined(X2_DIR_PIN) && X2_DIR_PIN > -1
+    SET_OUTPUT(X2_DIR_PIN);
   #endif
-  #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 
+  #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1
+    SET_OUTPUT(Y_DIR_PIN);
+	
+	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1)
+	  SET_OUTPUT(Y2_DIR_PIN);
+	#endif
+  #endif
+  #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1
     SET_OUTPUT(Z_DIR_PIN);
 
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_DIR_PIN) && (Z2_DIR_PIN > -1)
       SET_OUTPUT(Z2_DIR_PIN);
     #endif
   #endif
-  #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 
+  #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1
     SET_OUTPUT(E0_DIR_PIN);
   #endif
   #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1)
@@ -711,14 +803,23 @@ void st_init()
     SET_OUTPUT(X_ENABLE_PIN);
     if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
   #endif
+  #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
+    SET_OUTPUT(X2_ENABLE_PIN);
+    if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH);
+  #endif
   #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
     SET_OUTPUT(Y_ENABLE_PIN);
     if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
+	
+	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1)
+	  SET_OUTPUT(Y2_ENABLE_PIN);
+	  if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH);
+	#endif
   #endif
   #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
     SET_OUTPUT(Z_ENABLE_PIN);
     if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);
-    
+
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_ENABLE_PIN) && (Z2_ENABLE_PIN > -1)
       SET_OUTPUT(Z2_ENABLE_PIN);
       if(!Z_ENABLE_ON) WRITE(Z2_ENABLE_PIN,HIGH);
@@ -738,62 +839,71 @@ void st_init()
   #endif
 
   //endstops and pullups
-  
+
   #if defined(X_MIN_PIN) && X_MIN_PIN > -1
-    SET_INPUT(X_MIN_PIN); 
+    SET_INPUT(X_MIN_PIN);
     #ifdef ENDSTOPPULLUP_XMIN
       WRITE(X_MIN_PIN,HIGH);
     #endif
   #endif
-      
+
   #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
-    SET_INPUT(Y_MIN_PIN); 
+    SET_INPUT(Y_MIN_PIN);
     #ifdef ENDSTOPPULLUP_YMIN
       WRITE(Y_MIN_PIN,HIGH);
     #endif
   #endif
-  
+
   #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
-    SET_INPUT(Z_MIN_PIN); 
+    SET_INPUT(Z_MIN_PIN);
     #ifdef ENDSTOPPULLUP_ZMIN
       WRITE(Z_MIN_PIN,HIGH);
     #endif
   #endif
-      
+
   #if defined(X_MAX_PIN) && X_MAX_PIN > -1
-    SET_INPUT(X_MAX_PIN); 
+    SET_INPUT(X_MAX_PIN);
     #ifdef ENDSTOPPULLUP_XMAX
       WRITE(X_MAX_PIN,HIGH);
     #endif
   #endif
-      
+
   #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
-    SET_INPUT(Y_MAX_PIN); 
+    SET_INPUT(Y_MAX_PIN);
     #ifdef ENDSTOPPULLUP_YMAX
       WRITE(Y_MAX_PIN,HIGH);
     #endif
   #endif
-  
+
   #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
-    SET_INPUT(Z_MAX_PIN); 
+    SET_INPUT(Z_MAX_PIN);
     #ifdef ENDSTOPPULLUP_ZMAX
       WRITE(Z_MAX_PIN,HIGH);
     #endif
   #endif
- 
+
 
   //Initialize Step Pins
-  #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) 
+  #if defined(X_STEP_PIN) && (X_STEP_PIN > -1)
     SET_OUTPUT(X_STEP_PIN);
     WRITE(X_STEP_PIN,INVERT_X_STEP_PIN);
     disable_x();
-  #endif  
-  #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) 
+  #endif
+  #if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1)
+    SET_OUTPUT(X2_STEP_PIN);
+    WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
+    disable_x();
+  #endif
+  #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1)
     SET_OUTPUT(Y_STEP_PIN);
     WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN);
+    #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1)
+      SET_OUTPUT(Y2_STEP_PIN);
+      WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN);
+    #endif
     disable_y();
-  #endif  
-  #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) 
+  #endif
+  #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1)
     SET_OUTPUT(Z_STEP_PIN);
     WRITE(Z_STEP_PIN,INVERT_Z_STEP_PIN);
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_STEP_PIN) && (Z2_STEP_PIN > -1)
@@ -801,33 +911,33 @@ void st_init()
       WRITE(Z2_STEP_PIN,INVERT_Z_STEP_PIN);
     #endif
     disable_z();
-  #endif  
-  #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) 
+  #endif
+  #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1)
     SET_OUTPUT(E0_STEP_PIN);
     WRITE(E0_STEP_PIN,INVERT_E_STEP_PIN);
     disable_e0();
-  #endif  
-  #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) 
+  #endif
+  #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1)
     SET_OUTPUT(E1_STEP_PIN);
     WRITE(E1_STEP_PIN,INVERT_E_STEP_PIN);
     disable_e1();
-  #endif  
-  #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) 
+  #endif
+  #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1)
     SET_OUTPUT(E2_STEP_PIN);
     WRITE(E2_STEP_PIN,INVERT_E_STEP_PIN);
     disable_e2();
-  #endif  
+  #endif
 
   // waveform generation = 0100 = CTC
   TCCR1B &= ~(1<<WGM13);
   TCCR1B |=  (1<<WGM12);
-  TCCR1A &= ~(1<<WGM11); 
+  TCCR1A &= ~(1<<WGM11);
   TCCR1A &= ~(1<<WGM10);
 
   // output mode = 00 (disconnected)
-  TCCR1A &= ~(3<<COM1A0); 
-  TCCR1A &= ~(3<<COM1B0); 
-  
+  TCCR1A &= ~(3<<COM1A0);
+  TCCR1A &= ~(3<<COM1B0);
+
   // Set the timer pre-scaler
   // Generally we use a divider of 8, resulting in a 2MHz timer
   // frequency on a 16MHz MCU. If you are going to change this, be
@@ -837,19 +947,19 @@ void st_init()
 
   OCR1A = 0x4000;
   TCNT1 = 0;
-  ENABLE_STEPPER_DRIVER_INTERRUPT();  
+  ENABLE_STEPPER_DRIVER_INTERRUPT();
 
   #ifdef ADVANCE
   #if defined(TCCR0A) && defined(WGM01)
     TCCR0A &= ~(1<<WGM01);
     TCCR0A &= ~(1<<WGM00);
-  #endif  
+  #endif
     e_steps[0] = 0;
     e_steps[1] = 0;
     e_steps[2] = 0;
     TIMSK0 |= (1<<OCIE0A);
   #endif //ADVANCE
-  
+
   enable_endstops(true); // Start with endstops active. After homing they can be disabled
   sei();
 }
@@ -893,13 +1003,13 @@ long st_get_position(uint8_t axis)
 
 void finishAndDisableSteppers()
 {
-  st_synchronize(); 
-  disable_x(); 
-  disable_y(); 
-  disable_z(); 
-  disable_e0(); 
-  disable_e1(); 
-  disable_e2(); 
+  st_synchronize();
+  disable_x();
+  disable_y();
+  disable_z();
+  disable_e0();
+  disable_e1();
+  disable_e2();
 }
 
 void quickStop()
@@ -926,10 +1036,10 @@ void digipot_init() //Initialize Digipot Motor Current
 {
   #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
     const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT;
-    
-    SPI.begin(); 
-    pinMode(DIGIPOTSS_PIN, OUTPUT);    
-    for(int i=0;i<=4;i++) 
+
+    SPI.begin();
+    pinMode(DIGIPOTSS_PIN, OUTPUT);
+    for(int i=0;i<=4;i++)
       //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]);
       digipot_current(i,digipot_motor_current[i]);
   #endif

From f4a59e4ce5987fafb1a4e849bc7fbcbb8d3bc920 Mon Sep 17 00:00:00 2001
From: Richard Miles <github@fast-chat.couk>
Date: Tue, 17 Sep 2013 19:05:49 +0100
Subject: [PATCH 2/4] Revert "Added Y_DUAL_STEPPER_DRIVERS"

This reverts commit 7ee275b620fa055bb2b7516cf302ac3e531438ac.
---
 Marlin/Configuration_adv.h |  73 +-------
 Marlin/Marlin.h            |  30 +--
 Marlin/stepper.cpp         | 366 +++++++++++++------------------------
 3 files changed, 144 insertions(+), 325 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 648a9beafc..5f1c77a056 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -18,6 +18,12 @@
 //#define WATCH_TEMP_PERIOD 40000 //40 seconds
 //#define WATCH_TEMP_INCREASE 10  //Heat up at least 10 degree in 20 seconds
 
+// Wait for Cooldown
+// This defines if the M109 call should not block if it is cooling down.
+// example: From a current temp of 220, you set M109 S200. 
+// if CooldownNoWait is defined M109 will not wait for the cooldown to finish
+#define CooldownNoWait true
+
 #ifdef PIDTEMP
   // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed.
   // if Kc is choosen well, the additional required power due to increased melting should be compensated.
@@ -146,68 +152,6 @@
   #define EXTRUDERS 1
 #endif
 
-// Same again but for Y Axis.
-#define Y_DUAL_STEPPER_DRIVERS
-
-// Define if the two Y drives need to rotate in opposite directions
-#define INVERT_Y2_VS_Y_DIR true
-
-#ifdef Y_DUAL_STEPPER_DRIVERS
-  #undef EXTRUDERS
-  #define EXTRUDERS 1
-#endif
-
-#ifdef Z_DUAL_STEPPER_DRIVERS && Y_DUAL_STEPPER_DRIVERS
-  #error "You cannot have dual drivers for both Y and Z"
-#endif 
-
-// Enable this for dual x-carriage printers. 
-// A dual x-carriage design has the advantage that the inactive extruder can be parked which
-// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
-// allowing faster printing speeds.
-//#define DUAL_X_CARRIAGE
-#ifdef DUAL_X_CARRIAGE
-// 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 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 
-    // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
-    // without modifying the firmware (through the "M218 T1 X???" command).
-    // Remember: you should set the second extruder x-offset to 0 in your slicer.
-
-// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
-#define X2_ENABLE_PIN 29
-#define X2_STEP_PIN 25
-#define X2_DIR_PIN 23
-
-// 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 
 #define Y_HOME_RETRACT_MM 5 
@@ -230,11 +174,6 @@
 #define DEFAULT_MINIMUMFEEDRATE       0.0     // minimum feedrate
 #define DEFAULT_MINTRAVELFEEDRATE     0.0
 
-// Feedrates for manual moves along X, Y, Z, E from panel
-#ifdef ULTIPANEL
-#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60}  // set the speeds for manual moves (mm/min)
-#endif
-
 // minimum time in microseconds that a movement needs to take if the buffer is emptied.
 #define DEFAULT_MINSEGMENTTIME        20000
 
diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index 3066017966..c9759eb219 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -51,22 +51,22 @@
   #define MYSERIAL MSerial
 #endif
 
-#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x))
-#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y))
-#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x)))
-#define SERIAL_PROTOCOLLN(x) (MYSERIAL.print(x),MYSERIAL.write('\n'))
-#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.write('\n'))
+#define SERIAL_PROTOCOL(x) MYSERIAL.print(x);
+#define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y);
+#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x));
+#define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');}
+#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(PSTR(x));MYSERIAL.write('\n');}
 
 
 const char errormagic[] PROGMEM ="Error:";
 const char echomagic[] PROGMEM ="echo:";
-#define SERIAL_ERROR_START (serialprintPGM(errormagic))
+#define SERIAL_ERROR_START serialprintPGM(errormagic);
 #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x)
 #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x)
 #define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x)
 #define SERIAL_ERRORLNPGM(x) SERIAL_PROTOCOLLNPGM(x)
 
-#define SERIAL_ECHO_START (serialprintPGM(echomagic))
+#define SERIAL_ECHO_START serialprintPGM(echomagic);
 #define SERIAL_ECHO(x) SERIAL_PROTOCOL(x)
 #define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x)
 #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x)
@@ -96,11 +96,7 @@ void process_commands();
 
 void manage_inactivity();
 
-#if defined(DUAL_X_CARRIAGE) && defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 \
-    && defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
-  #define  enable_x() do { WRITE(X_ENABLE_PIN, X_ENABLE_ON); WRITE(X2_ENABLE_PIN, X_ENABLE_ON); } while (0)
-  #define disable_x() do { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); WRITE(X2_ENABLE_PIN,!X_ENABLE_ON); } while (0)
-#elif defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
+#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
   #define  enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
   #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON)
 #else
@@ -109,13 +105,8 @@ void manage_inactivity();
 #endif
 
 #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
-  #ifdef Y_DUAL_STEPPER_DRIVERS
-    #define  enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN,  Y_ENABLE_ON); }
-    #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); }
-  #else
-    #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
-    #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
-  #endif
+  #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
+  #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
 #else
   #define enable_y() ;
   #define disable_y() ;
@@ -168,7 +159,6 @@ void ClearToSend();
 void get_coordinates();
 #ifdef DELTA
 void calculate_delta(float cartesian[3]);
-extern float delta[3];
 #endif
 void prepare_move();
 void kill();
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index 217030217a..a7991501e9 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -48,8 +48,8 @@ block_t *current_block;  // A pointer to the block currently being traced
 // Variables used by The Stepper Driver Interrupt
 static unsigned char out_bits;        // The next stepping-bits to be output
 static long counter_x,       // Counter variables for the bresenham line tracer
-            counter_y,
-            counter_z,
+            counter_y, 
+            counter_z,       
             counter_e;
 volatile static unsigned long step_events_completed; // The number of step events executed in the current block
 #ifdef ADVANCE
@@ -224,27 +224,27 @@ void enable_endstops(bool check)
 //   |               BLOCK 1            |      BLOCK 2          |    d
 //
 //                           time ----->
-//
-//  The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
-//  first block->accelerate_until step_events_completed, then keeps going at constant speed until
+// 
+//  The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates 
+//  first block->accelerate_until step_events_completed, then keeps going at constant speed until 
 //  step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
 //  The slope of acceleration is calculated with the leib ramp alghorithm.
 
 void st_wake_up() {
   //  TCNT1 = 0;
-  ENABLE_STEPPER_DRIVER_INTERRUPT();
+  ENABLE_STEPPER_DRIVER_INTERRUPT();  
 }
 
 void step_wait(){
     for(int8_t i=0; i < 6; i++){
     }
 }
-
+  
 
 FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
   unsigned short timer;
   if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;
-
+  
   if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times
     step_rate = (step_rate >> 2)&0x3fff;
     step_loops = 4;
@@ -255,11 +255,11 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
   }
   else {
     step_loops = 1;
-  }
-
+  } 
+  
   if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000);
   step_rate -= (F_CPU/500000); // Correct for minimal speed
-  if(step_rate >= (8*256)){ // higher step rate
+  if(step_rate >= (8*256)){ // higher step rate 
     unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
     unsigned char tmp_step_rate = (step_rate & 0x00ff);
     unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);
@@ -276,7 +276,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
   return timer;
 }
 
-// Initializes the trapezoid generator from the current block. Called whenever a new
+// Initializes the trapezoid generator from the current block. Called whenever a new 
 // block begins.
 FORCE_INLINE void trapezoid_generator_reset() {
   #ifdef ADVANCE
@@ -284,7 +284,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
     final_advance = current_block->final_advance;
     // Do E steps + advance steps
     e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-    old_advance = advance >>8;
+    old_advance = advance >>8;  
   #endif
   deceleration_time = 0;
   // step_rate to timer interval
@@ -294,7 +294,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
   acc_step_rate = current_block->initial_rate;
   acceleration_time = calc_timer(acc_step_rate);
   OCR1A = acceleration_time;
-
+  
 //    SERIAL_ECHO_START;
 //    SERIAL_ECHOPGM("advance :");
 //    SERIAL_ECHO(current_block->advance/256.0);
@@ -304,13 +304,13 @@ FORCE_INLINE void trapezoid_generator_reset() {
 //  SERIAL_ECHO(current_block->initial_advance/256.0);
 //    SERIAL_ECHOPGM("final advance :");
 //    SERIAL_ECHOLN(current_block->final_advance/256.0);
-
+    
 }
 
-// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
-// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
+// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.  
+// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. 
 ISR(TIMER1_COMPA_vect)
-{
+{    
   // If there is no current block, attempt to pop one from the buffer
   if (current_block == NULL) {
     // Anything in the buffer?
@@ -322,24 +322,24 @@ ISR(TIMER1_COMPA_vect)
       counter_y = counter_x;
       counter_z = counter_x;
       counter_e = counter_x;
-      step_events_completed = 0;
-
-      #ifdef Z_LATE_ENABLE
+      step_events_completed = 0; 
+      
+      #ifdef Z_LATE_ENABLE 
         if(current_block->steps_z > 0) {
           enable_z();
           OCR1A = 2000; //1ms wait
           return;
         }
       #endif
-
+      
 //      #ifdef ADVANCE
 //      e_steps[current_block->active_extruder] = 0;
 //      #endif
-    }
+    } 
     else {
         OCR1A=2000; // 1kHz.
-    }
-  }
+    }    
+  } 
 
   if (current_block != NULL) {
     // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt
@@ -348,58 +348,22 @@ 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 (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        
+      WRITE(X_DIR_PIN, INVERT_X_DIR);
       count_direction[X_AXIS]=-1;
     }
     else{
-      #ifdef DUAL_X_CARRIAGE
-        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        
+      WRITE(X_DIR_PIN, !INVERT_X_DIR);
       count_direction[X_AXIS]=1;
     }
     if((out_bits & (1<<Y_AXIS))!=0){
       WRITE(Y_DIR_PIN, INVERT_Y_DIR);
-	  
-	  #ifdef Y_DUAL_STEPPER_DRIVERS
-	    WRITE(Y2_DIR_PIN, !(INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
-	  #endif
-	  
       count_direction[Y_AXIS]=-1;
     }
     else{
       WRITE(Y_DIR_PIN, !INVERT_Y_DIR);
-	  
-	  #ifdef Y_DUAL_STEPPER_DRIVERS
-	    WRITE(Y2_DIR_PIN, (INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
-	  #endif
-	  
       count_direction[Y_AXIS]=1;
     }
-
+    
     // Set direction en check limit switches
     #ifndef COREXY
     if ((out_bits & (1<<X_AXIS)) != 0) {   // stepping along -X axis
@@ -408,43 +372,29 @@ ISR(TIMER1_COMPA_vect)
     #endif
       CHECK_ENDSTOPS
       {
-        #ifdef DUAL_X_CARRIAGE
-        // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
-        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);
-            if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
-              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
-              endstop_x_hit=true;
-              step_events_completed = current_block->step_event_count;
-            }
-            old_x_min_endstop = x_min_endstop;
-          #endif
-        }
+        #if defined(X_MIN_PIN) && X_MIN_PIN > -1
+          bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING);
+          if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
+            endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
+            endstop_x_hit=true;
+            step_events_completed = current_block->step_event_count;
+          }
+          old_x_min_endstop = x_min_endstop;
+        #endif
       }
     }
     else { // +direction
-      CHECK_ENDSTOPS
+      CHECK_ENDSTOPS 
       {
-        #ifdef DUAL_X_CARRIAGE
-        // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
-        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);
-            if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
-              endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
-              endstop_x_hit=true;
-              step_events_completed = current_block->step_event_count;
-            }
-            old_x_max_endstop = x_max_endstop;
-          #endif
-        }
+        #if defined(X_MAX_PIN) && X_MAX_PIN > -1
+          bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING);
+          if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
+            endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
+            endstop_x_hit=true;
+            step_events_completed = current_block->step_event_count;
+          }
+          old_x_max_endstop = x_max_endstop;
+        #endif
       }
     }
 
@@ -456,7 +406,7 @@ ISR(TIMER1_COMPA_vect)
       CHECK_ENDSTOPS
       {
         #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
-          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING);
+          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING);
           if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
             endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
             endstop_y_hit=true;
@@ -470,7 +420,7 @@ ISR(TIMER1_COMPA_vect)
       CHECK_ENDSTOPS
       {
         #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
-          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING);
+          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING);
           if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
             endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
             endstop_y_hit=true;
@@ -484,15 +434,15 @@ 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
-
+      
       count_direction[Z_AXIS]=-1;
       CHECK_ENDSTOPS
       {
         #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
-          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
+          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING);
           if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) {
             endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
             endstop_z_hit=true;
@@ -505,7 +455,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
 
@@ -513,7 +463,7 @@ ISR(TIMER1_COMPA_vect)
       CHECK_ENDSTOPS
       {
         #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
-          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
+          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING);
           if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) {
             endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
             endstop_z_hit=true;
@@ -534,10 +484,10 @@ ISR(TIMER1_COMPA_vect)
         count_direction[E_AXIS]=1;
       }
     #endif //!ADVANCE
+    
 
-
-
-    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
+    
+    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) 
       #ifndef AT90USB
       MSerial.checkRx(); // Check for serial chars.
       #endif
@@ -552,73 +502,38 @@ ISR(TIMER1_COMPA_vect)
         else {
           e_steps[current_block->active_extruder]++;
         }
-      }
+      }    
       #endif //ADVANCE
 
         counter_x += current_block->steps_x;
         if (counter_x > 0) {
-        #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 (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;
         if (counter_y > 0) {
           WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN);
-		  
-		  #ifdef Y_DUAL_STEPPER_DRIVERS
-			WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN);
-		  #endif
-		  
-          counter_y -= current_block->step_event_count;
-          count_position[Y_AXIS]+=count_direction[Y_AXIS];
+          counter_y -= current_block->step_event_count; 
+          count_position[Y_AXIS]+=count_direction[Y_AXIS]; 
           WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN);
-		  
-		  #ifdef Y_DUAL_STEPPER_DRIVERS
-			WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN);
-		  #endif
         }
-
+  
       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
       }
@@ -632,17 +547,17 @@ ISR(TIMER1_COMPA_vect)
           WRITE_E_STEP(INVERT_E_STEP_PIN);
         }
       #endif //!ADVANCE
-      step_events_completed += 1;
+      step_events_completed += 1;  
       if(step_events_completed >= current_block->step_event_count) break;
     }
     // Calculare new timer value
     unsigned short timer;
     unsigned short step_rate;
     if (step_events_completed <= (unsigned long int)current_block->accelerate_until) {
-
+      
       MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
       acc_step_rate += current_block->initial_rate;
-
+      
       // upper limit
       if(acc_step_rate > current_block->nominal_rate)
         acc_step_rate = current_block->nominal_rate;
@@ -658,13 +573,13 @@ ISR(TIMER1_COMPA_vect)
         //if(advance > current_block->advance) advance = current_block->advance;
         // Do E steps + advance steps
         e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-        old_advance = advance >>8;
-
+        old_advance = advance >>8;  
+        
       #endif
-    }
-    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
+    } 
+    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {   
       MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
-
+      
       if(step_rate > acc_step_rate) { // Check step_rate stays positive
         step_rate = current_block->final_rate;
       }
@@ -687,7 +602,7 @@ ISR(TIMER1_COMPA_vect)
         if(advance < final_advance) advance = final_advance;
         // Do E steps + advance steps
         e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-        old_advance = advance >>8;
+        old_advance = advance >>8;  
       #endif //ADVANCE
     }
     else {
@@ -696,12 +611,12 @@ ISR(TIMER1_COMPA_vect)
       step_loops = step_loops_nominal;
     }
 
-    // If current block is finished, reset pointer
+    // If current block is finished, reset pointer 
     if (step_events_completed >= current_block->step_event_count) {
       current_block = NULL;
       plan_discard_current_block();
-    }
-  }
+    }   
+  } 
 }
 
 #ifdef ADVANCE
@@ -720,7 +635,7 @@ ISR(TIMER1_COMPA_vect)
           WRITE(E0_DIR_PIN, INVERT_E0_DIR);
           e_steps[0]++;
           WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
+        } 
         else if (e_steps[0] > 0) {
           WRITE(E0_DIR_PIN, !INVERT_E0_DIR);
           e_steps[0]--;
@@ -734,7 +649,7 @@ ISR(TIMER1_COMPA_vect)
           WRITE(E1_DIR_PIN, INVERT_E1_DIR);
           e_steps[1]++;
           WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
+        } 
         else if (e_steps[1] > 0) {
           WRITE(E1_DIR_PIN, !INVERT_E1_DIR);
           e_steps[1]--;
@@ -749,7 +664,7 @@ ISR(TIMER1_COMPA_vect)
           WRITE(E2_DIR_PIN, INVERT_E2_DIR);
           e_steps[2]++;
           WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
+        } 
         else if (e_steps[2] > 0) {
           WRITE(E2_DIR_PIN, !INVERT_E2_DIR);
           e_steps[2]--;
@@ -765,29 +680,22 @@ void st_init()
 {
   digipot_init(); //Initialize Digipot Motor Current
   microstep_init(); //Initialize Microstepping Pins
-
+  
   //Initialize Dir Pins
   #if defined(X_DIR_PIN) && X_DIR_PIN > -1
     SET_OUTPUT(X_DIR_PIN);
   #endif
-  #if defined(X2_DIR_PIN) && X2_DIR_PIN > -1
-    SET_OUTPUT(X2_DIR_PIN);
-  #endif
-  #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1
+  #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 
     SET_OUTPUT(Y_DIR_PIN);
-	
-	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1)
-	  SET_OUTPUT(Y2_DIR_PIN);
-	#endif
   #endif
-  #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1
+  #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 
     SET_OUTPUT(Z_DIR_PIN);
 
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_DIR_PIN) && (Z2_DIR_PIN > -1)
       SET_OUTPUT(Z2_DIR_PIN);
     #endif
   #endif
-  #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1
+  #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 
     SET_OUTPUT(E0_DIR_PIN);
   #endif
   #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1)
@@ -803,23 +711,14 @@ void st_init()
     SET_OUTPUT(X_ENABLE_PIN);
     if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
   #endif
-  #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
-    SET_OUTPUT(X2_ENABLE_PIN);
-    if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH);
-  #endif
   #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
     SET_OUTPUT(Y_ENABLE_PIN);
     if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
-	
-	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1)
-	  SET_OUTPUT(Y2_ENABLE_PIN);
-	  if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH);
-	#endif
   #endif
   #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
     SET_OUTPUT(Z_ENABLE_PIN);
     if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);
-
+    
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_ENABLE_PIN) && (Z2_ENABLE_PIN > -1)
       SET_OUTPUT(Z2_ENABLE_PIN);
       if(!Z_ENABLE_ON) WRITE(Z2_ENABLE_PIN,HIGH);
@@ -839,71 +738,62 @@ void st_init()
   #endif
 
   //endstops and pullups
-
+  
   #if defined(X_MIN_PIN) && X_MIN_PIN > -1
-    SET_INPUT(X_MIN_PIN);
+    SET_INPUT(X_MIN_PIN); 
     #ifdef ENDSTOPPULLUP_XMIN
       WRITE(X_MIN_PIN,HIGH);
     #endif
   #endif
-
+      
   #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
-    SET_INPUT(Y_MIN_PIN);
+    SET_INPUT(Y_MIN_PIN); 
     #ifdef ENDSTOPPULLUP_YMIN
       WRITE(Y_MIN_PIN,HIGH);
     #endif
   #endif
-
+  
   #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
-    SET_INPUT(Z_MIN_PIN);
+    SET_INPUT(Z_MIN_PIN); 
     #ifdef ENDSTOPPULLUP_ZMIN
       WRITE(Z_MIN_PIN,HIGH);
     #endif
   #endif
-
+      
   #if defined(X_MAX_PIN) && X_MAX_PIN > -1
-    SET_INPUT(X_MAX_PIN);
+    SET_INPUT(X_MAX_PIN); 
     #ifdef ENDSTOPPULLUP_XMAX
       WRITE(X_MAX_PIN,HIGH);
     #endif
   #endif
-
+      
   #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
-    SET_INPUT(Y_MAX_PIN);
+    SET_INPUT(Y_MAX_PIN); 
     #ifdef ENDSTOPPULLUP_YMAX
       WRITE(Y_MAX_PIN,HIGH);
     #endif
   #endif
-
+  
   #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
-    SET_INPUT(Z_MAX_PIN);
+    SET_INPUT(Z_MAX_PIN); 
     #ifdef ENDSTOPPULLUP_ZMAX
       WRITE(Z_MAX_PIN,HIGH);
     #endif
   #endif
-
+ 
 
   //Initialize Step Pins
-  #if defined(X_STEP_PIN) && (X_STEP_PIN > -1)
+  #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) 
     SET_OUTPUT(X_STEP_PIN);
     WRITE(X_STEP_PIN,INVERT_X_STEP_PIN);
     disable_x();
-  #endif
-  #if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1)
-    SET_OUTPUT(X2_STEP_PIN);
-    WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
-    disable_x();
-  #endif
-  #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1)
+  #endif  
+  #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) 
     SET_OUTPUT(Y_STEP_PIN);
     WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN);
-    #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1)
-      SET_OUTPUT(Y2_STEP_PIN);
-      WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN);
-    #endif
     disable_y();
-  #endif
-  #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1)
+  #endif  
+  #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) 
     SET_OUTPUT(Z_STEP_PIN);
     WRITE(Z_STEP_PIN,INVERT_Z_STEP_PIN);
     #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_STEP_PIN) && (Z2_STEP_PIN > -1)
@@ -911,33 +801,33 @@ void st_init()
       WRITE(Z2_STEP_PIN,INVERT_Z_STEP_PIN);
     #endif
     disable_z();
-  #endif
-  #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1)
+  #endif  
+  #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) 
     SET_OUTPUT(E0_STEP_PIN);
     WRITE(E0_STEP_PIN,INVERT_E_STEP_PIN);
     disable_e0();
-  #endif
-  #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1)
+  #endif  
+  #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) 
     SET_OUTPUT(E1_STEP_PIN);
     WRITE(E1_STEP_PIN,INVERT_E_STEP_PIN);
     disable_e1();
-  #endif
-  #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1)
+  #endif  
+  #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) 
     SET_OUTPUT(E2_STEP_PIN);
     WRITE(E2_STEP_PIN,INVERT_E_STEP_PIN);
     disable_e2();
-  #endif
+  #endif  
 
   // waveform generation = 0100 = CTC
   TCCR1B &= ~(1<<WGM13);
   TCCR1B |=  (1<<WGM12);
-  TCCR1A &= ~(1<<WGM11);
+  TCCR1A &= ~(1<<WGM11); 
   TCCR1A &= ~(1<<WGM10);
 
   // output mode = 00 (disconnected)
-  TCCR1A &= ~(3<<COM1A0);
-  TCCR1A &= ~(3<<COM1B0);
-
+  TCCR1A &= ~(3<<COM1A0); 
+  TCCR1A &= ~(3<<COM1B0); 
+  
   // Set the timer pre-scaler
   // Generally we use a divider of 8, resulting in a 2MHz timer
   // frequency on a 16MHz MCU. If you are going to change this, be
@@ -947,19 +837,19 @@ void st_init()
 
   OCR1A = 0x4000;
   TCNT1 = 0;
-  ENABLE_STEPPER_DRIVER_INTERRUPT();
+  ENABLE_STEPPER_DRIVER_INTERRUPT();  
 
   #ifdef ADVANCE
   #if defined(TCCR0A) && defined(WGM01)
     TCCR0A &= ~(1<<WGM01);
     TCCR0A &= ~(1<<WGM00);
-  #endif
+  #endif  
     e_steps[0] = 0;
     e_steps[1] = 0;
     e_steps[2] = 0;
     TIMSK0 |= (1<<OCIE0A);
   #endif //ADVANCE
-
+  
   enable_endstops(true); // Start with endstops active. After homing they can be disabled
   sei();
 }
@@ -1003,13 +893,13 @@ long st_get_position(uint8_t axis)
 
 void finishAndDisableSteppers()
 {
-  st_synchronize();
-  disable_x();
-  disable_y();
-  disable_z();
-  disable_e0();
-  disable_e1();
-  disable_e2();
+  st_synchronize(); 
+  disable_x(); 
+  disable_y(); 
+  disable_z(); 
+  disable_e0(); 
+  disable_e1(); 
+  disable_e2(); 
 }
 
 void quickStop()
@@ -1036,10 +926,10 @@ void digipot_init() //Initialize Digipot Motor Current
 {
   #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
     const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT;
-
-    SPI.begin();
-    pinMode(DIGIPOTSS_PIN, OUTPUT);
-    for(int i=0;i<=4;i++)
+    
+    SPI.begin(); 
+    pinMode(DIGIPOTSS_PIN, OUTPUT);    
+    for(int i=0;i<=4;i++) 
       //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]);
       digipot_current(i,digipot_motor_current[i]);
   #endif

From ed1ab42186fd8631456e4d7c6b572bf0a2d124f7 Mon Sep 17 00:00:00 2001
From: Richard Miles <github@fast-chat.couk>
Date: Tue, 17 Sep 2013 19:19:20 +0100
Subject: [PATCH 3/4] Added Y_DUAL_STEPPER_DRIVERS

Enables two stepper drivers to be used for the Y axis (useful for
Shapeoko style machines)
Each Y driver can be stepped in either the same way or in opposite
directions, accounting for different hardware setups (leadscrew vs. belt
driven)
---
 Marlin/Configuration_adv.h | 15 +++++++++++++++
 Marlin/Marlin.h            |  9 +++++++--
 Marlin/stepper.cpp         | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 5f1c77a056..bd411a403b 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -152,6 +152,21 @@
   #define EXTRUDERS 1
 #endif
 
+// Same again but for Y Axis.
+#define Y_DUAL_STEPPER_DRIVERS
+
+// Define if the two Y drives need to rotate in opposite directions
+#define INVERT_Y2_VS_Y_DIR true
+
+#ifdef Y_DUAL_STEPPER_DRIVERS
+  #undef EXTRUDERS
+  #define EXTRUDERS 1
+#endif
+
+#ifdef Z_DUAL_STEPPER_DRIVERS && Y_DUAL_STEPPER_DRIVERS
+  #error "You cannot have dual drivers for both Y and Z"
+#endif 
+
 //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
 #define X_HOME_RETRACT_MM 5 
 #define Y_HOME_RETRACT_MM 5 
diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index c9759eb219..c4460e79f0 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -105,8 +105,13 @@ void manage_inactivity();
 #endif
 
 #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
-  #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
-  #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
+  #ifdef Y_DUAL_STEPPER_DRIVERS
+    #define  enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN,  Y_ENABLE_ON); }
+    #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); }
+  #else
+    #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
+    #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)
+  #endif
 #else
   #define enable_y() ;
   #define disable_y() ;
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index a7991501e9..10c41b9a62 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -357,10 +357,20 @@ ISR(TIMER1_COMPA_vect)
     }
     if((out_bits & (1<<Y_AXIS))!=0){
       WRITE(Y_DIR_PIN, INVERT_Y_DIR);
+	  
+	  #ifdef Y_DUAL_STEPPER_DRIVERS
+	    WRITE(Y2_DIR_PIN, !(INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
+	  #endif
+	  
       count_direction[Y_AXIS]=-1;
     }
     else{
       WRITE(Y_DIR_PIN, !INVERT_Y_DIR);
+	  
+	  #ifdef Y_DUAL_STEPPER_DRIVERS
+	    WRITE(Y2_DIR_PIN, (INVERT_Y_DIR == INVERT_Y2_VS_Y_DIR));
+	  #endif
+	  
       count_direction[Y_AXIS]=1;
     }
     
@@ -516,9 +526,18 @@ ISR(TIMER1_COMPA_vect)
         counter_y += current_block->steps_y;
         if (counter_y > 0) {
           WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN);
+		  
+		  #ifdef Y_DUAL_STEPPER_DRIVERS
+			WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN);
+		  #endif
+		  
           counter_y -= current_block->step_event_count; 
           count_position[Y_AXIS]+=count_direction[Y_AXIS]; 
           WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN);
+		  
+		  #ifdef Y_DUAL_STEPPER_DRIVERS
+			WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN);
+		  #endif
         }
   
       counter_z += current_block->steps_z;
@@ -687,6 +706,10 @@ void st_init()
   #endif
   #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 
     SET_OUTPUT(Y_DIR_PIN);
+		
+	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1)
+	  SET_OUTPUT(Y2_DIR_PIN);
+	#endif
   #endif
   #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 
     SET_OUTPUT(Z_DIR_PIN);
@@ -714,6 +737,11 @@ void st_init()
   #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
     SET_OUTPUT(Y_ENABLE_PIN);
     if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
+	
+	#if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1)
+	  SET_OUTPUT(Y2_ENABLE_PIN);
+	  if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH);
+	#endif
   #endif
   #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
     SET_OUTPUT(Z_ENABLE_PIN);
@@ -791,6 +819,10 @@ void st_init()
   #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) 
     SET_OUTPUT(Y_STEP_PIN);
     WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN);
+    #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1)
+      SET_OUTPUT(Y2_STEP_PIN);
+      WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN);
+    #endif
     disable_y();
   #endif  
   #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) 

From 77df2ab0e7e6253d2e1d975c76a9876ec46bd96b Mon Sep 17 00:00:00 2001
From: Richard Miles <github@fast-chat.couk>
Date: Tue, 17 Sep 2013 21:49:44 +0100
Subject: [PATCH 4/4] Make Y_DUAL_STEPPER_DRIVERS disabled by default

---
 Marlin/Configuration_adv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index bd411a403b..4747842479 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -153,7 +153,7 @@
 #endif
 
 // Same again but for Y Axis.
-#define Y_DUAL_STEPPER_DRIVERS
+//#define Y_DUAL_STEPPER_DRIVERS
 
 // Define if the two Y drives need to rotate in opposite directions
 #define INVERT_Y2_VS_Y_DIR true