From 9980ceb4a37ec1d2cae99b73ceae146ef7340e88 Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sun, 13 Nov 2011 19:58:09 +0100
Subject: [PATCH] added a m400, that finished all moves, and the mechanism so
 that if an endstop is hit it the ISR, the steps_to_be_taken are stored, and
 some current_block data that will be deleted in the next move If the normal
 loop() then finds such an event, the position is calculated (floats would
 have taken too long in the ISR) A serial message is generated.

---
 Marlin/Marlin.h    |  2 ++
 Marlin/Marlin.pde  | 20 +++++++++++++++---
 Marlin/stepper.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++-
 Marlin/stepper.h   |  7 +++++++
 4 files changed, 77 insertions(+), 4 deletions(-)

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