chiark / gitweb /
Add M401 - Wait for user on LCD button press
[marlin.git] / Marlin / Marlin.pde
1 /*
2     Reprap firmware based on Sprinter and grbl.
3  Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
4  
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9  
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14  
15  You should have received a copy of the GNU General Public License
16  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /*
20  This firmware is a mashup between Sprinter and grbl.
21   (https://github.com/kliment/Sprinter)
22   (https://github.com/simen/grbl/tree)
23  
24  It has preliminary support for Matthew Roberts advance algorithm 
25     http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
26  */
27
28 #include "Marlin.h"
29
30 #include "ultralcd.h"
31 #include "planner.h"
32 #include "stepper.h"
33 #include "temperature.h"
34 #include "motion_control.h"
35 #include "cardreader.h"
36 #include "watchdog.h"
37 #include "EEPROMwrite.h"
38 #include "language.h"
39 #include "pins_arduino.h"
40
41 #define VERSION_STRING  "1.0.0 RC2"
42
43 // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html
44 // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
45
46 //Implemented Codes
47 //-------------------
48 // G0  -> G1
49 // G1  - Coordinated Movement X Y Z E
50 // G2  - CW ARC
51 // G3  - CCW ARC
52 // G4  - Dwell S<seconds> or P<milliseconds>
53 // G28 - Home all Axis
54 // G90 - Use Absolute Coordinates
55 // G91 - Use Relative Coordinates
56 // G92 - Set current position to cordinates given
57
58 //RepRap M Codes
59 // M104 - Set extruder target temp
60 // M105 - Read current temp
61 // M106 - Fan on
62 // M107 - Fan off
63 // M109 - Wait for extruder current temp to reach target temp.
64 // M114 - Display current position
65
66 //Custom M Codes
67 // M17  - Enable/Power all stepper motors
68 // M18  - Disable all stepper motors; same as M84
69 // M20  - List SD card
70 // M21  - Init SD card
71 // M22  - Release SD card
72 // M23  - Select SD file (M23 filename.g)
73 // M24  - Start/resume SD print
74 // M25  - Pause SD print
75 // M26  - Set SD position in bytes (M26 S12345)
76 // M27  - Report SD print status
77 // M28  - Start SD write (M28 filename.g)
78 // M29  - Stop SD write
79 // M30  - Delete file from SD (M30 filename.g)
80 // M31  - Output time since last M109 or SD card start to serial
81 // M42  - Change pin status via gcode
82 // M80  - Turn on Power Supply
83 // M81  - Turn off Power Supply
84 // M82  - Set E codes absolute (default)
85 // M83  - Set E codes relative while in Absolute Coordinates (G90) mode
86 // M84  - Disable steppers until next move, 
87 //        or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled.  S0 to disable the timeout.
88 // M85  - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
89 // M92  - Set axis_steps_per_unit - same syntax as G92
90 // M114 - Output current position to serial port 
91 // M115 - Capabilities string
92 // M117 - display message
93 // M119 - Output Endstop status to serial port
94 // M140 - Set bed target temp
95 // M190 - Wait for bed current temp to reach target temp.
96 // M200 - Set filament diameter
97 // M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
98 // M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!!
99 // M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
100 // M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2  also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate
101 // M205 -  advanced settings:  minimum travel speed S=while printing T=travel only,  B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E=maximum E jerk
102 // M206 - set additional homeing offset
103 // M220 S<factor in percent>- set speed factor override percentage
104 // M221 S<factor in percent>- set extrude factor override percentage
105 // M240 - Trigger a camera to take a photograph
106 // M301 - Set PID parameters P I and D
107 // M302 - Allow cold extrudes
108 // M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
109 // M400 - Finish all moves
110 // M401 - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
111 // M500 - stores paramters in EEPROM
112 // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).  
113 // M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
114 // M503 - print the current settings (from memory not from eeprom)
115 // M999 - Restart after being stopped by error
116
117 //Stepper Movement Variables
118
119 //===========================================================================
120 //=============================imported variables============================
121 //===========================================================================
122
123
124 //===========================================================================
125 //=============================public variables=============================
126 //===========================================================================
127 #ifdef SDSUPPORT
128 CardReader card;
129 #endif
130 float homing_feedrate[] = HOMING_FEEDRATE;
131 bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
132 volatile int feedmultiply=100; //100->1 200->2
133 int saved_feedmultiply;
134 volatile bool feedmultiplychanged=false;
135 volatile int extrudemultiply=100; //100->1 200->2
136 float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 };
137 float add_homeing[3]={0,0,0};
138 uint8_t active_extruder = 0;
139 unsigned char FanSpeed=0;
140
141
142 //===========================================================================
143 //=============================private variables=============================
144 //===========================================================================
145 const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
146 static float destination[NUM_AXIS] = {  0.0, 0.0, 0.0, 0.0};
147 static float offset[3] = {0.0, 0.0, 0.0};
148 static bool home_all_axis = true;
149 static float feedrate = 1500.0, next_feedrate, saved_feedrate;
150 static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
151
152 static bool relative_mode = false;  //Determines Absolute or Relative Coordinates
153 static bool relative_mode_e = false;  //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode.
154
155 static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
156 static bool fromsd[BUFSIZE];
157 static int bufindr = 0;
158 static int bufindw = 0;
159 static int buflen = 0;
160 //static int i = 0;
161 static char serial_char;
162 static int serial_count = 0;
163 static boolean comment_mode = false;
164 static char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc
165
166 const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42
167
168 //static float tt = 0;
169 //static float bt = 0;
170
171 //Inactivity shutdown variables
172 static unsigned long previous_millis_cmd = 0;
173 static unsigned long max_inactive_time = 0;
174 static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l;
175
176 static unsigned long starttime=0;
177 static unsigned long stoptime=0;
178
179 static uint8_t tmp_extruder;
180
181 bool Stopped=false;
182
183 //===========================================================================
184 //=============================ROUTINES=============================
185 //===========================================================================
186
187 void get_arc_coordinates();
188
189 extern "C"{
190   extern unsigned int __bss_end;
191   extern unsigned int __heap_start;
192   extern void *__brkval;
193
194   int freeMemory() {
195     int free_memory;
196
197     if((int)__brkval == 0)
198       free_memory = ((int)&free_memory) - ((int)&__bss_end);
199     else
200       free_memory = ((int)&free_memory) - ((int)__brkval);
201
202     return free_memory;
203   }
204 }
205
206 //adds an command to the main command buffer
207 //thats really done in a non-safe way.
208 //needs overworking someday
209 void enquecommand(const char *cmd)
210 {
211   if(buflen < BUFSIZE)
212   {
213     //this is dangerous if a mixing of serial and this happsens
214     strcpy(&(cmdbuffer[bufindw][0]),cmd);
215     SERIAL_ECHO_START;
216     SERIAL_ECHOPGM("enqueing \"");
217     SERIAL_ECHO(cmdbuffer[bufindw]);
218     SERIAL_ECHOLNPGM("\"");
219     bufindw= (bufindw + 1)%BUFSIZE;
220     buflen += 1;
221   }
222 }
223
224 void setup_photpin()
225 {
226   #ifdef PHOTOGRAPH_PIN
227     #if (PHOTOGRAPH_PIN > -1)
228     SET_OUTPUT(PHOTOGRAPH_PIN);
229     WRITE(PHOTOGRAPH_PIN, LOW);
230     #endif
231   #endif 
232 }
233
234 void setup_powerhold()
235 {
236  #ifdef SUICIDE_PIN
237    #if (SUICIDE_PIN> -1)
238       SET_OUTPUT(SUICIDE_PIN);
239       WRITE(SUICIDE_PIN, HIGH);
240    #endif
241  #endif
242 }
243
244 void suicide()
245 {
246  #ifdef SUICIDE_PIN
247     #if (SUICIDE_PIN> -1) 
248       SET_OUTPUT(SUICIDE_PIN);
249       WRITE(SUICIDE_PIN, LOW);
250     #endif
251   #endif
252 }
253
254 void setup()
255
256   setup_powerhold();
257   MYSERIAL.begin(BAUDRATE);
258   SERIAL_PROTOCOLLNPGM("start");
259   SERIAL_ECHO_START;
260
261   // Check startup - does nothing if bootloader sets MCUSR to 0
262   byte mcu = MCUSR;
263   if(mcu & 1) SERIAL_ECHOLNPGM(MSG_POWERUP);
264   if(mcu & 2) SERIAL_ECHOLNPGM(MSG_EXTERNAL_RESET);
265   if(mcu & 4) SERIAL_ECHOLNPGM(MSG_BROWNOUT_RESET);
266   if(mcu & 8) SERIAL_ECHOLNPGM(MSG_WATCHDOG_RESET);
267   if(mcu & 32) SERIAL_ECHOLNPGM(MSG_SOFTWARE_RESET);
268   MCUSR=0;
269
270   SERIAL_ECHOPGM(MSG_MARLIN);
271   SERIAL_ECHOLNPGM(VERSION_STRING);
272   #ifdef STRING_VERSION_CONFIG_H
273     #ifdef STRING_CONFIG_H_AUTHOR
274       SERIAL_ECHO_START;
275       SERIAL_ECHOPGM(MSG_CONFIGURATION_VER);
276       SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H);
277       SERIAL_ECHOPGM(MSG_AUTHOR);
278       SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR);
279     #endif
280   #endif
281   SERIAL_ECHO_START;
282   SERIAL_ECHOPGM(MSG_FREE_MEMORY);
283   SERIAL_ECHO(freeMemory());
284   SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES);
285   SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE);
286   for(int8_t i = 0; i < BUFSIZE; i++)
287   {
288     fromsd[i] = false;
289   }
290   
291   EEPROM_RetrieveSettings(); // loads data from EEPROM if available
292
293   for(int8_t i=0; i < NUM_AXIS; i++)
294   {
295     axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
296   }
297
298
299   tp_init();    // Initialize temperature loop 
300   plan_init();  // Initialize planner;
301   st_init();    // Initialize stepper;
302   wd_init();
303   setup_photpin();
304   
305   LCD_INIT;
306 }
307
308
309 void loop()
310 {
311   if(buflen < (BUFSIZE-1))
312     get_command();
313   #ifdef SDSUPPORT
314   card.checkautostart(false);
315   #endif
316   if(buflen)
317   {
318     #ifdef SDSUPPORT
319       if(card.saving)
320       {
321         if(strstr(cmdbuffer[bufindr],"M29") == NULL)
322         {
323           card.write_command(cmdbuffer[bufindr]);
324           SERIAL_PROTOCOLLNPGM(MSG_OK);
325         }
326         else
327         {
328           card.closefile();
329           SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED);
330         }
331       }
332       else
333       {
334         process_commands();
335       }
336     #else
337       process_commands();
338     #endif //SDSUPPORT
339     buflen = (buflen-1);
340     bufindr = (bufindr + 1)%BUFSIZE;
341   }
342   //check heater every n milliseconds
343   manage_heater();
344   manage_inactivity(1);
345   checkHitEndstops();
346   LCD_STATUS;
347 }
348
349 void get_command() 
350
351   while( MYSERIAL.available() > 0  && buflen < BUFSIZE) {
352     serial_char = MYSERIAL.read();
353     if(serial_char == '\n' || 
354        serial_char == '\r' || 
355        (serial_char == ':' && comment_mode == false) || 
356        serial_count >= (MAX_CMD_SIZE - 1) ) 
357     {
358       if(!serial_count) { //if empty line
359         comment_mode = false; //for new command
360         return;
361       }
362       cmdbuffer[bufindw][serial_count] = 0; //terminate string
363       if(!comment_mode){
364         comment_mode = false; //for new command
365         fromsd[bufindw] = false;
366         if(strstr(cmdbuffer[bufindw], "N") != NULL)
367         {
368           strchr_pointer = strchr(cmdbuffer[bufindw], 'N');
369           gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));
370           if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) {
371             SERIAL_ERROR_START;
372             SERIAL_ERRORPGM(MSG_ERR_LINE_NO);
373             SERIAL_ERRORLN(gcode_LastN);
374             //Serial.println(gcode_N);
375             FlushSerialRequestResend();
376             serial_count = 0;
377             return;
378           }
379
380           if(strstr(cmdbuffer[bufindw], "*") != NULL)
381           {
382             byte checksum = 0;
383             byte count = 0;
384             while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++];
385             strchr_pointer = strchr(cmdbuffer[bufindw], '*');
386
387             if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) {
388               SERIAL_ERROR_START;
389               SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH);
390               SERIAL_ERRORLN(gcode_LastN);
391               FlushSerialRequestResend();
392               serial_count = 0;
393               return;
394             }
395             //if no errors, continue parsing
396           }
397           else 
398           {
399             SERIAL_ERROR_START;
400             SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM);
401             SERIAL_ERRORLN(gcode_LastN);
402             FlushSerialRequestResend();
403             serial_count = 0;
404             return;
405           }
406
407           gcode_LastN = gcode_N;
408           //if no errors, continue parsing
409         }
410         else  // if we don't receive 'N' but still see '*'
411         {
412           if((strstr(cmdbuffer[bufindw], "*") != NULL))
413           {
414             SERIAL_ERROR_START;
415             SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM);
416             SERIAL_ERRORLN(gcode_LastN);
417             serial_count = 0;
418             return;
419           }
420         }
421         if((strstr(cmdbuffer[bufindw], "G") != NULL)){
422           strchr_pointer = strchr(cmdbuffer[bufindw], 'G');
423           switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){
424           case 0:
425           case 1:
426           case 2:
427           case 3:
428             if(Stopped == false) { // If printer is stopped by an error the G[0-3] codes are ignored.
429               #ifdef SDSUPPORT
430               if(card.saving)
431                 break;
432               #endif //SDSUPPORT
433               SERIAL_PROTOCOLLNPGM(MSG_OK); 
434             }
435             else {
436               SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
437               LCD_MESSAGEPGM(MSG_STOPPED);
438             }
439             break;
440           default:
441             break;
442           }
443
444         }
445         bufindw = (bufindw + 1)%BUFSIZE;
446         buflen += 1;
447       }
448       serial_count = 0; //clear buffer
449     }
450     else
451     {
452       if(serial_char == ';') comment_mode = true;
453       if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
454     }
455   }
456   #ifdef SDSUPPORT
457   if(!card.sdprinting || serial_count!=0){
458     return;
459   }
460   while( !card.eof()  && buflen < BUFSIZE) {
461     int16_t n=card.get();
462     serial_char = (char)n;
463     if(serial_char == '\n' || 
464        serial_char == '\r' || 
465        (serial_char == ':' && comment_mode == false) || 
466        serial_count >= (MAX_CMD_SIZE - 1)||n==-1) 
467     {
468       if(card.eof()){
469         SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
470         stoptime=millis();
471         char time[30];
472         unsigned long t=(stoptime-starttime)/1000;
473         int sec,min;
474         min=t/60;
475         sec=t%60;
476         sprintf(time,"%i min, %i sec",min,sec);
477         SERIAL_ECHO_START;
478         SERIAL_ECHOLN(time);
479         LCD_MESSAGE(time);
480         card.printingHasFinished();
481         card.checkautostart(true);
482         
483       }
484       if(!serial_count)
485       {
486         comment_mode = false; //for new command
487         return; //if empty line
488       }
489       cmdbuffer[bufindw][serial_count] = 0; //terminate string
490 //      if(!comment_mode){
491         fromsd[bufindw] = true;
492         buflen += 1;
493         bufindw = (bufindw + 1)%BUFSIZE;
494 //      }     
495       comment_mode = false; //for new command
496       serial_count = 0; //clear buffer
497     }
498     else
499     {
500       if(serial_char == ';') comment_mode = true;
501       if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
502     }
503   }
504   
505   #endif //SDSUPPORT
506
507 }
508
509
510 float code_value() 
511
512   return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); 
513 }
514
515 long code_value_long() 
516
517   return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); 
518 }
519
520 bool code_seen(char code_string[]) //Return True if the string was found
521
522   return (strstr(cmdbuffer[bufindr], code_string) != NULL); 
523 }  
524
525 bool code_seen(char code)
526 {
527   strchr_pointer = strchr(cmdbuffer[bufindr], code);
528   return (strchr_pointer != NULL);  //Return True if a character was found
529 }
530
531 #define HOMEAXIS(LETTER) \
532   if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\
533     { \
534     current_position[LETTER##_AXIS] = 0; \
535     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \
536     destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \
537     feedrate = homing_feedrate[LETTER##_AXIS]; \
538     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \
539     st_synchronize();\
540     \
541     current_position[LETTER##_AXIS] = 0;\
542     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\
543     destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\
544     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \
545     st_synchronize();\
546     \
547     destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\
548     feedrate = homing_feedrate[LETTER##_AXIS]/2 ;  \
549     plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \
550     st_synchronize();\
551     \
552     current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\
553     destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\
554     feedrate = 0.0;\
555     endstops_hit_on_purpose();\
556   }
557
558 void process_commands()
559 {
560   unsigned long codenum; //throw away variable
561   char *starpos = NULL;
562
563   if(code_seen('G'))
564   {
565     switch((int)code_value())
566     {
567     case 0: // G0 -> G1
568     case 1: // G1
569       if(Stopped == false) {
570         get_coordinates(); // For X Y Z E F
571         prepare_move();
572         //ClearToSend();
573         return;
574       }
575       //break;
576     case 2: // G2  - CW ARC
577       if(Stopped == false) {
578         get_arc_coordinates();
579         prepare_arc_move(true);
580         return;
581       }
582     case 3: // G3  - CCW ARC
583       if(Stopped == false) {
584         get_arc_coordinates();
585         prepare_arc_move(false);
586         return;
587       }
588     case 4: // G4 dwell
589       LCD_MESSAGEPGM(MSG_DWELL);
590       codenum = 0;
591       if(code_seen('P')) codenum = code_value(); // milliseconds to wait
592       if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
593       
594       st_synchronize();
595       codenum += millis();  // keep track of when we started waiting
596       previous_millis_cmd = millis();
597       while(millis()  < codenum ){
598         manage_heater();
599         manage_inactivity(1);
600                 LCD_STATUS;
601       }
602       break;
603     case 28: //G28 Home all Axis one at a time
604       saved_feedrate = feedrate;
605       saved_feedmultiply = feedmultiply;
606       feedmultiply = 100;
607       previous_millis_cmd = millis();
608       
609       enable_endstops(true);
610       
611       for(int8_t i=0; i < NUM_AXIS; i++) {
612         destination[i] = current_position[i];
613       }
614       feedrate = 0.0;
615       home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2])));
616       #ifdef QUICK_HOME
617       if((home_all_axis)||( code_seen(axis_codes[X_AXIS]) && code_seen(axis_codes[Y_AXIS])) )  //first diagonal move
618       {
619         current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0;  
620
621         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 
622         destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR;  
623         feedrate = homing_feedrate[X_AXIS]; 
624         if(homing_feedrate[Y_AXIS]<feedrate)
625           feedrate =homing_feedrate[Y_AXIS]; 
626         plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
627         st_synchronize();
628     
629         current_position[X_AXIS] = (X_HOME_DIR == -1) ? X_HOME_POS : X_MAX_LENGTH;
630         current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? Y_HOME_POS : Y_MAX_LENGTH;
631         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
632         destination[X_AXIS] = current_position[X_AXIS];
633         destination[Y_AXIS] = current_position[Y_AXIS];
634         plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
635         feedrate = 0.0;
636         st_synchronize();
637         endstops_hit_on_purpose();
638       }
639       #endif
640       
641       if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) 
642       {
643         HOMEAXIS(X);
644       }
645
646       if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) {
647        HOMEAXIS(Y);
648       }
649       
650       if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) {
651         HOMEAXIS(Z);
652       }
653       
654       if(code_seen(axis_codes[X_AXIS])) 
655       {
656         if(code_value_long() != 0) {
657           current_position[X_AXIS]=code_value()+add_homeing[0];
658         }
659       }
660
661       if(code_seen(axis_codes[Y_AXIS])) {
662         if(code_value_long() != 0) {
663           current_position[Y_AXIS]=code_value()+add_homeing[1];
664         }
665       }
666
667       if(code_seen(axis_codes[Z_AXIS])) {
668         if(code_value_long() != 0) {
669           current_position[Z_AXIS]=code_value()+add_homeing[2];
670         }
671       }
672       plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
673       
674       #ifdef ENDSTOPS_ONLY_FOR_HOMING
675         enable_endstops(false);
676       #endif
677       
678       feedrate = saved_feedrate;
679       feedmultiply = saved_feedmultiply;
680       previous_millis_cmd = millis();
681       endstops_hit_on_purpose();
682       break;
683     case 90: // G90
684       relative_mode = false;
685       break;
686     case 91: // G91
687       relative_mode = true;
688       break;
689     case 92: // G92
690       if(!code_seen(axis_codes[E_AXIS]))
691         st_synchronize();
692       for(int8_t i=0; i < NUM_AXIS; i++) {
693         if(code_seen(axis_codes[i])) { 
694            if(i == E_AXIS) {
695              current_position[i] = code_value();  
696              plan_set_e_position(current_position[E_AXIS]);
697            }
698            else {
699              current_position[i] = code_value()+add_homeing[i];  
700              plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
701            }
702         }
703       }
704       break;
705     }
706   }
707
708   else if(code_seen('M'))
709   {
710     switch( (int)code_value() ) 
711     {
712     case 17:
713         LCD_MESSAGEPGM(MSG_NO_MOVE);
714         enable_x(); 
715         enable_y(); 
716         enable_z(); 
717         enable_e0(); 
718         enable_e1(); 
719         enable_e2(); 
720       break;
721
722 #ifdef SDSUPPORT
723     case 20: // M20 - list SD card
724       SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST);
725       card.ls();
726       SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST);
727       break;
728     case 21: // M21 - init SD card
729       
730       card.initsd();
731       
732       break;
733     case 22: //M22 - release SD card
734       card.release();
735
736       break;
737     case 23: //M23 - Select file
738       starpos = (strchr(strchr_pointer + 4,'*'));
739       if(starpos!=NULL)
740         *(starpos-1)='\0';
741       card.openFile(strchr_pointer + 4,true);
742       break;
743     case 24: //M24 - Start SD print
744       card.startFileprint();
745       starttime=millis();
746       break;
747     case 25: //M25 - Pause SD print
748       card.pauseSDPrint();
749       break;
750     case 26: //M26 - Set SD index
751       if(card.cardOK && code_seen('S')) {
752         card.setIndex(code_value_long());
753       }
754       break;
755     case 27: //M27 - Get SD status
756       card.getStatus();
757       break;
758     case 28: //M28 - Start SD write
759       starpos = (strchr(strchr_pointer + 4,'*'));
760       if(starpos != NULL){
761         char* npos = strchr(cmdbuffer[bufindr], 'N');
762         strchr_pointer = strchr(npos,' ') + 1;
763         *(starpos-1) = '\0';
764       }
765       card.openFile(strchr_pointer+4,false);
766       break;
767     case 29: //M29 - Stop SD write
768       //processed in write to file routine above
769       //card,saving = false;
770       break;
771     case 30: //M30 <filename> Delete File 
772         if (card.cardOK){
773                 card.closefile();
774                 starpos = (strchr(strchr_pointer + 4,'*'));
775                 if(starpos != NULL){
776                 char* npos = strchr(cmdbuffer[bufindr], 'N');
777                 strchr_pointer = strchr(npos,' ') + 1;
778                 *(starpos-1) = '\0';
779          }
780          card.removeFile(strchr_pointer + 4);
781         }
782         break;
783         
784 #endif //SDSUPPORT
785
786     case 31: //M31 take time since the start of the SD print or an M109 command
787       {
788       stoptime=millis();
789       char time[30];
790       unsigned long t=(stoptime-starttime)/1000;
791       int sec,min;
792       min=t/60;
793       sec=t%60;
794       sprintf(time,"%i min, %i sec",min,sec);
795       SERIAL_ECHO_START;
796       SERIAL_ECHOLN(time);
797       LCD_MESSAGE(time);
798       autotempShutdown();
799       }
800       break;
801     case 42: //M42 -Change pin status via gcode
802       if (code_seen('S'))
803       {
804         int pin_status = code_value();
805         if (code_seen('P') && pin_status >= 0 && pin_status <= 255)
806         {
807           int pin_number = code_value();
808           for(int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++)
809           {
810             if (sensitive_pins[i] == pin_number)
811             {
812               pin_number = -1;
813               break;
814             }
815           }
816           
817           if (pin_number > -1)
818           {              
819             pinMode(pin_number, OUTPUT);
820             digitalWrite(pin_number, pin_status);
821             analogWrite(pin_number, pin_status);
822           }
823         }
824       }
825      break;
826     case 104: // M104
827       tmp_extruder = active_extruder;
828       if(code_seen('T')) {
829         tmp_extruder = code_value();
830         if(tmp_extruder >= EXTRUDERS) {
831           SERIAL_ECHO_START;
832           SERIAL_ECHO(MSG_M104_INVALID_EXTRUDER);
833           SERIAL_ECHOLN(tmp_extruder);
834           break;
835         }
836       }
837       if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder);
838       setWatch();
839       break;
840     case 140: // M140 set bed temp
841       if (code_seen('S')) setTargetBed(code_value());
842       break;
843     case 105 : // M105
844       tmp_extruder = active_extruder;
845       if(code_seen('T')) {
846         tmp_extruder = code_value();
847         if(tmp_extruder >= EXTRUDERS) {
848           SERIAL_ECHO_START;
849           SERIAL_ECHO(MSG_M105_INVALID_EXTRUDER);
850           SERIAL_ECHOLN(tmp_extruder);
851           break;
852         }
853       }
854       #if (TEMP_0_PIN > -1)
855         SERIAL_PROTOCOLPGM("ok T:");
856         SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); 
857         SERIAL_PROTOCOLPGM(" /");
858         SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1); 
859         #if TEMP_BED_PIN > -1
860           SERIAL_PROTOCOLPGM(" B:");  
861           SERIAL_PROTOCOL_F(degBed(),1);
862           SERIAL_PROTOCOLPGM(" /");
863           SERIAL_PROTOCOL_F(degTargetBed(),1);
864         #endif //TEMP_BED_PIN
865       #else
866         SERIAL_ERROR_START;
867         SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
868       #endif
869       #ifdef PIDTEMP
870         SERIAL_PROTOCOLPGM(" @:");
871         SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));  
872       #endif
873         SERIAL_PROTOCOLLN("");
874       return;
875       break;
876     case 109: 
877     {// M109 - Wait for extruder heater to reach target.
878       tmp_extruder = active_extruder;
879       if(code_seen('T')) {
880         tmp_extruder = code_value();
881         if(tmp_extruder >= EXTRUDERS) {
882           SERIAL_ECHO_START;
883           SERIAL_ECHO(MSG_M109_INVALID_EXTRUDER);
884           SERIAL_ECHOLN(tmp_extruder);
885           break;
886         }
887       }
888       LCD_MESSAGEPGM(MSG_HEATING);   
889       #ifdef AUTOTEMP
890         autotemp_enabled=false;
891       #endif
892       if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder);
893       #ifdef AUTOTEMP
894         if (code_seen('S')) autotemp_min=code_value();
895         if (code_seen('B')) autotemp_max=code_value();
896         if (code_seen('F')) 
897         {
898           autotemp_factor=code_value();
899           autotemp_enabled=true;
900         }
901       #endif
902       
903       setWatch();
904       codenum = millis(); 
905
906       /* See if we are heating up or cooling down */
907       bool target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling
908
909       #ifdef TEMP_RESIDENCY_TIME
910         long residencyStart;
911         residencyStart = -1;
912         /* continue to loop until we have reached the target temp   
913           _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */
914         while((residencyStart == -1) ||
915               (residencyStart >= 0 && (((unsigned int) (millis() - residencyStart)) < (TEMP_RESIDENCY_TIME * 1000UL))) ) {
916       #else
917         while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) {
918       #endif //TEMP_RESIDENCY_TIME
919           if( (millis() - codenum) > 1000UL )
920           { //Print Temp Reading and remaining time every 1 second while heating up/cooling down
921             SERIAL_PROTOCOLPGM("T:");
922             SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); 
923             SERIAL_PROTOCOLPGM(" E:");
924             SERIAL_PROTOCOL((int)tmp_extruder); 
925             #ifdef TEMP_RESIDENCY_TIME
926               SERIAL_PROTOCOLPGM(" W:");
927               if(residencyStart > -1)
928               {
929                  codenum = ((TEMP_RESIDENCY_TIME * 1000UL) - (millis() - residencyStart)) / 1000UL;
930                  SERIAL_PROTOCOLLN( codenum );
931               }
932               else 
933               {
934                  SERIAL_PROTOCOLLN( "?" );
935               }
936             #else
937               SERIAL_PROTOCOLLN("");
938             #endif
939             codenum = millis();
940           }
941           manage_heater();
942           manage_inactivity(1);
943           LCD_STATUS;
944         #ifdef TEMP_RESIDENCY_TIME
945             /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time
946               or when current temp falls outside the hysteresis after target temp was reached */
947           if ((residencyStart == -1 &&  target_direction && (degHotend(tmp_extruder) >= (degTargetHotend(tmp_extruder)-TEMP_WINDOW))) ||
948               (residencyStart == -1 && !target_direction && (degHotend(tmp_extruder) <= (degTargetHotend(tmp_extruder)+TEMP_WINDOW))) ||
949               (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) 
950           {
951             residencyStart = millis();
952           }
953         #endif //TEMP_RESIDENCY_TIME
954         }
955         LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
956         starttime=millis();
957         previous_millis_cmd = millis();
958       }
959       break;
960     case 190: // M190 - Wait for bed heater to reach target.
961     #if TEMP_BED_PIN > -1
962         LCD_MESSAGEPGM(MSG_BED_HEATING);
963         if (code_seen('S')) setTargetBed(code_value());
964         codenum = millis(); 
965         while(isHeatingBed()) 
966         {
967           if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
968           {
969             float tt=degHotend(active_extruder);
970             SERIAL_PROTOCOLPGM("T:");
971             SERIAL_PROTOCOL(tt);
972             SERIAL_PROTOCOLPGM(" E:");
973             SERIAL_PROTOCOL((int)active_extruder); 
974             SERIAL_PROTOCOLPGM(" B:");
975             SERIAL_PROTOCOL_F(degBed(),1); 
976             SERIAL_PROTOCOLLN(""); 
977             codenum = millis(); 
978           }
979           manage_heater();
980           manage_inactivity(1);
981           LCD_STATUS;
982         }
983         LCD_MESSAGEPGM(MSG_BED_DONE);
984         previous_millis_cmd = millis();
985     #endif
986         break;
987
988     #if FAN_PIN > -1
989       case 106: //M106 Fan On
990         if (code_seen('S')){
991            FanSpeed=constrain(code_value(),0,255);
992         }
993         else {
994           FanSpeed=255;                 
995         }
996         break;
997       case 107: //M107 Fan Off
998         FanSpeed = 0;
999         break;
1000     #endif //FAN_PIN
1001
1002     #if (PS_ON_PIN > -1)
1003       case 80: // M80 - ATX Power On
1004         SET_OUTPUT(PS_ON_PIN); //GND
1005         WRITE(PS_ON_PIN, LOW);
1006         break;
1007       #endif
1008       
1009       case 81: // M81 - ATX Power Off
1010       
1011       #if defined SUICIDE_PIN && SUICIDE_PIN > -1
1012         st_synchronize();
1013         suicide();
1014       #elif (PS_ON_PIN > -1)
1015         SET_INPUT(PS_ON_PIN); //Floating
1016       #endif
1017                 break;
1018         
1019     case 82:
1020       axis_relative_modes[3] = false;
1021       break;
1022     case 83:
1023       axis_relative_modes[3] = true;
1024       break;
1025     case 18: //compatibility
1026     case 84: // M84
1027       if(code_seen('S')){ 
1028         stepper_inactive_time = code_value() * 1000; 
1029       }
1030       else
1031       { 
1032         bool all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))|| (code_seen(axis_codes[3])));
1033         if(all_axis)
1034         {
1035           st_synchronize();
1036           disable_e0();
1037           disable_e1();
1038           disable_e2();
1039           finishAndDisableSteppers();
1040         }
1041         else
1042         {
1043           st_synchronize();
1044           if(code_seen('X')) disable_x();
1045           if(code_seen('Y')) disable_y();
1046           if(code_seen('Z')) disable_z();
1047           #if ((E0_ENABLE_PIN != X_ENABLE_PIN) && (E1_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS
1048             if(code_seen('E')) {
1049               disable_e0();
1050               disable_e1();
1051               disable_e2();
1052             }
1053           #endif 
1054           LCD_MESSAGEPGM(MSG_PART_RELEASE);
1055         }
1056       }
1057       break;
1058     case 85: // M85
1059       code_seen('S');
1060       max_inactive_time = code_value() * 1000; 
1061       break;
1062     case 92: // M92
1063       for(int8_t i=0; i < NUM_AXIS; i++) 
1064       {
1065         if(code_seen(axis_codes[i])) 
1066           
1067           if(i == 3) { // E
1068             float value = code_value();
1069             if(value < 20.0) {
1070               float factor = axis_steps_per_unit[i] / value; // increase e constants if M92 E14 is given for netfab.
1071               max_e_jerk *= factor;
1072               max_feedrate[i] *= factor;
1073               axis_steps_per_sqr_second[i] *= factor;
1074             }
1075             axis_steps_per_unit[i] = value;
1076           }
1077           else {
1078             axis_steps_per_unit[i] = code_value();
1079           }
1080       }
1081       break;
1082     case 115: // M115
1083       SerialprintPGM(MSG_M115_REPORT);
1084       break;
1085     case 117: // M117 display message
1086       LCD_MESSAGE(cmdbuffer[bufindr]+5);
1087       break;
1088     case 114: // M114
1089       SERIAL_PROTOCOLPGM("X:");
1090       SERIAL_PROTOCOL(current_position[X_AXIS]);
1091       SERIAL_PROTOCOLPGM("Y:");
1092       SERIAL_PROTOCOL(current_position[Y_AXIS]);
1093       SERIAL_PROTOCOLPGM("Z:");
1094       SERIAL_PROTOCOL(current_position[Z_AXIS]);
1095       SERIAL_PROTOCOLPGM("E:");      
1096       SERIAL_PROTOCOL(current_position[E_AXIS]);
1097       
1098       SERIAL_PROTOCOLPGM(MSG_COUNT_X);
1099       SERIAL_PROTOCOL(float(st_get_position(X_AXIS))/axis_steps_per_unit[X_AXIS]);
1100       SERIAL_PROTOCOLPGM("Y:");
1101       SERIAL_PROTOCOL(float(st_get_position(Y_AXIS))/axis_steps_per_unit[Y_AXIS]);
1102       SERIAL_PROTOCOLPGM("Z:");
1103       SERIAL_PROTOCOL(float(st_get_position(Z_AXIS))/axis_steps_per_unit[Z_AXIS]);
1104       
1105       SERIAL_PROTOCOLLN("");
1106       break;
1107     case 120: // M120
1108       enable_endstops(false) ;
1109       break;
1110     case 121: // M121
1111       enable_endstops(true) ;
1112       break;
1113     case 119: // M119
1114       #if (X_MIN_PIN > -1)
1115         SERIAL_PROTOCOLPGM(MSG_X_MIN);
1116         SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L "));
1117       #endif
1118       #if (X_MAX_PIN > -1)
1119         SERIAL_PROTOCOLPGM(MSG_X_MAX);
1120         SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L "));
1121       #endif
1122       #if (Y_MIN_PIN > -1)
1123         SERIAL_PROTOCOLPGM(MSG_Y_MIN);
1124         SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L "));
1125       #endif
1126       #if (Y_MAX_PIN > -1)
1127         SERIAL_PROTOCOLPGM(MSG_Y_MAX);
1128         SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L "));
1129       #endif
1130       #if (Z_MIN_PIN > -1)
1131         SERIAL_PROTOCOLPGM(MSG_Z_MIN);
1132         SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L "));
1133       #endif
1134       #if (Z_MAX_PIN > -1)
1135         SERIAL_PROTOCOLPGM(MSG_Z_MAX);
1136         SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L "));
1137       #endif
1138       SERIAL_PROTOCOLLN("");
1139       break;
1140       //TODO: update for all axis, use for loop
1141     case 201: // M201
1142       for(int8_t i=0; i < NUM_AXIS; i++) 
1143       {
1144         if(code_seen(axis_codes[i]))
1145         {
1146           max_acceleration_units_per_sq_second[i] = code_value();
1147           axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
1148         }
1149       }
1150       break;
1151     #if 0 // Not used for Sprinter/grbl gen6
1152     case 202: // M202
1153       for(int8_t i=0; i < NUM_AXIS; i++) {
1154         if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
1155       }
1156       break;
1157     #endif
1158     case 203: // M203 max feedrate mm/sec
1159       for(int8_t i=0; i < NUM_AXIS; i++) {
1160         if(code_seen(axis_codes[i])) max_feedrate[i] = code_value();
1161       }
1162       break;
1163     case 204: // M204 acclereration S normal moves T filmanent only moves
1164       {
1165         if(code_seen('S')) acceleration = code_value() ;
1166         if(code_seen('T')) retract_acceleration = code_value() ;
1167       }
1168       break;
1169     case 205: //M205 advanced settings:  minimum travel speed S=while printing T=travel only,  B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
1170     {
1171       if(code_seen('S')) minimumfeedrate = code_value();
1172       if(code_seen('T')) mintravelfeedrate = code_value();
1173       if(code_seen('B')) minsegmenttime = code_value() ;
1174       if(code_seen('X')) max_xy_jerk = code_value() ;
1175       if(code_seen('Z')) max_z_jerk = code_value() ;
1176       if(code_seen('E')) max_e_jerk = code_value() ;
1177     }
1178     break;
1179     case 206: // M206 additional homeing offset
1180       for(int8_t i=0; i < 3; i++) 
1181       {
1182         if(code_seen(axis_codes[i])) add_homeing[i] = code_value();
1183       }
1184       break;
1185     case 220: // M220 S<factor in percent>- set speed factor override percentage
1186     {
1187       if(code_seen('S')) 
1188       {
1189         feedmultiply = code_value() ;
1190         feedmultiplychanged=true;
1191       }
1192     }
1193     break;
1194     case 221: // M221 S<factor in percent>- set extrude factor override percentage
1195     {
1196       if(code_seen('S')) 
1197       {
1198         extrudemultiply = code_value() ;
1199       }
1200     }
1201     break;
1202
1203     #ifdef PIDTEMP
1204     case 301: // M301
1205       {
1206         if(code_seen('P')) Kp = code_value();
1207         if(code_seen('I')) Ki = code_value()*PID_dT;
1208         if(code_seen('D')) Kd = code_value()/PID_dT;
1209         #ifdef PID_ADD_EXTRUSION_RATE
1210         if(code_seen('C')) Kc = code_value();
1211         #endif
1212         updatePID();
1213         SERIAL_PROTOCOL(MSG_OK);
1214                 SERIAL_PROTOCOL(" p:");
1215         SERIAL_PROTOCOL(Kp);
1216         SERIAL_PROTOCOL(" i:");
1217         SERIAL_PROTOCOL(Ki/PID_dT);
1218         SERIAL_PROTOCOL(" d:");
1219         SERIAL_PROTOCOL(Kd*PID_dT);
1220         #ifdef PID_ADD_EXTRUSION_RATE
1221         SERIAL_PROTOCOL(" c:");
1222         SERIAL_PROTOCOL(Kc*PID_dT);
1223         #endif
1224         SERIAL_PROTOCOLLN("");
1225       }
1226       break;
1227     #endif //PIDTEMP
1228     case 240: // M240  Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
1229      {
1230       #ifdef PHOTOGRAPH_PIN
1231         #if (PHOTOGRAPH_PIN > -1)
1232         const uint8_t NUM_PULSES=16;
1233         const float PULSE_LENGTH=0.01524;
1234         for(int i=0; i < NUM_PULSES; i++) {
1235           WRITE(PHOTOGRAPH_PIN, HIGH);
1236           _delay_ms(PULSE_LENGTH);
1237           WRITE(PHOTOGRAPH_PIN, LOW);
1238           _delay_ms(PULSE_LENGTH);
1239         }
1240         delay(7.33);
1241         for(int i=0; i < NUM_PULSES; i++) {
1242           WRITE(PHOTOGRAPH_PIN, HIGH);
1243           _delay_ms(PULSE_LENGTH);
1244           WRITE(PHOTOGRAPH_PIN, LOW);
1245           _delay_ms(PULSE_LENGTH);
1246         }
1247         #endif
1248       #endif
1249      }
1250     break;
1251       
1252     case 302: // allow cold extrudes
1253     {
1254       allow_cold_extrudes(true);
1255     }
1256     break;
1257     case 303: // M303 PID autotune
1258     {
1259       float temp = 150.0;
1260       if (code_seen('S')) temp=code_value();
1261       PID_autotune(temp);
1262     }
1263     break;
1264     case 400: // M400 finish all moves
1265     {
1266       st_synchronize();
1267     }
1268     break;
1269 #ifdef ULTRA_LCD
1270     case 401: // M401 - Wait for user button press on LCD
1271     {
1272       LCD_MESSAGEPGM(MSG_USERWAIT);
1273       codenum = 0;
1274       if(code_seen('P')) codenum = code_value(); // milliseconds to wait
1275       if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
1276       
1277       st_synchronize();
1278       previous_millis_cmd = millis();
1279           if (codenum > 0)
1280           {
1281         codenum += millis();  // keep track of when we started waiting
1282         while(millis()  < codenum && buttons == 0){
1283           manage_heater();
1284           manage_inactivity(1);
1285                 }
1286       }else{
1287         while(buttons == 0) {
1288           manage_heater();
1289           manage_inactivity(1);
1290                 }
1291           }
1292     }
1293     break;
1294 #endif
1295     case 500: // Store settings in EEPROM
1296     {
1297         EEPROM_StoreSettings();
1298     }
1299     break;
1300     case 501: // Read settings from EEPROM
1301     {
1302       EEPROM_RetrieveSettings();
1303     }
1304     break;
1305     case 502: // Revert to default settings
1306     {
1307       EEPROM_RetrieveSettings(true);
1308     }
1309     break;
1310     case 503: // print settings currently in memory
1311     {
1312       EEPROM_printSettings();
1313     }
1314     break;
1315     case 999: // Restart after being stopped
1316       Stopped = false;
1317       gcode_LastN = Stopped_gcode_LastN;
1318       FlushSerialRequestResend();
1319     break;
1320     }
1321   }
1322
1323   else if(code_seen('T')) 
1324   {
1325     tmp_extruder = code_value();
1326     if(tmp_extruder >= EXTRUDERS) {
1327       SERIAL_ECHO_START;
1328       SERIAL_ECHO("T");
1329       SERIAL_ECHO(tmp_extruder);
1330       SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
1331     }
1332     else {
1333       active_extruder = tmp_extruder;
1334       SERIAL_ECHO_START;
1335       SERIAL_ECHO(MSG_ACTIVE_EXTRUDER);
1336       SERIAL_PROTOCOLLN((int)active_extruder);
1337     }
1338   }
1339
1340   else
1341   {
1342     SERIAL_ECHO_START;
1343     SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
1344     SERIAL_ECHO(cmdbuffer[bufindr]);
1345     SERIAL_ECHOLNPGM("\"");
1346   }
1347
1348   ClearToSend();
1349 }
1350
1351 void FlushSerialRequestResend()
1352 {
1353   //char cmdbuffer[bufindr][100]="Resend:";
1354   MYSERIAL.flush();
1355   SERIAL_PROTOCOLPGM(MSG_RESEND);
1356   SERIAL_PROTOCOLLN(gcode_LastN + 1);
1357   ClearToSend();
1358 }
1359
1360 void ClearToSend()
1361 {
1362   previous_millis_cmd = millis();
1363   #ifdef SDSUPPORT
1364   if(fromsd[bufindr])
1365     return;
1366   #endif //SDSUPPORT
1367   SERIAL_PROTOCOLLNPGM(MSG_OK); 
1368 }
1369
1370 void get_coordinates()
1371 {
1372   for(int8_t i=0; i < NUM_AXIS; i++) {
1373     if(code_seen(axis_codes[i])) destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i];
1374     else destination[i] = current_position[i]; //Are these else lines really needed?
1375   }
1376   if(code_seen('F')) {
1377     next_feedrate = code_value();
1378     if(next_feedrate > 0.0) feedrate = next_feedrate;
1379   }
1380 }
1381
1382 void get_arc_coordinates()
1383 {
1384    get_coordinates();
1385    if(code_seen('I')) {
1386      offset[0] = code_value();
1387    } 
1388    else {
1389      offset[0] = 0.0;
1390    }
1391    if(code_seen('J')) {
1392      offset[1] = code_value();
1393    }
1394    else {
1395      offset[1] = 0.0;
1396    }
1397 }
1398
1399 void prepare_move()
1400 {
1401   if (min_software_endstops) {
1402     if (destination[X_AXIS] < X_HOME_POS) destination[X_AXIS] = X_HOME_POS;
1403     if (destination[Y_AXIS] < Y_HOME_POS) destination[Y_AXIS] = Y_HOME_POS;
1404     if (destination[Z_AXIS] < Z_HOME_POS) destination[Z_AXIS] = Z_HOME_POS;
1405   }
1406
1407   if (max_software_endstops) {
1408     if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH;
1409     if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH;
1410     if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH;
1411   }
1412   previous_millis_cmd = millis();  
1413   plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder);
1414   for(int8_t i=0; i < NUM_AXIS; i++) {
1415     current_position[i] = destination[i];
1416   }
1417 }
1418
1419 void prepare_arc_move(char isclockwise) {
1420   float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc
1421
1422   // Trace the arc
1423   mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder);
1424   
1425   // As far as the parser is concerned, the position is now == target. In reality the
1426   // motion control system might still be processing the action and the real tool position
1427   // in any intermediate location.
1428   for(int8_t i=0; i < NUM_AXIS; i++) {
1429     current_position[i] = destination[i];
1430   }
1431   previous_millis_cmd = millis();
1432 }
1433
1434 #ifdef CONTROLLERFAN_PIN
1435 unsigned long lastMotor = 0; //Save the time for when a motor was turned on last
1436 unsigned long lastMotorCheck = 0;
1437
1438 void controllerFan()
1439 {
1440   if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms
1441   {
1442     lastMotorCheck = millis();
1443     
1444     if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN)
1445     #if EXTRUDERS > 2
1446        || !READ(E2_ENABLE_PIN)
1447     #endif
1448     #if EXTRUDER > 1
1449        || !READ(E2_ENABLE_PIN)
1450     #endif
1451        || !READ(E0_ENABLE_PIN)) //If any of the drivers are enabled...    
1452     {
1453       lastMotor = millis(); //... set time to NOW so the fan will turn on
1454     }
1455     
1456     if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC...   
1457     {
1458       WRITE(CONTROLLERFAN_PIN, LOW); //... turn the fan off
1459     }
1460     else
1461     {
1462       WRITE(CONTROLLERFAN_PIN, HIGH); //... turn the fan on
1463     }
1464   }
1465 }
1466 #endif
1467
1468 void manage_inactivity(byte debug) 
1469
1470   if( (millis() - previous_millis_cmd) >  max_inactive_time ) 
1471     if(max_inactive_time) 
1472       kill(); 
1473   if(stepper_inactive_time)  {
1474     if( (millis() - previous_millis_cmd) >  stepper_inactive_time ) 
1475     {
1476       if(blocks_queued() == false) {
1477         disable_x();
1478         disable_y();
1479         disable_z();
1480         disable_e0();
1481         disable_e1();
1482         disable_e2();
1483       }
1484     }
1485   }
1486   #ifdef CONTROLLERFAN_PIN
1487     controllerFan(); //Check if fan should be turned on to cool stepper drivers down
1488   #endif
1489   #ifdef EXTRUDER_RUNOUT_PREVENT
1490     if( (millis() - previous_millis_cmd) >  EXTRUDER_RUNOUT_SECONDS*1000 ) 
1491     if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP)
1492     {
1493      bool oldstatus=READ(E0_ENABLE_PIN);
1494      enable_e0();
1495      float oldepos=current_position[E_AXIS];
1496      float oldedes=destination[E_AXIS];
1497      plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], 
1498                       current_position[E_AXIS]+EXTRUDER_RUNOUT_EXTRUDE*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], 
1499                       EXTRUDER_RUNOUT_SPEED/60.*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], active_extruder);
1500      current_position[E_AXIS]=oldepos;
1501      destination[E_AXIS]=oldedes;
1502      plan_set_e_position(oldepos);
1503      previous_millis_cmd=millis();
1504      st_synchronize();
1505      WRITE(E0_ENABLE_PIN,oldstatus);
1506     }
1507   #endif
1508   check_axes_activity();
1509 }
1510
1511 void kill()
1512 {
1513   cli(); // Stop interrupts
1514   disable_heater();
1515
1516   disable_x();
1517   disable_y();
1518   disable_z();
1519   disable_e0();
1520   disable_e1();
1521   disable_e2();
1522   
1523   if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT);
1524   SERIAL_ERROR_START;
1525   SERIAL_ERRORLNPGM(MSG_ERR_KILLED);
1526   LCD_MESSAGEPGM(MSG_KILLED);
1527   suicide();
1528   while(1); // Wait for reset
1529 }
1530
1531 void Stop()
1532 {
1533   disable_heater();
1534   if(Stopped == false) {
1535     Stopped = true;
1536     Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart
1537     SERIAL_ERROR_START;
1538     SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
1539     LCD_MESSAGEPGM(MSG_STOPPED);
1540   }
1541 }
1542
1543 bool IsStopped() { return Stopped; };
1544
1545 #ifdef FAST_PWM_FAN
1546 void setPwmFrequency(uint8_t pin, int val)
1547 {
1548   val &= 0x07;
1549   switch(digitalPinToTimer(pin))
1550   {
1551  
1552     #if defined(TCCR0A)
1553     case TIMER0A:
1554     case TIMER0B:
1555          TCCR0B &= ~(CS00 | CS01 | CS02);
1556          TCCR0B |= val;
1557          break;
1558     #endif
1559
1560     #if defined(TCCR1A)
1561     case TIMER1A:
1562     case TIMER1B:
1563          TCCR1B &= ~(CS10 | CS11 | CS12);
1564          TCCR1B |= val;
1565          break;
1566     #endif
1567
1568     #if defined(TCCR2)
1569     case TIMER2:
1570     case TIMER2:
1571          TCCR2 &= ~(CS10 | CS11 | CS12);
1572          TCCR2 |= val;
1573          break;
1574     #endif
1575
1576     #if defined(TCCR2A)
1577     case TIMER2A:
1578     case TIMER2B:
1579          TCCR2B &= ~(CS20 | CS21 | CS22);
1580          TCCR2B |= val;
1581          break;
1582     #endif
1583
1584     #if defined(TCCR3A)
1585     case TIMER3A:
1586     case TIMER3B:
1587     case TIMER3C:
1588          TCCR3B &= ~(CS30 | CS31 | CS32);
1589          TCCR3B |= val;
1590          break;
1591     #endif
1592
1593     #if defined(TCCR4A) 
1594     case TIMER4A:
1595     case TIMER4B:
1596     case TIMER4C:
1597          TCCR4B &= ~(CS40 | CS41 | CS42);
1598          TCCR4B |= val;
1599          break;
1600    #endif
1601
1602     #if defined(TCCR5A) 
1603     case TIMER5A:
1604     case TIMER5B:
1605     case TIMER5C:
1606          TCCR5B &= ~(CS50 | CS51 | CS52);
1607          TCCR5B |= val;
1608          break;
1609    #endif
1610
1611   }
1612 }
1613 #endif
1614
1615