diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index e14471264f..440a44a579 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -6,6 +6,7 @@
 #include <WProgram.h>
 #include "fastio.h"
 #include <avr/pgmspace.h>
+#include "Configuration.h"
 
 //#define SERIAL_ECHO(x) Serial << "echo: " << x;
 //#define SERIAL_ECHOLN(x) Serial << "echo: "<<x<<endl;
@@ -108,5 +109,6 @@ void enquecommand(const char *cmd); //put an ascii command at the end of the cur
 
 extern float homing_feedrate[];
 extern bool axis_relative_modes[];
+extern float current_position[NUM_AXIS] ;
 
 #endif
diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde
index 4c1ece07e3..e15f025514 100644
--- a/Marlin/Marlin.pde
+++ b/Marlin/Marlin.pde
@@ -39,7 +39,7 @@
 #include "cardreader.h"
 
 
-char version_string[] = "1.0.0 Alpha 1";
+#define VERSION_STRING  "1.0.0 Alpha 1"
 
 
 
@@ -99,6 +99,7 @@ char version_string[] = "1.0.0 Alpha 1";
 // M205 -  advanced settings:  minimum travel speed S=while printing T=travel only,  B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
 // M220 - set speed factor override percentage S:factor in percent
 // M301 - Set PID parameters P I and D
+// M400 - Finish all moves
 // M500 - stores paramters in EEPROM
 // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).  
 // M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
@@ -120,13 +121,14 @@ bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
 volatile int feedmultiply=100; //100->1 200->2
 int saved_feedmultiply;
 volatile bool feedmultiplychanged=false;
+float current_position[NUM_AXIS] = {  0.0, 0.0, 0.0, 0.0};
+
 
 //===========================================================================
 //=============================private variables=============================
 //===========================================================================
 const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
 static float destination[NUM_AXIS] = {  0.0, 0.0, 0.0, 0.0};
-static float current_position[NUM_AXIS] = {  0.0, 0.0, 0.0, 0.0};
 static float offset[3] = {0.0, 0.0, 0.0};
 static bool home_all_axis = true;
 static float feedrate = 1500.0, next_feedrate, saved_feedrate;
@@ -211,7 +213,7 @@ void setup()
 { 
   Serial.begin(BAUDRATE);
   SERIAL_ECHO_START;
-  SERIAL_ECHOLN(version_string);
+  SERIAL_ECHOLNPGM(VERSION_STRING);
   SERIAL_PROTOCOLLNPGM("start");
   SERIAL_ECHO_START;
   SERIAL_ECHOPGM("Free Memory:");
@@ -269,6 +271,7 @@ void loop()
   //check heater every n milliseconds
   manage_heater();
   manage_inactivity(1);
+  checkHitEndstops();
   LCD_STATUS;
 }
 
@@ -443,20 +446,25 @@ inline bool code_seen(char code)
     destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \
     feedrate = homing_feedrate[LETTER##_AXIS]; \
     prepare_move(); \
+    st_synchronize();\
     \
     current_position[LETTER##_AXIS] = 0;\
     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\
     destination[LETTER##_AXIS] = -5 * LETTER##_HOME_DIR;\
     prepare_move(); \
+    st_synchronize();\
     \
     destination[LETTER##_AXIS] = 10 * LETTER##_HOME_DIR;\
     feedrate = homing_feedrate[LETTER##_AXIS]/2 ;  \
     prepare_move(); \
+    st_synchronize();\
     \
     current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? 0 : LETTER##_MAX_LENGTH;\
     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\
     destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\
     feedrate = 0.0;\
+    st_synchronize();\
+    endstops_hit_on_purpose();\
   }
 
 inline void process_commands()
@@ -522,6 +530,7 @@ inline void process_commands()
       feedrate = saved_feedrate;
       feedmultiply = saved_feedmultiply;
       previous_millis_cmd = millis();
+      endstops_hit_on_purpose();
       break;
     case 90: // G90
       relative_mode = false;
@@ -909,6 +918,11 @@ inline void process_commands()
       
       break;
     #endif //PIDTEMP
+    case 400: // finish all moves
+    {
+      st_synchronize();
+    }
+    break;
     case 500: // Store settings in EEPROM
     {
         StoreSettings();
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index d5d41b1736..23066ef320 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -33,12 +33,14 @@
 #include "speed_lookuptable.h"
 
 
+
 //===========================================================================
 //=============================public variables  ============================
 //===========================================================================
 block_t *current_block;  // A pointer to the block currently being traced
 
 
+
 //===========================================================================
 //=============================private variables ============================
 //===========================================================================
@@ -62,7 +64,9 @@ static long acceleration_time, deceleration_time;
 static unsigned short acc_step_rate; // needed for deccelaration start point
 static char step_loops;
 
-
+volatile long endstops_trigsteps[3]={0,0,0};
+volatile long endstops_stepsTotal,endstops_stepsDone;
+static volatile bool endstops_hit=false;
 
 // if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer.
 // for debugging purposes only, should be disabled by default
@@ -152,9 +156,49 @@ asm volatile ( \
 #define DISABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 &= ~(1<<OCIE1A)
 
 
+void endstops_triggered(const unsigned long &stepstaken)  
+{
+  //this will only work if there is no bufferig
+  //however, if you perform a move at which the endstops should be triggered, and wait for it to complete, i.e. by blocking command, it should work
+  //yes, it uses floats, but: if endstops are triggered, thats hopefully not critical anymore anyways.
+  //endstops_triggerpos;
+  
+  if(endstops_hit) //hitting a second time while the first hit is not reported
+    return;
+  if(current_block == NULL)
+    return;
+  endstops_stepsTotal=current_block->step_event_count;
+  endstops_stepsDone=stepstaken;
+  endstops_trigsteps[0]=current_block->steps_x;
+  endstops_trigsteps[1]=current_block->steps_y;
+  endstops_trigsteps[2]=current_block->steps_z;
 
+  endstops_hit=true;
+}
 
+void checkHitEndstops()
+{
+  if( !endstops_hit)
+   return;
+  float endstops_triggerpos[3]={0,0,0};
+  float ratiodone=endstops_stepsDone/float(endstops_stepsTotal);  //ratio of current_block thas was performed
+  
+  endstops_triggerpos[0]=current_position[0]-(endstops_trigsteps[0]*ratiodone)/float(axis_steps_per_unit[0]);
+  endstops_triggerpos[1]=current_position[1]-(endstops_trigsteps[1]*ratiodone)/float(axis_steps_per_unit[1]);
+  endstops_triggerpos[2]=current_position[2]-(endstops_trigsteps[2]*ratiodone)/float(axis_steps_per_unit[2]);
+ SERIAL_ECHO_START;
+ SERIAL_ECHOPGM("endstops hit: ");
+ SERIAL_ECHOPAIR(" X:",endstops_triggerpos[0]);
+ SERIAL_ECHOPAIR(" Y:",endstops_triggerpos[1]);
+ SERIAL_ECHOPAIR(" Z:",endstops_triggerpos[2]);
+ SERIAL_ECHOLN("");
+ endstops_hit=false;
+}
 
+void endstops_hit_on_purpose()
+{
+  endstops_hit=false;
+}
 
 //         __________________________
 //        /|                        |\     _________________         ^
@@ -296,6 +340,7 @@ ISR(TIMER1_COMPA_vect)
       #endif
       #if X_MIN_PIN > -1
             if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) {
+              endstops_triggered(step_events_completed);
               step_events_completed = current_block->step_event_count;
             }
       #endif
@@ -307,6 +352,7 @@ ISR(TIMER1_COMPA_vect)
       #endif
       #if X_MAX_PIN > -1
         if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING)  && (current_block->steps_x >0)){
+          endstops_triggered(step_events_completed);
           step_events_completed = current_block->step_event_count;
         }
         #endif
@@ -319,6 +365,7 @@ ISR(TIMER1_COMPA_vect)
       #endif
       #if Y_MIN_PIN > -1
         if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) {
+          endstops_triggered(step_events_completed);
           step_events_completed = current_block->step_event_count;
         }
       #endif
@@ -330,6 +377,7 @@ ISR(TIMER1_COMPA_vect)
       #endif
       #if Y_MAX_PIN > -1
       if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){
+          endstops_triggered(step_events_completed);
           step_events_completed = current_block->step_event_count;
         }
       #endif
@@ -342,6 +390,7 @@ ISR(TIMER1_COMPA_vect)
       #endif
       #if Z_MIN_PIN > -1
         if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) {
+          endstops_triggered(step_events_completed);
           step_events_completed = current_block->step_event_count;
         }
       #endif
@@ -353,6 +402,7 @@ ISR(TIMER1_COMPA_vect)
       #endif
       #if Z_MAX_PIN > -1
         if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING)  && (current_block->steps_z >0)){
+          endstops_triggered(step_events_completed);
           step_events_completed = current_block->step_event_count;
         }
       #endif
diff --git a/Marlin/stepper.h b/Marlin/stepper.h
index fb649692d3..ecbc713e36 100644
--- a/Marlin/stepper.h
+++ b/Marlin/stepper.h
@@ -39,6 +39,13 @@ void st_wake_up();
   extern volatile long count_position[NUM_AXIS];
   extern volatile int count_direction[NUM_AXIS];
 #endif
+  
+void checkHitEndstops(); //call from somwhere to create an serial error message with the locations the endstops where hit, in case they were triggered
+void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homeing and before a routine call of checkHitEndstops();
+
+
 
 extern block_t *current_block;  // A pointer to the block currently being traced
+
+
 #endif