Advertisement
Guest User

Untitled

a guest
May 9th, 2014
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 201.51 KB | None | 0 0
  1. [quote]
  2. [color=#7E7E7E]/* -*- c++ -*- */[/color]
  3.  
  4. [color=#7E7E7E]/*[/color]
  5. [color=#7E7E7E]    Reprap firmware based on Sprinter and grbl.[/color]
  6. [color=#7E7E7E] Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm[/color]
  7.  
  8. [color=#7E7E7E] This program is free software: you can redistribute it and/or modify[/color]
  9. [color=#7E7E7E] it under the terms of the GNU General Public License as published by[/color]
  10. [color=#7E7E7E] the Free Software Foundation, either version 3 of the License, or[/color]
  11. [color=#7E7E7E] (at your option) any later version.[/color]
  12.  
  13. [color=#7E7E7E] This program is distributed in the hope that it will be useful,[/color]
  14. [color=#7E7E7E] but WITHOUT ANY WARRANTY; without even the implied warranty of[/color]
  15. [color=#7E7E7E] MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the[/color]
  16. [color=#7E7E7E] GNU General Public License for more details.[/color]
  17.  
  18. [color=#7E7E7E] You should have received a copy of the GNU General Public License[/color]
  19. [color=#7E7E7E] along with this program.  If not, see <http://www.gnu.org/licenses/>.[/color]
  20. [color=#7E7E7E] */[/color]
  21.  
  22. [color=#7E7E7E]/*[/color]
  23. [color=#7E7E7E] This firmware is a mashup between Sprinter and grbl.[/color]
  24. [color=#7E7E7E]  (https://github.com/kliment/Sprinter)[/color]
  25. [color=#7E7E7E]  (https://github.com/simen/grbl/tree)[/color]
  26.  
  27. [color=#7E7E7E] It has preliminary support for Matthew Roberts advance algorithm[/color]
  28. [color=#7E7E7E]    http://reprap.org/pipermail/reprap-dev/2011-May/003323.html[/color]
  29. [color=#7E7E7E] */[/color]
  30.  
  31. #include [color=#006699]"Marlin.h"[/color]
  32.  
  33. #ifdef ENABLE_AUTO_BED_LEVELING
  34. #include [color=#006699]"vector_3.h"[/color]
  35.   #ifdef ACCURATE_BED_LEVELING
  36.     #include [color=#006699]"qr_solve.h"[/color]
  37.   #endif
  38. #endif [color=#7E7E7E]// ENABLE_AUTO_BED_LEVELING[/color]
  39.  
  40. #include [color=#006699]"ultralcd.h"[/color]
  41. #include [color=#006699]"planner.h"[/color]
  42. #include [color=#006699]"stepper.h"[/color]
  43. #include [color=#006699]"temperature.h"[/color]
  44. #include [color=#006699]"motion_control.h"[/color]
  45. #include [color=#006699]"cardreader.h"[/color]
  46. #include [color=#006699]"watchdog.h"[/color]
  47. #include [color=#006699]"ConfigurationStore.h"[/color]
  48. #include [color=#006699]"language.h"[/color]
  49. #include [color=#006699]"pins_arduino.h"[/color]
  50. #include [color=#006699]"math.h"[/color]
  51.  
  52. #ifdef BLINKM
  53. #include [color=#006699]"BlinkM.h"[/color]
  54. #include [color=#006699]"Wire.h"[/color]
  55. #endif
  56.  
  57. #if NUM_SERVOS > 0
  58. #include [color=#006699]"Servo.h"[/color]
  59. #endif
  60.  
  61. #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
  62. #include <[color=#CC6600]SPI[/color].h>
  63. #endif
  64.  
  65. #define VERSION_STRING  [color=#006699]"1.0.0"[/color]
  66.  
  67. [color=#7E7E7E]// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html[/color]
  68. [color=#7E7E7E]// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes[/color]
  69.  
  70. [color=#7E7E7E]//Implemented Codes[/color]
  71. [color=#7E7E7E]//-------------------[/color]
  72. [color=#7E7E7E]// G0  -> G1[/color]
  73. [color=#7E7E7E]// G1  - Coordinated Movement X Y Z E[/color]
  74. [color=#7E7E7E]// G2  - CW ARC[/color]
  75. [color=#7E7E7E]// G3  - CCW ARC[/color]
  76. [color=#7E7E7E]// G4  - Dwell S<seconds> or P<milliseconds>[/color]
  77. [color=#7E7E7E]// G10 - retract filament according to settings of M207[/color]
  78. [color=#7E7E7E]// G11 - retract recover filament according to settings of M208[/color]
  79. [color=#7E7E7E]// G28 - Home all Axis[/color]
  80. [color=#7E7E7E]// G29 - Detailed Z-Probe, probes the bed at 3 points.  You must de at the home position for this to work correctly.[/color]
  81. [color=#7E7E7E]// G30 - Single Z Probe, probes bed at current XY location.[/color]
  82. [color=#7E7E7E]// G90 - Use Absolute Coordinates[/color]
  83. [color=#7E7E7E]// G91 - Use Relative Coordinates[/color]
  84. [color=#7E7E7E]// G92 - Set current position to cordinates given[/color]
  85.  
  86. [color=#7E7E7E]// M Codes[/color]
  87. [color=#7E7E7E]// M0   - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)[/color]
  88. [color=#7E7E7E]// M1   - Same as M0[/color]
  89. [color=#7E7E7E]// M17  - Enable/Power all stepper motors[/color]
  90. [color=#7E7E7E]// M18  - Disable all stepper motors; same as M84[/color]
  91. [color=#7E7E7E]// M20  - List SD card[/color]
  92. [color=#7E7E7E]// M21  - Init SD card[/color]
  93. [color=#7E7E7E]// M22  - Release SD card[/color]
  94. [color=#7E7E7E]// M23  - Select SD file (M23 filename.g)[/color]
  95. [color=#7E7E7E]// M24  - Start/resume SD print[/color]
  96. [color=#7E7E7E]// M25  - Pause SD print[/color]
  97. [color=#7E7E7E]// M26  - Set SD position in bytes (M26 S12345)[/color]
  98. [color=#7E7E7E]// M27  - Report SD print status[/color]
  99. [color=#7E7E7E]// M28  - Start SD write (M28 filename.g)[/color]
  100. [color=#7E7E7E]// M29  - Stop SD write[/color]
  101. [color=#7E7E7E]// M30  - Delete file from SD (M30 filename.g)[/color]
  102. [color=#7E7E7E]// M31  - Output time since last M109 or SD card start to serial[/color]
  103. [color=#7E7E7E]// M32  - Select file and start SD print (Can be used _while_ printing from SD card files):[/color]
  104. [color=#7E7E7E]//        syntax "M32 /path/filename#", or "M32 S<startpos bytes> !filename#"[/color]
  105. [color=#7E7E7E]//        Call gcode file : "M32 P !filename#" and return to caller file after finishing (simiarl to #include).[/color]
  106. [color=#7E7E7E]//        The '#' is necessary when calling from within sd files, as it stops buffer prereading[/color]
  107. [color=#7E7E7E]// M42  - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used.[/color]
  108. [color=#7E7E7E]// M80  - Turn on Power Supply[/color]
  109. [color=#7E7E7E]// M81  - Turn off Power Supply[/color]
  110. [color=#7E7E7E]// M82  - Set E codes absolute (default)[/color]
  111. [color=#7E7E7E]// M83  - Set E codes relative while in Absolute Coordinates (G90) mode[/color]
  112. [color=#7E7E7E]// M84  - Disable steppers until next move,[/color]
  113. [color=#7E7E7E]//        or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled.  S0 to disable the timeout.[/color]
  114. [color=#7E7E7E]// M85  - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)[/color]
  115. [color=#7E7E7E]// M92  - Set axis_steps_per_unit - same syntax as G92[/color]
  116. [color=#7E7E7E]// M104 - Set extruder target temp[/color]
  117. [color=#7E7E7E]// M105 - Read current temp[/color]
  118. [color=#7E7E7E]// M106 - Fan on[/color]
  119. [color=#7E7E7E]// M107 - Fan off[/color]
  120. [color=#7E7E7E]// M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating[/color]
  121. [color=#7E7E7E]//        Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling[/color]
  122. [color=#7E7E7E]// M114 - Output current position to serial port[/color]
  123. [color=#7E7E7E]// M115 - Capabilities string[/color]
  124. [color=#7E7E7E]// M117 - display message[/color]
  125. [color=#7E7E7E]// M119 - Output Endstop status to serial port[/color]
  126. [color=#7E7E7E]// M126 - Solenoid Air Valve Open (BariCUDA support by jmil)[/color]
  127. [color=#7E7E7E]// M127 - Solenoid Air Valve Closed (BariCUDA vent to atmospheric pressure by jmil)[/color]
  128. [color=#7E7E7E]// M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil)[/color]
  129. [color=#7E7E7E]// M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)[/color]
  130. [color=#7E7E7E]// M140 - Set bed target temp[/color]
  131. [color=#7E7E7E]// M150 - Set BlinkM Colour Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.[/color]
  132. [color=#7E7E7E]// M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating[/color]
  133. [color=#7E7E7E]//        Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling[/color]
  134. [color=#7E7E7E]// M200 D<millimeters>- set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).[/color]
  135. [color=#7E7E7E]// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)[/color]
  136. [color=#7E7E7E]// M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!![/color]
  137. [color=#7E7E7E]// M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec[/color]
  138. [color=#7E7E7E]// 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[/color]
  139. [color=#7E7E7E]// 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[/color]
  140. [color=#7E7E7E]// M206 - set additional homeing offset[/color]
  141. [color=#7E7E7E]// M207 - set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop], stays in mm regardless of M200 setting[/color]
  142. [color=#7E7E7E]// M208 - set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/min][/color]
  143. [color=#7E7E7E]// M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.[/color]
  144. [color=#7E7E7E]// M218 - set hotend offset (in mm): T<extruder_number> X<offset_on_X> Y<offset_on_Y>[/color]
  145. [color=#7E7E7E]// M220 S<factor in percent>- set speed factor override percentage[/color]
  146. [color=#7E7E7E]// M221 S<factor in percent>- set extrude factor override percentage[/color]
  147. [color=#7E7E7E]// M226 P<pin number> S<pin state>- Wait until the specified pin reaches the state required[/color]
  148. [color=#7E7E7E]// M240 - Trigger a camera to take a photograph[/color]
  149. [color=#7E7E7E]// M250 - Set LCD contrast C<contrast value> (value 0..63)[/color]
  150. [color=#7E7E7E]// M280 - set servo position absolute. P: servo index, S: angle or microseconds[/color]
  151. [color=#7E7E7E]// M300 - Play beepsound S<frequency Hz> P<duration ms>[/color]
  152. [color=#7E7E7E]// M301 - Set PID parameters P I and D[/color]
  153. [color=#7E7E7E]// M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.[/color]
  154. [color=#7E7E7E]// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)[/color]
  155. [color=#7E7E7E]// M304 - Set bed PID parameters P I and D[/color]
  156. [color=#7E7E7E]// M400 - Finish all moves[/color]
  157. [color=#7E7E7E]// M401 - Lower z-probe if present[/color]
  158. [color=#7E7E7E]// M402 - Raise z-probe if present[/color]
  159. [color=#7E7E7E]// M500 - stores paramters in EEPROM[/color]
  160. [color=#7E7E7E]// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).[/color]
  161. [color=#7E7E7E]// M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.[/color]
  162. [color=#7E7E7E]// M503 - print the current settings (from memory not from eeprom)[/color]
  163. [color=#7E7E7E]// M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)[/color]
  164. [color=#7E7E7E]// M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal][/color]
  165. [color=#7E7E7E]// M666 - set delta endstop adjustemnt[/color]
  166. [color=#7E7E7E]// M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ][/color]
  167. [color=#7E7E7E]// M907 - Set digital trimpot motor current using axis codes.[/color]
  168. [color=#7E7E7E]// M908 - Control digital trimpot directly.[/color]
  169. [color=#7E7E7E]// M350 - Set microstepping mode.[/color]
  170. [color=#7E7E7E]// M351 - Toggle MS1 MS2 pins directly.[/color]
  171. [color=#7E7E7E]// M928 - Start SD logging (M928 filename.g) - ended by M29[/color]
  172. [color=#7E7E7E]// M999 - Restart after being stopped by error[/color]
  173.  
  174. [color=#7E7E7E]//Stepper Movement Variables[/color]
  175.  
  176. [color=#7E7E7E]//===========================================================================[/color]
  177. [color=#7E7E7E]//=============================imported variables============================[/color]
  178. [color=#7E7E7E]//===========================================================================[/color]
  179.  
  180.  
  181. [color=#7E7E7E]//===========================================================================[/color]
  182. [color=#7E7E7E]//=============================public variables=============================[/color]
  183. [color=#7E7E7E]//===========================================================================[/color]
  184. #ifdef SDSUPPORT
  185. CardReader card;
  186. #endif
  187. [color=#CC6600]float[/color] homing_feedrate[] = HOMING_FEEDRATE;
  188. bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
  189. [color=#CC6600]int[/color] feedmultiply=100; [color=#7E7E7E]//100->1 200->2[/color]
  190. [color=#CC6600]int[/color] saved_feedmultiply;
  191. [color=#CC6600]int[/color] extrudemultiply=100; [color=#7E7E7E]//100->1 200->2[/color]
  192. [color=#CC6600]float[/color] volumetric_multiplier[EXTRUDERS] = {1.0
  193.   #if EXTRUDERS > 1
  194.     , 1.0
  195.     #if EXTRUDERS > 2
  196.       , 1.0
  197.     #endif
  198.   #endif
  199. };
  200. [color=#CC6600]float[/color] current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 };
  201. [color=#CC6600]float[/color] add_homeing[3]={0,0,0};
  202. #ifdef DELTA
  203. [color=#CC6600]float[/color] endstop_adj[3]={0,0,0};
  204. #endif
  205. [color=#CC6600]float[/color] min_pos[3] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS };
  206. [color=#CC6600]float[/color] max_pos[3] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS };
  207. bool axis_known_position[3] = {[color=#CC6600]false[/color], [color=#CC6600]false[/color], [color=#CC6600]false[/color]};
  208. [color=#CC6600]float[/color] zprobe_zoffset;
  209.  
  210. [color=#7E7E7E]// Extruder offset[/color]
  211. #if EXTRUDERS > 1
  212. #ifndef DUAL_X_CARRIAGE
  213.   #define NUM_EXTRUDER_OFFSETS 2 [color=#7E7E7E]// only in XY plane[/color]
  214. #else
  215.   #define NUM_EXTRUDER_OFFSETS 3 [color=#7E7E7E]// supports offsets in XYZ plane[/color]
  216. #endif
  217. [color=#CC6600]float[/color] extruder_offset[NUM_EXTRUDER_OFFSETS][EXTRUDERS] = {
  218. #if defined(EXTRUDER_OFFSET_X) && defined(EXTRUDER_OFFSET_Y)
  219.   EXTRUDER_OFFSET_X, EXTRUDER_OFFSET_Y
  220. #endif
  221. };
  222. #endif
  223. uint8_t active_extruder = 0;
  224. [color=#CC6600]int[/color] fanSpeed=0;
  225. #ifdef SERVO_ENDSTOPS
  226.   [color=#CC6600]int[/color] servo_endstops[] = SERVO_ENDSTOPS;
  227.   [color=#CC6600]int[/color] servo_endstop_angles[] = SERVO_ENDSTOP_ANGLES;
  228. #endif
  229. #ifdef BARICUDA
  230. [color=#CC6600]int[/color] ValvePressure=0;
  231. [color=#CC6600]int[/color] EtoPPressure=0;
  232. #endif
  233.  
  234. #ifdef FWRETRACT
  235.   bool autoretract_enabled=[color=#CC6600]true[/color];
  236.   bool retracted=[color=#CC6600]false[/color];
  237.   [color=#CC6600]float[/color] retract_length=3, retract_feedrate=17*60, retract_zlift=0.8;
  238.   [color=#CC6600]float[/color] retract_recover_length=0, retract_recover_feedrate=8*60;
  239. #endif
  240.  
  241. #ifdef ULTIPANEL
  242.   #ifdef PS_DEFAULT_OFF
  243.     bool powersupply = [color=#CC6600]false[/color];
  244.   #else
  245.   bool powersupply = [color=#CC6600]true[/color];
  246.   #endif
  247. #endif
  248.  
  249. #ifdef DELTA
  250. [color=#CC6600]float[/color] delta[3] = {0.0, 0.0, 0.0};
  251. #endif
  252.  
  253.  
  254. [color=#7E7E7E]//===========================================================================[/color]
  255. [color=#7E7E7E]//=============================private variables=============================[/color]
  256. [color=#7E7E7E]//===========================================================================[/color]
  257. [color=#CC6600]const[/color] [color=#CC6600]char[/color] axis_codes[NUM_AXIS] = {[color=#006699]'X'[/color], [color=#006699]'Y'[/color], [color=#006699]'Z'[/color], [color=#006699]'E'[/color]};
  258. [color=#CC6600]static[/color] [color=#CC6600]float[/color] destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0};
  259. [color=#CC6600]static[/color] [color=#CC6600]float[/color] offset[3] = {0.0, 0.0, 0.0};
  260. [color=#CC6600]static[/color] bool home_all_axis = [color=#CC6600]true[/color];
  261. [color=#CC6600]static[/color] [color=#CC6600]float[/color] feedrate = 1500.0, next_feedrate, saved_feedrate;
  262. [color=#CC6600]static[/color] [color=#CC6600]long[/color] gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
  263.  
  264. [color=#CC6600]static[/color] bool relative_mode = [color=#CC6600]false[/color]; [color=#7E7E7E]//Determines Absolute or Relative Coordinates[/color]
  265.  
  266. [color=#CC6600]static[/color] [color=#CC6600]char[/color] cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
  267. [color=#CC6600]static[/color] bool fromsd[BUFSIZE];
  268. [color=#CC6600]static[/color] [color=#CC6600]int[/color] bufindr = 0;
  269. [color=#CC6600]static[/color] [color=#CC6600]int[/color] bufindw = 0;
  270. [color=#CC6600]static[/color] [color=#CC6600]int[/color] buflen = 0;
  271. [color=#7E7E7E]//static int i = 0;[/color]
  272. [color=#CC6600]static[/color] [color=#CC6600]char[/color] serial_char;
  273. [color=#CC6600]static[/color] [color=#CC6600]int[/color] serial_count = 0;
  274. [color=#CC6600]static[/color] [color=#CC6600]boolean[/color] comment_mode = [color=#CC6600]false[/color];
  275. [color=#CC6600]static[/color] [color=#CC6600]char[/color] *strchr_pointer; [color=#7E7E7E]// just a pointer to find chars in the cmd string like X, Y, Z, E, etc[/color]
  276.  
  277. [color=#CC6600]const[/color] [color=#CC6600]int[/color] sensitive_pins[] = SENSITIVE_PINS; [color=#7E7E7E]// Sensitive pin list for M42[/color]
  278.  
  279. [color=#7E7E7E]//static float tt = 0;[/color]
  280. [color=#7E7E7E]//static float bt = 0;[/color]
  281.  
  282. [color=#7E7E7E]//Inactivity shutdown variables[/color]
  283. [color=#CC6600]static[/color] [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] previous_millis_cmd = 0;
  284. [color=#CC6600]static[/color] [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] max_inactive_time = 0;
  285. [color=#CC6600]static[/color] [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l;
  286.  
  287. [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] starttime=0;
  288. [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] stoptime=0;
  289.  
  290. [color=#CC6600]static[/color] uint8_t tmp_extruder;
  291.  
  292.  
  293. bool Stopped=[color=#CC6600]false[/color];
  294.  
  295. #if NUM_SERVOS > 0
  296.   [color=#CC6600]Servo[/color] servos[NUM_SERVOS];
  297. #endif
  298.  
  299. bool CooldownNoWait = [color=#CC6600]true[/color];
  300. bool target_direction;
  301.  
  302. [color=#7E7E7E]//===========================================================================[/color]
  303. [color=#7E7E7E]//=============================ROUTINES=============================[/color]
  304. [color=#7E7E7E]//===========================================================================[/color]
  305.  
  306. [color=#CC6600]void[/color] get_arc_coordinates();
  307. bool setTargetedHotend([color=#CC6600]int[/color] code);
  308.  
  309. [color=#CC6600]void[/color] serial_echopair_P([color=#CC6600]const[/color] [color=#CC6600]char[/color] *s_P, [color=#CC6600]float[/color] v)
  310.     { serialprintPGM(s_P); SERIAL_ECHO(v); }
  311. [color=#CC6600]void[/color] serial_echopair_P([color=#CC6600]const[/color] [color=#CC6600]char[/color] *s_P, [color=#CC6600]double[/color] v)
  312.     { serialprintPGM(s_P); SERIAL_ECHO(v); }
  313. [color=#CC6600]void[/color] serial_echopair_P([color=#CC6600]const[/color] [color=#CC6600]char[/color] *s_P, [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] v)
  314.     { serialprintPGM(s_P); SERIAL_ECHO(v); }
  315.  
  316. extern [color=#006699]"C"[/color]{
  317.   extern [color=#CC6600]unsigned[/color] [color=#CC6600]int[/color] __bss_end;
  318.   extern [color=#CC6600]unsigned[/color] [color=#CC6600]int[/color] __heap_start;
  319.   extern [color=#CC6600]void[/color] *__brkval;
  320.  
  321.   [color=#CC6600]int[/color] freeMemory() {
  322.     [color=#CC6600]int[/color] free_memory;
  323.  
  324.     [color=#CC6600]if[/color](([color=#CC6600]int[/color])__brkval == 0)
  325.       free_memory = (([color=#CC6600]int[/color])&free_memory) - (([color=#CC6600]int[/color])&__bss_end);
  326.     [color=#CC6600]else[/color]
  327.       free_memory = (([color=#CC6600]int[/color])&free_memory) - (([color=#CC6600]int[/color])__brkval);
  328.  
  329.     [color=#CC6600]return[/color] free_memory;
  330.   }
  331. }
  332.  
  333. [color=#7E7E7E]//adds an command to the main command buffer[/color]
  334. [color=#7E7E7E]//thats really done in a non-safe way.[/color]
  335. [color=#7E7E7E]//needs overworking someday[/color]
  336. [color=#CC6600]void[/color] enquecommand([color=#CC6600]const[/color] [color=#CC6600]char[/color] *cmd)
  337. {
  338.   [color=#CC6600]if[/color](buflen < BUFSIZE)
  339.   {
  340.     [color=#7E7E7E]//this is dangerous if a mixing of serial and this happsens[/color]
  341.     strcpy(&(cmdbuffer[bufindw][0]),cmd);
  342.     SERIAL_ECHO_START;
  343.     SERIAL_ECHOPGM([color=#006699]"enqueing \""[/color]);
  344.     SERIAL_ECHO(cmdbuffer[bufindw]);
  345.     SERIAL_ECHOLNPGM([color=#006699]"\""[/color]);
  346.     bufindw= (bufindw + 1)%BUFSIZE;
  347.     buflen += 1;
  348.   }
  349. }
  350.  
  351. [color=#CC6600]void[/color] enquecommand_P([color=#CC6600]const[/color] [color=#CC6600]char[/color] *cmd)
  352. {
  353.   [color=#CC6600]if[/color](buflen < BUFSIZE)
  354.   {
  355.     [color=#7E7E7E]//this is dangerous if a mixing of serial and this happsens[/color]
  356.     strcpy_P(&(cmdbuffer[bufindw][0]),cmd);
  357.     SERIAL_ECHO_START;
  358.     SERIAL_ECHOPGM([color=#006699]"enqueing \""[/color]);
  359.     SERIAL_ECHO(cmdbuffer[bufindw]);
  360.     SERIAL_ECHOLNPGM([color=#006699]"\""[/color]);
  361.     bufindw= (bufindw + 1)%BUFSIZE;
  362.     buflen += 1;
  363.   }
  364. }
  365.  
  366. [color=#CC6600]void[/color] setup_killpin()
  367. {
  368.   #if defined(KILL_PIN) && KILL_PIN > -1
  369.     [color=#CC6600]pinMode[/color](KILL_PIN,[color=#006699]INPUT[/color]);
  370.     WRITE(KILL_PIN,[color=#006699]HIGH[/color]);
  371.   #endif
  372. }
  373.  
  374. [color=#CC6600]void[/color] setup_photpin()
  375. {
  376.   #if defined(PHOTOGRAPH_PIN) && PHOTOGRAPH_PIN > -1
  377.     SET_OUTPUT(PHOTOGRAPH_PIN);
  378.     WRITE(PHOTOGRAPH_PIN, [color=#006699]LOW[/color]);
  379.   #endif
  380. }
  381.  
  382. [color=#CC6600]void[/color] setup_powerhold()
  383. {
  384.   #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1
  385.     SET_OUTPUT(SUICIDE_PIN);
  386.     WRITE(SUICIDE_PIN, [color=#006699]HIGH[/color]);
  387.   #endif
  388.   #if defined(PS_ON_PIN) && PS_ON_PIN > -1
  389.     SET_OUTPUT(PS_ON_PIN);
  390. #if defined(PS_DEFAULT_OFF)
  391.   WRITE(PS_ON_PIN, PS_ON_ASLEEP);
  392.     #else
  393.   WRITE(PS_ON_PIN, PS_ON_AWAKE);
  394. #endif
  395.   #endif
  396. }
  397.  
  398. [color=#CC6600]void[/color] suicide()
  399. {
  400.   #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1
  401.     SET_OUTPUT(SUICIDE_PIN);
  402.     WRITE(SUICIDE_PIN, [color=#006699]LOW[/color]);
  403.   #endif
  404. }
  405.  
  406. [color=#CC6600]void[/color] servo_init()
  407. {
  408.   #if (NUM_SERVOS >= 1) && defined(SERVO0_PIN) && (SERVO0_PIN > -1)
  409.     servos[0].[color=#CC6600]attach[/color](SERVO0_PIN);
  410.   #endif
  411.   #if (NUM_SERVOS >= 2) && defined(SERVO1_PIN) && (SERVO1_PIN > -1)
  412.     servos[1].[color=#CC6600]attach[/color](SERVO1_PIN);
  413.   #endif
  414.   #if (NUM_SERVOS >= 3) && defined(SERVO2_PIN) && (SERVO2_PIN > -1)
  415.     servos[2].[color=#CC6600]attach[/color](SERVO2_PIN);
  416.   #endif
  417.   #if (NUM_SERVOS >= 4) && defined(SERVO3_PIN) && (SERVO3_PIN > -1)
  418.     servos[3].[color=#CC6600]attach[/color](SERVO3_PIN);
  419.   #endif
  420.   #if (NUM_SERVOS >= 5)
  421.     #error [color=#006699]"TODO: enter initalisation code for more servos"[/color]
  422.   #endif
  423.  
  424.   [color=#7E7E7E]// Set position of Servo Endstops that are defined[/color]
  425.   #ifdef SERVO_ENDSTOPS
  426.   [color=#CC6600]for[/color](int8_t i = 0; i < 3; i++)
  427.   {
  428.     [color=#CC6600]if[/color](servo_endstops[i] > -1) {
  429.       servos[servo_endstops[i]].[color=#CC6600]write[/color](servo_endstop_angles[i * 2 + 1]);
  430.     }
  431.   }
  432.   #endif
  433.  
  434.   #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  435.   [color=#CC6600]delay[/color](PROBE_SERVO_DEACTIVATION_DELAY);
  436.   servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]detach[/color]();
  437.   #endif
  438. }
  439.  
  440. [color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color]()
  441. {
  442.   setup_killpin();
  443.   setup_powerhold();
  444.   MYSERIAL.[color=#CC6600]begin[/color](BAUDRATE);
  445.   SERIAL_PROTOCOLLNPGM([color=#006699]"start"[/color]);
  446.   SERIAL_ECHO_START;
  447.  
  448.   [color=#7E7E7E]// Check startup - does nothing if bootloader sets MCUSR to 0[/color]
  449.   [color=#CC6600]byte[/color] mcu = MCUSR;
  450.   [color=#CC6600]if[/color](mcu & 1) SERIAL_ECHOLNPGM(MSG_POWERUP);
  451.   [color=#CC6600]if[/color](mcu & 2) SERIAL_ECHOLNPGM(MSG_EXTERNAL_RESET);
  452.   [color=#CC6600]if[/color](mcu & 4) SERIAL_ECHOLNPGM(MSG_BROWNOUT_RESET);
  453.   [color=#CC6600]if[/color](mcu & 8) SERIAL_ECHOLNPGM(MSG_WATCHDOG_RESET);
  454.   [color=#CC6600]if[/color](mcu & 32) SERIAL_ECHOLNPGM(MSG_SOFTWARE_RESET);
  455.   MCUSR=0;
  456.  
  457.   SERIAL_ECHOPGM(MSG_MARLIN);
  458.   SERIAL_ECHOLNPGM(VERSION_STRING);
  459.   #ifdef STRING_VERSION_CONFIG_H
  460.     #ifdef STRING_CONFIG_H_AUTHOR
  461.       SERIAL_ECHO_START;
  462.       SERIAL_ECHOPGM(MSG_CONFIGURATION_VER);
  463.       SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H);
  464.       SERIAL_ECHOPGM(MSG_AUTHOR);
  465.       SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR);
  466.       SERIAL_ECHOPGM([color=#006699]"Compiled: "[/color]);
  467.       SERIAL_ECHOLNPGM(__DATE__);
  468.     #endif
  469.   #endif
  470.   SERIAL_ECHO_START;
  471.   SERIAL_ECHOPGM(MSG_FREE_MEMORY);
  472.   SERIAL_ECHO(freeMemory());
  473.   SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES);
  474.   SERIAL_ECHOLN(([color=#CC6600]int[/color])sizeof(block_t)*BLOCK_BUFFER_SIZE);
  475.   [color=#CC6600]for[/color](int8_t i = 0; i < BUFSIZE; i++)
  476.   {
  477.     fromsd[i] = [color=#CC6600]false[/color];
  478.   }
  479.  
  480.   [color=#7E7E7E]// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)[/color]
  481.   Config_RetrieveSettings();
  482.  
  483.   tp_init();    [color=#7E7E7E]// Initialize temperature loop[/color]
  484.   plan_init();  [color=#7E7E7E]// Initialize planner;[/color]
  485.   watchdog_init();
  486.   st_init();    [color=#7E7E7E]// Initialize stepper, this enables interrupts![/color]
  487.   setup_photpin();
  488.   servo_init();
  489.  
  490.   lcd_init();
  491.   _delay_ms(1000); [color=#7E7E7E]// wait 1sec to display the splash screen[/color]
  492.  
  493.   #if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
  494.     SET_OUTPUT(CONTROLLERFAN_PIN); [color=#7E7E7E]//Set pin used for driver cooling fan[/color]
  495.   #endif
  496.  
  497.   #ifdef DIGIPOT_I2C
  498.     digipot_i2c_init();
  499.   #endif
  500. }
  501.  
  502.  
  503. [color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color]()
  504. {
  505.   [color=#CC6600]if[/color](buflen < (BUFSIZE-1))
  506.     get_command();
  507.   #ifdef SDSUPPORT
  508.   card.checkautostart([color=#CC6600]false[/color]);
  509.   #endif
  510.   [color=#CC6600]if[/color](buflen)
  511.   {
  512.     #ifdef SDSUPPORT
  513.       [color=#CC6600]if[/color](card.saving)
  514.       {
  515.         [color=#CC6600]if[/color](strstr_P(cmdbuffer[bufindr], PSTR([color=#006699]"M29"[/color])) == NULL)
  516.         {
  517.           card.write_command(cmdbuffer[bufindr]);
  518.           [color=#CC6600]if[/color](card.logging)
  519.           {
  520.             process_commands();
  521.           }
  522.           [color=#CC6600]else[/color]
  523.           {
  524.             SERIAL_PROTOCOLLNPGM(MSG_OK);
  525.           }
  526.         }
  527.         [color=#CC6600]else[/color]
  528.         {
  529.           card.closefile();
  530.           SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED);
  531.         }
  532.       }
  533.       [color=#CC6600]else[/color]
  534.       {
  535.         process_commands();
  536.       }
  537.     #else
  538.       process_commands();
  539.     #endif [color=#7E7E7E]//SDSUPPORT[/color]
  540.     buflen = (buflen-1);
  541.     bufindr = (bufindr + 1)%BUFSIZE;
  542.   }
  543.   [color=#7E7E7E]//check heater every n milliseconds[/color]
  544.   manage_heater();
  545.   manage_inactivity();
  546.   checkHitEndstops();
  547.   lcd_update();
  548. }
  549.  
  550. [color=#CC6600]void[/color] get_command()
  551. {
  552.   [color=#CC6600]while[/color]( MYSERIAL.[color=#CC6600]available[/color]() > 0 && buflen < BUFSIZE) {
  553.     serial_char = MYSERIAL.[color=#CC6600]read[/color]();
  554.     [color=#CC6600]if[/color](serial_char == [color=#006699]'\n'[/color] ||
  555.        serial_char == [color=#006699]'\r'[/color] ||
  556.        (serial_char == [color=#006699]':'[/color] && comment_mode == [color=#CC6600]false[/color]) ||
  557.        serial_count >= (MAX_CMD_SIZE - 1) )
  558.     {
  559.       [color=#CC6600]if[/color](!serial_count) { [color=#7E7E7E]//if empty line[/color]
  560.         comment_mode = [color=#CC6600]false[/color]; [color=#7E7E7E]//for new command[/color]
  561.         [color=#CC6600]return[/color];
  562.       }
  563.       cmdbuffer[bufindw][serial_count] = 0; [color=#7E7E7E]//terminate string[/color]
  564.       [color=#CC6600]if[/color](!comment_mode){
  565.         comment_mode = [color=#CC6600]false[/color]; [color=#7E7E7E]//for new command[/color]
  566.         fromsd[bufindw] = [color=#CC6600]false[/color];
  567.         [color=#CC6600]if[/color](strchr(cmdbuffer[bufindw], [color=#006699]'N'[/color]) != NULL)
  568.         {
  569.           strchr_pointer = strchr(cmdbuffer[bufindw], [color=#006699]'N'[/color]);
  570.           gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));
  571.           [color=#CC6600]if[/color](gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer[bufindw], PSTR([color=#006699]"M110"[/color])) == NULL) ) {
  572.             SERIAL_ERROR_START;
  573.             SERIAL_ERRORPGM(MSG_ERR_LINE_NO);
  574.             SERIAL_ERRORLN(gcode_LastN);
  575.             [color=#7E7E7E]//Serial.println(gcode_N);[/color]
  576.             FlushSerialRequestResend();
  577.             serial_count = 0;
  578.             [color=#CC6600]return[/color];
  579.           }
  580.  
  581.           [color=#CC6600]if[/color](strchr(cmdbuffer[bufindw], [color=#006699]'*'[/color]) != NULL)
  582.           {
  583.             [color=#CC6600]byte[/color] checksum = 0;
  584.             [color=#CC6600]byte[/color] count = 0;
  585.             [color=#CC6600]while[/color](cmdbuffer[bufindw][count] != [color=#006699]'*'[/color]) checksum = checksum^cmdbuffer[bufindw][count++];
  586.             strchr_pointer = strchr(cmdbuffer[bufindw], [color=#006699]'*'[/color]);
  587.  
  588.             [color=#CC6600]if[/color]( ([color=#CC6600]int[/color])(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) {
  589.               SERIAL_ERROR_START;
  590.               SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH);
  591.               SERIAL_ERRORLN(gcode_LastN);
  592.               FlushSerialRequestResend();
  593.               serial_count = 0;
  594.               [color=#CC6600]return[/color];
  595.             }
  596.             [color=#7E7E7E]//if no errors, continue parsing[/color]
  597.           }
  598.           [color=#CC6600]else[/color]
  599.           {
  600.             SERIAL_ERROR_START;
  601.             SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM);
  602.             SERIAL_ERRORLN(gcode_LastN);
  603.             FlushSerialRequestResend();
  604.             serial_count = 0;
  605.             [color=#CC6600]return[/color];
  606.           }
  607.  
  608.           gcode_LastN = gcode_N;
  609.           [color=#7E7E7E]//if no errors, continue parsing[/color]
  610.         }
  611.         [color=#CC6600]else[/color] [color=#7E7E7E]// if we don't receive 'N' but still see '*'[/color]
  612.         {
  613.           [color=#CC6600]if[/color]((strchr(cmdbuffer[bufindw], [color=#006699]'*'[/color]) != NULL))
  614.           {
  615.             SERIAL_ERROR_START;
  616.             SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM);
  617.             SERIAL_ERRORLN(gcode_LastN);
  618.             serial_count = 0;
  619.             [color=#CC6600]return[/color];
  620.           }
  621.         }
  622.         [color=#CC6600]if[/color]((strchr(cmdbuffer[bufindw], [color=#006699]'G'[/color]) != NULL)){
  623.           strchr_pointer = strchr(cmdbuffer[bufindw], [color=#006699]'G'[/color]);
  624.           [color=#CC6600]switch[/color](([color=#CC6600]int[/color])((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){
  625.           [color=#CC6600]case[/color] 0:
  626.           [color=#CC6600]case[/color] 1:
  627.           [color=#CC6600]case[/color] 2:
  628.           [color=#CC6600]case[/color] 3:
  629.             [color=#CC6600]if[/color](Stopped == [color=#CC6600]false[/color]) { [color=#7E7E7E]// If printer is stopped by an error the G[0-3] codes are ignored.[/color]
  630.           #ifdef SDSUPPORT
  631.               [color=#CC6600]if[/color](card.saving)
  632.                 [color=#CC6600]break[/color];
  633.           #endif [color=#7E7E7E]//SDSUPPORT[/color]
  634.               SERIAL_PROTOCOLLNPGM(MSG_OK);
  635.             }
  636.             [color=#CC6600]else[/color] {
  637.               SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
  638.               LCD_MESSAGEPGM(MSG_STOPPED);
  639.             }
  640.             [color=#CC6600]break[/color];
  641.           [color=#CC6600]default[/color]:
  642.             [color=#CC6600]break[/color];
  643.           }
  644.  
  645.         }
  646.         bufindw = (bufindw + 1)%BUFSIZE;
  647.         buflen += 1;
  648.       }
  649.       serial_count = 0; [color=#7E7E7E]//clear buffer[/color]
  650.     }
  651.     [color=#CC6600]else[/color]
  652.     {
  653.       [color=#CC6600]if[/color](serial_char == [color=#006699]';'[/color]) comment_mode = [color=#CC6600]true[/color];
  654.       [color=#CC6600]if[/color](!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
  655.     }
  656.   }
  657.   #ifdef SDSUPPORT
  658.   [color=#CC6600]if[/color](!card.sdprinting || serial_count!=0){
  659.     [color=#CC6600]return[/color];
  660.   }
  661.  
  662.   [color=#7E7E7E]//'#' stops reading from sd to the buffer prematurely, so procedural macro calls are possible[/color]
  663.   [color=#7E7E7E]// if it occures, stop_buffering is triggered and the buffer is ran dry.[/color]
  664.   [color=#7E7E7E]// this character _can_ occure in serial com, due to checksums. however, no checksums are used in sd printing[/color]
  665.  
  666.   [color=#CC6600]static[/color] bool stop_buffering=[color=#CC6600]false[/color];
  667.   [color=#CC6600]if[/color](buflen==0) stop_buffering=[color=#CC6600]false[/color];
  668.  
  669.   [color=#CC6600]while[/color]( !card.eof() && buflen < BUFSIZE && !stop_buffering) {
  670.     int16_t n=card.get();
  671.     serial_char = ([color=#CC6600]char[/color])n;
  672.     [color=#CC6600]if[/color](serial_char == [color=#006699]'\n'[/color] ||
  673.        serial_char == [color=#006699]'\r'[/color] ||
  674.        (serial_char == [color=#006699]'#'[/color] && comment_mode == [color=#CC6600]false[/color]) ||
  675.        (serial_char == [color=#006699]':'[/color] && comment_mode == [color=#CC6600]false[/color]) ||
  676.        serial_count >= (MAX_CMD_SIZE - 1)||n==-1)
  677.     {
  678.       [color=#CC6600]if[/color](card.eof()){
  679.         SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
  680.         stoptime=[color=#CC6600]millis[/color]();
  681.         [color=#CC6600]char[/color] time[30];
  682.         [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] t=(stoptime-starttime)/1000;
  683.         [color=#CC6600]int[/color] hours, minutes;
  684.         minutes=(t/60)%60;
  685.         hours=t/60/60;
  686.         sprintf_P(time, PSTR([color=#006699]"%i hours %i minutes"[/color]),hours, minutes);
  687.         SERIAL_ECHO_START;
  688.         SERIAL_ECHOLN(time);
  689.         lcd_setstatus(time);
  690.         card.printingHasFinished();
  691.         card.checkautostart([color=#CC6600]true[/color]);
  692.  
  693.       }
  694.       [color=#CC6600]if[/color](serial_char==[color=#006699]'#'[/color])
  695.         stop_buffering=[color=#CC6600]true[/color];
  696.  
  697.       [color=#CC6600]if[/color](!serial_count)
  698.       {
  699.         comment_mode = [color=#CC6600]false[/color]; [color=#7E7E7E]//for new command[/color]
  700.         [color=#CC6600]return[/color]; [color=#7E7E7E]//if empty line[/color]
  701.       }
  702.       cmdbuffer[bufindw][serial_count] = 0; [color=#7E7E7E]//terminate string[/color]
  703. [color=#7E7E7E]//      if(!comment_mode){[/color]
  704.         fromsd[bufindw] = [color=#CC6600]true[/color];
  705.         buflen += 1;
  706.         bufindw = (bufindw + 1)%BUFSIZE;
  707. [color=#7E7E7E]//      }[/color]
  708.       comment_mode = [color=#CC6600]false[/color]; [color=#7E7E7E]//for new command[/color]
  709.       serial_count = 0; [color=#7E7E7E]//clear buffer[/color]
  710.     }
  711.     [color=#CC6600]else[/color]
  712.     {
  713.       [color=#CC6600]if[/color](serial_char == [color=#006699]';'[/color]) comment_mode = [color=#CC6600]true[/color];
  714.       [color=#CC6600]if[/color](!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
  715.     }
  716.   }
  717.  
  718.   #endif [color=#7E7E7E]//SDSUPPORT[/color]
  719.  
  720. }
  721.  
  722.  
  723. [color=#CC6600]float[/color] code_value()
  724. {
  725.   [color=#CC6600]return[/color] (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL));
  726. }
  727.  
  728. [color=#CC6600]long[/color] code_value_long()
  729. {
  730.   [color=#CC6600]return[/color] (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10));
  731. }
  732.  
  733. bool code_seen([color=#CC6600]char[/color] code)
  734. {
  735.   strchr_pointer = strchr(cmdbuffer[bufindr], code);
  736.   [color=#CC6600]return[/color] (strchr_pointer != NULL); [color=#7E7E7E]//Return True if a character was found[/color]
  737. }
  738.  
  739. #define DEFINE_PGM_READ_ANY(type, reader)       \
  740.     [color=#CC6600]static[/color] inline type pgm_read_any([color=#CC6600]const[/color] type *p) \
  741.     { [color=#CC6600]return[/color] pgm_read_##reader##_near(p); }
  742.  
  743. DEFINE_PGM_READ_ANY([color=#CC6600]float[/color], [color=#CC6600]float[/color]);
  744. DEFINE_PGM_READ_ANY([color=#CC6600]signed[/color] [color=#CC6600]char[/color], [color=#CC6600]byte[/color]);
  745.  
  746. #define XYZ_CONSTS_FROM_CONFIG(type, array, CONFIG) \
  747. [color=#CC6600]static[/color] [color=#CC6600]const[/color] PROGMEM type array##_P[3] = \
  748.     { X_##CONFIG, Y_##CONFIG, Z_##CONFIG };     \
  749. [color=#CC6600]static[/color] inline type array([color=#CC6600]int[/color] axis) \
  750.     { [color=#CC6600]return[/color] pgm_read_any(&array##_P[axis]); }
  751.  
  752. XYZ_CONSTS_FROM_CONFIG([color=#CC6600]float[/color], base_min_pos, MIN_POS);
  753. XYZ_CONSTS_FROM_CONFIG([color=#CC6600]float[/color], base_max_pos, MAX_POS);
  754. XYZ_CONSTS_FROM_CONFIG([color=#CC6600]float[/color], base_home_pos, HOME_POS);
  755. XYZ_CONSTS_FROM_CONFIG([color=#CC6600]float[/color], max_length, MAX_LENGTH);
  756. XYZ_CONSTS_FROM_CONFIG([color=#CC6600]float[/color], home_retract_mm, HOME_RETRACT_MM);
  757. XYZ_CONSTS_FROM_CONFIG([color=#CC6600]signed[/color] [color=#CC6600]char[/color], home_dir, HOME_DIR);
  758.  
  759. #ifdef DUAL_X_CARRIAGE
  760.   #if EXTRUDERS == 1 || defined(COREXY) \
  761.       || !defined(X2_ENABLE_PIN) || !defined(X2_STEP_PIN) || !defined(X2_DIR_PIN) \
  762.       || !defined(X2_HOME_POS) || !defined(X2_MIN_POS) || !defined(X2_MAX_POS) \
  763.       || !defined(X_MAX_PIN) || X_MAX_PIN < 0
  764.     #error [color=#006699]"Missing or invalid definitions for DUAL_X_CARRIAGE mode."[/color]
  765.   #endif
  766.   #if X_HOME_DIR != -1 || X2_HOME_DIR != 1
  767.     #error [color=#006699]"Please use canonical x-carriage assignment"[/color] [color=#7E7E7E]// the x-carriages are defined by their homing directions[/color]
  768.   #endif
  769.  
  770. #define DXC_FULL_CONTROL_MODE 0
  771. #define DXC_AUTO_PARK_MODE    1
  772. #define DXC_DUPLICATION_MODE  2
  773. [color=#CC6600]static[/color] [color=#CC6600]int[/color] dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
  774.  
  775. [color=#CC6600]static[/color] [color=#CC6600]float[/color] x_home_pos([color=#CC6600]int[/color] extruder) {
  776.   [color=#CC6600]if[/color] (extruder == 0)
  777.     [color=#CC6600]return[/color] base_home_pos([color=#006699]X_AXIS[/color]) + add_homeing[[color=#006699]X_AXIS[/color]];
  778.   [color=#CC6600]else[/color]
  779.     [color=#7E7E7E]// In dual carriage mode the extruder offset provides an override of the[/color]
  780.     [color=#7E7E7E]// second X-carriage offset when homed - otherwise X2_HOME_POS is used.[/color]
  781.     [color=#7E7E7E]// This allow soft recalibration of the second extruder offset position without firmware reflash[/color]
  782.     [color=#7E7E7E]// (through the M218 command).[/color]
  783.     [color=#CC6600]return[/color] (extruder_offset[[color=#006699]X_AXIS[/color]][1] > 0) ? extruder_offset[[color=#006699]X_AXIS[/color]][1] : X2_HOME_POS;
  784. }
  785.  
  786. [color=#CC6600]static[/color] [color=#CC6600]int[/color] x_home_dir([color=#CC6600]int[/color] extruder) {
  787.   [color=#CC6600]return[/color] (extruder == 0) ? X_HOME_DIR : X2_HOME_DIR;
  788. }
  789.  
  790. [color=#CC6600]static[/color] [color=#CC6600]float[/color] inactive_extruder_x_pos = X2_MAX_POS; [color=#7E7E7E]// used in mode 0 & 1[/color]
  791. [color=#CC6600]static[/color] bool active_extruder_parked = [color=#CC6600]false[/color]; [color=#7E7E7E]// used in mode 1 & 2[/color]
  792. [color=#CC6600]static[/color] [color=#CC6600]float[/color] raised_parked_position[NUM_AXIS]; [color=#7E7E7E]// used in mode 1[/color]
  793. [color=#CC6600]static[/color] [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] delayed_move_time = 0; [color=#7E7E7E]// used in mode 1[/color]
  794. [color=#CC6600]static[/color] [color=#CC6600]float[/color] duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; [color=#7E7E7E]// used in mode 2[/color]
  795. [color=#CC6600]static[/color] [color=#CC6600]float[/color] duplicate_extruder_temp_offset = 0; [color=#7E7E7E]// used in mode 2[/color]
  796. bool extruder_duplication_enabled = [color=#CC6600]false[/color]; [color=#7E7E7E]// used in mode 2[/color]
  797. #endif [color=#7E7E7E]//DUAL_X_CARRIAGE[/color]
  798.  
  799. [color=#CC6600]static[/color] [color=#CC6600]void[/color] axis_is_at_home([color=#CC6600]int[/color] axis) {
  800. #ifdef DUAL_X_CARRIAGE
  801.   [color=#CC6600]if[/color] (axis == [color=#006699]X_AXIS[/color]) {
  802.     [color=#CC6600]if[/color] (active_extruder != 0) {
  803.       current_position[[color=#006699]X_AXIS[/color]] = x_home_pos(active_extruder);
  804.       min_pos[[color=#006699]X_AXIS[/color]] = X2_MIN_POS;
  805.       max_pos[[color=#006699]X_AXIS[/color]] = [color=#CC6600]max[/color](extruder_offset[[color=#006699]X_AXIS[/color]][1], X2_MAX_POS);
  806.       [color=#CC6600]return[/color];
  807.     }
  808.     [color=#CC6600]else[/color] [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0) {
  809.       current_position[[color=#006699]X_AXIS[/color]] = base_home_pos([color=#006699]X_AXIS[/color]) + add_homeing[[color=#006699]X_AXIS[/color]];
  810.       min_pos[[color=#006699]X_AXIS[/color]] = base_min_pos([color=#006699]X_AXIS[/color]) + add_homeing[[color=#006699]X_AXIS[/color]];
  811.       max_pos[[color=#006699]X_AXIS[/color]] = [color=#CC6600]min[/color](base_max_pos([color=#006699]X_AXIS[/color]) + add_homeing[[color=#006699]X_AXIS[/color]],
  812.                                   [color=#CC6600]max[/color](extruder_offset[[color=#006699]X_AXIS[/color]][1], X2_MAX_POS) - duplicate_extruder_x_offset);
  813.       [color=#CC6600]return[/color];
  814.     }
  815.   }
  816. #endif
  817.   current_position[axis] = base_home_pos(axis) + add_homeing[axis];
  818.   min_pos[axis] =          base_min_pos(axis) + add_homeing[axis];
  819.   max_pos[axis] =          base_max_pos(axis) + add_homeing[axis];
  820. }
  821.  
  822. #ifdef ENABLE_AUTO_BED_LEVELING
  823. #ifdef ACCURATE_BED_LEVELING
  824. [color=#CC6600]static[/color] [color=#CC6600]void[/color] set_bed_level_equation_lsq([color=#CC6600]double[/color] *plane_equation_coefficients)
  825. {
  826.     vector_3 planeNormal = vector_3(-plane_equation_coefficients[0], -plane_equation_coefficients[1], 1);
  827.     planeNormal.debug([color=#006699]"planeNormal"[/color]);
  828.     plan_bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
  829.     [color=#7E7E7E]//bedLevel.debug("bedLevel");[/color]
  830.  
  831.     [color=#7E7E7E]//plan_bed_level_matrix.debug("bed level before");[/color]
  832.     [color=#7E7E7E]//vector_3 uncorrected_position = plan_get_position_mm();[/color]
  833.     [color=#7E7E7E]//uncorrected_position.debug("position before");[/color]
  834.  
  835.     vector_3 corrected_position = plan_get_position();
  836. [color=#7E7E7E]//    corrected_position.debug("position after");[/color]
  837.     current_position[[color=#006699]X_AXIS[/color]] = corrected_position.x;
  838.     current_position[[color=#006699]Y_AXIS[/color]] = corrected_position.y;
  839.     current_position[[color=#006699]Z_AXIS[/color]] = corrected_position.z;
  840.  
  841.     [color=#7E7E7E]// but the bed at 0 so we don't go below it.[/color]
  842.     current_position[[color=#006699]Z_AXIS[/color]] = zprobe_zoffset; [color=#7E7E7E]// in the lsq we reach here after raising the extruder due to the loop structure[/color]
  843.  
  844.     plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  845. }
  846.  
  847. #else
  848. [color=#CC6600]static[/color] [color=#CC6600]void[/color] set_bed_level_equation([color=#CC6600]float[/color] z_at_xLeft_yFront, [color=#CC6600]float[/color] z_at_xRight_yFront, [color=#CC6600]float[/color] z_at_xLeft_yBack) {
  849.     plan_bed_level_matrix.set_to_identity();
  850.  
  851.     vector_3 xLeftyFront = vector_3(LEFT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, z_at_xLeft_yFront);
  852.     vector_3 xLeftyBack = vector_3(LEFT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, z_at_xLeft_yBack);
  853.     vector_3 xRightyFront = vector_3(RIGHT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, z_at_xRight_yFront);
  854.  
  855.     vector_3 xPositive = (xRightyFront - xLeftyFront).get_normal();
  856.     vector_3 yPositive = (xLeftyBack - xLeftyFront).get_normal();
  857.     vector_3 planeNormal = vector_3::cross(xPositive, yPositive).get_normal();
  858.  
  859.     [color=#7E7E7E]//planeNormal.debug("planeNormal");[/color]
  860.     [color=#7E7E7E]//yPositive.debug("yPositive");[/color]
  861.     plan_bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
  862.     [color=#7E7E7E]//bedLevel.debug("bedLevel");[/color]
  863.  
  864.     [color=#7E7E7E]//plan_bed_level_matrix.debug("bed level before");[/color]
  865.     [color=#7E7E7E]//vector_3 uncorrected_position = plan_get_position_mm();[/color]
  866.     [color=#7E7E7E]//uncorrected_position.debug("position before");[/color]
  867.  
  868.     [color=#7E7E7E]// and set our bed level equation to do the right thing[/color]
  869.     [color=#7E7E7E]//plan_bed_level_matrix.debug("bed level after");[/color]
  870.  
  871.     vector_3 corrected_position = plan_get_position();
  872.     [color=#7E7E7E]//corrected_position.debug("position after");[/color]
  873.     current_position[[color=#006699]X_AXIS[/color]] = corrected_position.x;
  874.     current_position[[color=#006699]Y_AXIS[/color]] = corrected_position.y;
  875.     current_position[[color=#006699]Z_AXIS[/color]] = corrected_position.z;
  876.  
  877.     [color=#7E7E7E]// but the bed at 0 so we don't go below it.[/color]
  878.     current_position[[color=#006699]Z_AXIS[/color]] = zprobe_zoffset;
  879.  
  880.     plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  881. }
  882. #endif [color=#7E7E7E]// ACCURATE_BED_LEVELING[/color]
  883.  
  884. [color=#CC6600]static[/color] [color=#CC6600]void[/color] run_z_probe() {
  885.     plan_bed_level_matrix.set_to_identity();
  886.     feedrate = homing_feedrate[[color=#006699]Z_AXIS[/color]];
  887.  
  888.     [color=#7E7E7E]// move down until you find the bed[/color]
  889.     [color=#CC6600]float[/color] zPosition = -10;
  890.     plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
  891.     st_synchronize();
  892.  
  893.         [color=#7E7E7E]// we have to let the planner know where we are right now as it is not where we said to go.[/color]
  894.     zPosition = st_get_position_mm([color=#006699]Z_AXIS[/color]);
  895.     plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], zPosition, current_position[E_AXIS]);
  896.  
  897.     [color=#7E7E7E]// move up the retract distance[/color]
  898.     zPosition += home_retract_mm([color=#006699]Z_AXIS[/color]);
  899.     plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
  900.     st_synchronize();
  901.  
  902.     [color=#7E7E7E]// move back down slowly to find bed[/color]
  903.     feedrate = homing_feedrate[[color=#006699]Z_AXIS[/color]]/4;
  904.     zPosition -= home_retract_mm([color=#006699]Z_AXIS[/color]) * 2;
  905.     plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
  906.     st_synchronize();
  907.  
  908.     current_position[[color=#006699]Z_AXIS[/color]] = st_get_position_mm([color=#006699]Z_AXIS[/color]);
  909.     [color=#7E7E7E]// make sure the planner knows where we are as it may be a bit different than we last said to move to[/color]
  910.     plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  911. }
  912.  
  913. [color=#CC6600]static[/color] [color=#CC6600]void[/color] do_blocking_move_to([color=#CC6600]float[/color] x, [color=#CC6600]float[/color] y, [color=#CC6600]float[/color] z) {
  914.     [color=#CC6600]float[/color] oldFeedRate = feedrate;
  915.  
  916.     feedrate = XY_TRAVEL_SPEED;
  917.  
  918.     current_position[[color=#006699]X_AXIS[/color]] = x;
  919.     current_position[[color=#006699]Y_AXIS[/color]] = y;
  920.     current_position[[color=#006699]Z_AXIS[/color]] = z;
  921.     plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS], feedrate/60, active_extruder);
  922.     st_synchronize();
  923.  
  924.     feedrate = oldFeedRate;
  925. }
  926.  
  927. [color=#CC6600]static[/color] [color=#CC6600]void[/color] do_blocking_move_relative([color=#CC6600]float[/color] offset_x, [color=#CC6600]float[/color] offset_y, [color=#CC6600]float[/color] offset_z) {
  928.     do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]] + offset_x, current_position[[color=#006699]Y_AXIS[/color]] + offset_y, current_position[[color=#006699]Z_AXIS[/color]] + offset_z);
  929. }
  930.  
  931. [color=#CC6600]static[/color] [color=#CC6600]void[/color] setup_for_endstop_move() {
  932.     saved_feedrate = feedrate;
  933.     saved_feedmultiply = feedmultiply;
  934.     feedmultiply = 100;
  935.     previous_millis_cmd = [color=#CC6600]millis[/color]();
  936.  
  937.     enable_endstops([color=#CC6600]true[/color]);
  938. }
  939.  
  940. [color=#CC6600]static[/color] [color=#CC6600]void[/color] clean_up_after_endstop_move() {
  941. #ifdef ENDSTOPS_ONLY_FOR_HOMING
  942.     enable_endstops([color=#CC6600]false[/color]);
  943. #endif
  944.  
  945.     feedrate = saved_feedrate;
  946.     feedmultiply = saved_feedmultiply;
  947.     previous_millis_cmd = [color=#CC6600]millis[/color]();
  948. }
  949.  
  950. [color=#CC6600]static[/color] [color=#CC6600]void[/color] engage_z_probe() {
  951.     [color=#7E7E7E]// Engage Z Servo endstop if enabled[/color]
  952.     #ifdef SERVO_ENDSTOPS
  953.     [color=#CC6600]if[/color] (servo_endstops[[color=#006699]Z_AXIS[/color]] > -1) {
  954. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  955.         servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]attach[/color](0);
  956. #endif
  957.         servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]write[/color](servo_endstop_angles[[color=#006699]Z_AXIS[/color] * 2]);
  958. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  959.         [color=#CC6600]delay[/color](PROBE_SERVO_DEACTIVATION_DELAY);
  960.         servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]detach[/color]();
  961. #endif
  962.     }
  963.     #endif
  964. }
  965.  
  966. [color=#CC6600]static[/color] [color=#CC6600]void[/color] retract_z_probe() {
  967.     [color=#7E7E7E]// Retract Z Servo endstop if enabled[/color]
  968.     #ifdef SERVO_ENDSTOPS
  969.     [color=#CC6600]if[/color] (servo_endstops[[color=#006699]Z_AXIS[/color]] > -1) {
  970. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  971.         servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]attach[/color](0);
  972. #endif
  973.         servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]write[/color](servo_endstop_angles[[color=#006699]Z_AXIS[/color] * 2 + 1]);
  974. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  975.         [color=#CC6600]delay[/color](PROBE_SERVO_DEACTIVATION_DELAY);
  976.         servos[servo_endstops[[color=#006699]Z_AXIS[/color]]].[color=#CC6600]detach[/color]();
  977. #endif
  978.     }
  979.     #endif
  980. }
  981.  
  982. #endif [color=#7E7E7E]// #ifdef ENABLE_AUTO_BED_LEVELING[/color]
  983.  
  984. [color=#CC6600]static[/color] [color=#CC6600]void[/color] homeaxis([color=#CC6600]int[/color] axis) {
  985. #define HOMEAXIS_DO(LETTER) \
  986.   ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
  987.  
  988.   [color=#CC6600]if[/color] (axis==[color=#006699]X_AXIS[/color] ? HOMEAXIS_DO(X) :
  989.       axis==[color=#006699]Y_AXIS[/color] ? HOMEAXIS_DO(Y) :
  990.       axis==[color=#006699]Z_AXIS[/color] ? HOMEAXIS_DO(Z) :
  991.       0) {
  992.     [color=#CC6600]int[/color] axis_home_dir = home_dir(axis);
  993. #ifdef DUAL_X_CARRIAGE
  994.     [color=#CC6600]if[/color] (axis == [color=#006699]X_AXIS[/color])
  995.       axis_home_dir = x_home_dir(active_extruder);
  996. #endif
  997.  
  998.     current_position[axis] = 0;
  999.     plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1000.  
  1001.  
  1002.     [color=#7E7E7E]// Engage Servo endstop if enabled[/color]
  1003.     #ifdef SERVO_ENDSTOPS
  1004.       #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  1005.         [color=#CC6600]if[/color] (axis==[color=#006699]Z_AXIS[/color]) {
  1006.           engage_z_probe();
  1007.         }
  1008.     [color=#CC6600]else[/color]
  1009.       #endif
  1010.       [color=#CC6600]if[/color] (servo_endstops[axis] > -1) {
  1011.         servos[servo_endstops[axis]].[color=#CC6600]write[/color](servo_endstop_angles[axis * 2]);
  1012.       }
  1013.     #endif
  1014.  
  1015.     destination[axis] = 1.5 * max_length(axis) * axis_home_dir;
  1016.     feedrate = homing_feedrate[axis];
  1017.     plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1018.     st_synchronize();
  1019.  
  1020.     current_position[axis] = 0;
  1021.     plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1022.     destination[axis] = -home_retract_mm(axis) * axis_home_dir;
  1023.     plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1024.     st_synchronize();
  1025.  
  1026.     destination[axis] = 2*home_retract_mm(axis) * axis_home_dir;
  1027. #ifdef DELTA
  1028.     feedrate = homing_feedrate[axis]/10;
  1029. #else
  1030.     feedrate = homing_feedrate[axis]/2 ;
  1031. #endif
  1032.     plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1033.     st_synchronize();
  1034. #ifdef DELTA
  1035.     [color=#7E7E7E]// retrace by the amount specified in endstop_adj[/color]
  1036.     [color=#CC6600]if[/color] (endstop_adj[axis] * axis_home_dir < 0) {
  1037.       plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1038.       destination[axis] = endstop_adj[axis];
  1039.       plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1040.       st_synchronize();
  1041.     }
  1042. #endif
  1043.     axis_is_at_home(axis);
  1044.     destination[axis] = current_position[axis];
  1045.     feedrate = 0.0;
  1046.     endstops_hit_on_purpose();
  1047.     axis_known_position[axis] = [color=#CC6600]true[/color];
  1048.  
  1049.     [color=#7E7E7E]// Retract Servo endstop if enabled[/color]
  1050.     #ifdef SERVO_ENDSTOPS
  1051.       [color=#CC6600]if[/color] (servo_endstops[axis] > -1) {
  1052.         servos[servo_endstops[axis]].[color=#CC6600]write[/color](servo_endstop_angles[axis * 2 + 1]);
  1053.       }
  1054.     #endif
  1055. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  1056.     [color=#CC6600]if[/color] (axis==[color=#006699]Z_AXIS[/color]) {
  1057.      
  1058.       
  1059.     }
  1060. #endif
  1061.  
  1062.   }
  1063. }
  1064. #define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS)
  1065.  
  1066. [color=#CC6600]void[/color] process_commands()
  1067. {
  1068.   [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] codenum; [color=#7E7E7E]//throw away variable[/color]
  1069.   [color=#CC6600]char[/color] *starpos = NULL;
  1070. #ifdef ENABLE_AUTO_BED_LEVELING
  1071.   [color=#CC6600]float[/color] x_tmp, y_tmp, z_tmp, real_z;
  1072. #endif
  1073.   [color=#CC6600]if[/color](code_seen([color=#006699]'G'[/color]))
  1074.   {
  1075.     [color=#CC6600]switch[/color](([color=#CC6600]int[/color])code_value())
  1076.     {
  1077.     [color=#CC6600]case[/color] 0: [color=#7E7E7E]// G0 -> G1[/color]
  1078.     [color=#CC6600]case[/color] 1: [color=#7E7E7E]// G1[/color]
  1079.       [color=#CC6600]if[/color](Stopped == [color=#CC6600]false[/color]) {
  1080.         get_coordinates(); [color=#7E7E7E]// For X Y Z E F[/color]
  1081.         prepare_move();
  1082.         [color=#7E7E7E]//ClearToSend();[/color]
  1083.         [color=#CC6600]return[/color];
  1084.       }
  1085.       [color=#7E7E7E]//break;[/color]
  1086.     [color=#CC6600]case[/color] 2: [color=#7E7E7E]// G2 - CW ARC[/color]
  1087.       [color=#CC6600]if[/color](Stopped == [color=#CC6600]false[/color]) {
  1088.         get_arc_coordinates();
  1089.         prepare_arc_move([color=#CC6600]true[/color]);
  1090.         [color=#CC6600]return[/color];
  1091.       }
  1092.     [color=#CC6600]case[/color] 3: [color=#7E7E7E]// G3 - CCW ARC[/color]
  1093.       [color=#CC6600]if[/color](Stopped == [color=#CC6600]false[/color]) {
  1094.         get_arc_coordinates();
  1095.         prepare_arc_move([color=#CC6600]false[/color]);
  1096.         [color=#CC6600]return[/color];
  1097.       }
  1098.     [color=#CC6600]case[/color] 4: [color=#7E7E7E]// G4 dwell[/color]
  1099.       LCD_MESSAGEPGM(MSG_DWELL);
  1100.       codenum = 0;
  1101.       [color=#CC6600]if[/color](code_seen([color=#006699]'P'[/color])) codenum = code_value(); [color=#7E7E7E]// milliseconds to wait[/color]
  1102.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) codenum = code_value() * 1000; [color=#7E7E7E]// seconds to wait[/color]
  1103.  
  1104.       st_synchronize();
  1105.       codenum += [color=#CC6600]millis[/color](); [color=#7E7E7E]// keep track of when we started waiting[/color]
  1106.       previous_millis_cmd = [color=#CC6600]millis[/color]();
  1107.       [color=#CC6600]while[/color]([color=#CC6600]millis[/color]() < codenum ){
  1108.         manage_heater();
  1109.         manage_inactivity();
  1110.         lcd_update();
  1111.       }
  1112.       [color=#CC6600]break[/color];
  1113.       #ifdef FWRETRACT
  1114.       [color=#CC6600]case[/color] 10: [color=#7E7E7E]// G10 retract[/color]
  1115.       [color=#CC6600]if[/color](!retracted)
  1116.       {
  1117.         destination[[color=#006699]X_AXIS[/color]]=current_position[[color=#006699]X_AXIS[/color]];
  1118.         destination[[color=#006699]Y_AXIS[/color]]=current_position[[color=#006699]Y_AXIS[/color]];
  1119.         destination[[color=#006699]Z_AXIS[/color]]=current_position[[color=#006699]Z_AXIS[/color]];
  1120.         current_position[[color=#006699]Z_AXIS[/color]]-=retract_zlift;
  1121.         destination[E_AXIS]=current_position[E_AXIS];
  1122.         current_position[E_AXIS]+=retract_length/volumetric_multiplier[active_extruder];
  1123.         plan_set_e_position(current_position[E_AXIS]);
  1124.         [color=#CC6600]float[/color] oldFeedrate = feedrate;
  1125.         feedrate=retract_feedrate;
  1126.         retracted=[color=#CC6600]true[/color];
  1127.         prepare_move();
  1128.         feedrate = oldFeedrate;
  1129.       }
  1130.  
  1131.       [color=#CC6600]break[/color];
  1132.       [color=#CC6600]case[/color] 11: [color=#7E7E7E]// G11 retract_recover[/color]
  1133.       [color=#CC6600]if[/color](retracted)
  1134.       {
  1135.         destination[[color=#006699]X_AXIS[/color]]=current_position[[color=#006699]X_AXIS[/color]];
  1136.         destination[[color=#006699]Y_AXIS[/color]]=current_position[[color=#006699]Y_AXIS[/color]];
  1137.         destination[[color=#006699]Z_AXIS[/color]]=current_position[[color=#006699]Z_AXIS[/color]];
  1138.         current_position[[color=#006699]Z_AXIS[/color]]+=retract_zlift;
  1139.         destination[E_AXIS]=current_position[E_AXIS];
  1140.         current_position[E_AXIS]-=(retract_length+retract_recover_length)/volumetric_multiplier[active_extruder]; 
  1141.         plan_set_e_position(current_position[E_AXIS]);
  1142.         [color=#CC6600]float[/color] oldFeedrate = feedrate;
  1143.         feedrate=retract_recover_feedrate;
  1144.         retracted=[color=#CC6600]false[/color];
  1145.         prepare_move();
  1146.         feedrate = oldFeedrate;
  1147.       }
  1148.       [color=#CC6600]break[/color];
  1149.       #endif [color=#7E7E7E]//FWRETRACT[/color]
  1150.     [color=#CC6600]case[/color] 28: [color=#7E7E7E]//G28 Home all Axis one at a time[/color]
  1151. #ifdef ENABLE_AUTO_BED_LEVELING
  1152.       plan_bed_level_matrix.set_to_identity();  [color=#7E7E7E]//Reset the plane ("erase" all leveling data)[/color]
  1153. #endif [color=#7E7E7E]//ENABLE_AUTO_BED_LEVELING[/color]
  1154.  
  1155.  
  1156.       saved_feedrate = feedrate;
  1157.       saved_feedmultiply = feedmultiply;
  1158.       feedmultiply = 100;
  1159.       previous_millis_cmd = [color=#CC6600]millis[/color]();
  1160.  
  1161.       enable_endstops([color=#CC6600]true[/color]);
  1162.  
  1163.       [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  1164.         destination[i] = current_position[i];
  1165.       }
  1166.       feedrate = 0.0;
  1167.  
  1168. #ifdef DELTA
  1169.           [color=#7E7E7E]// A delta can only safely home all axis at the same time[/color]
  1170.           [color=#7E7E7E]// all axis have to home at the same time[/color]
  1171.  
  1172.           [color=#7E7E7E]// Move all carriages up together until the first endstop is hit.[/color]
  1173.           current_position[[color=#006699]X_AXIS[/color]] = 0;
  1174.           current_position[[color=#006699]Y_AXIS[/color]] = 0;
  1175.           current_position[[color=#006699]Z_AXIS[/color]] = 0;
  1176.           plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1177.  
  1178.           destination[[color=#006699]X_AXIS[/color]] = 3 * Z_MAX_LENGTH;
  1179.           destination[[color=#006699]Y_AXIS[/color]] = 3 * Z_MAX_LENGTH;
  1180.           destination[[color=#006699]Z_AXIS[/color]] = 3 * Z_MAX_LENGTH;
  1181.           feedrate = 1.732 * homing_feedrate[[color=#006699]X_AXIS[/color]];
  1182.           plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1183.           st_synchronize();
  1184.           endstops_hit_on_purpose();
  1185.  
  1186.           current_position[[color=#006699]X_AXIS[/color]] = destination[[color=#006699]X_AXIS[/color]];
  1187.           current_position[[color=#006699]Y_AXIS[/color]] = destination[[color=#006699]Y_AXIS[/color]];
  1188.           current_position[[color=#006699]Z_AXIS[/color]] = destination[[color=#006699]Z_AXIS[/color]];
  1189.  
  1190.           [color=#7E7E7E]// take care of back off and rehome now we are all at the top[/color]
  1191.           HOMEAXIS(X);
  1192.           HOMEAXIS(Y);
  1193.           HOMEAXIS(Z);
  1194.  
  1195.           calculate_delta(current_position);
  1196.           plan_set_position(delta[[color=#006699]X_AXIS[/color]], delta[[color=#006699]Y_AXIS[/color]], delta[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1197.  
  1198. #else [color=#7E7E7E]// NOT DELTA[/color]
  1199.  
  1200.       home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2])));
  1201.  
  1202.       #if Z_HOME_DIR > 0                      [color=#7E7E7E]// If homing away from BED do Z first[/color]
  1203.       [color=#CC6600]if[/color]((home_all_axis) || (code_seen(axis_codes[[color=#006699]Z_AXIS[/color]]))) {
  1204.         HOMEAXIS(Z);
  1205.       }
  1206.       #endif
  1207.  
  1208.       #ifdef QUICK_HOME
  1209.       [color=#CC6600]if[/color]((home_all_axis)||( code_seen(axis_codes[[color=#006699]X_AXIS[/color]]) && code_seen(axis_codes[[color=#006699]Y_AXIS[/color]])) ) [color=#7E7E7E]//first diagonal move[/color]
  1210.       {
  1211.         current_position[[color=#006699]X_AXIS[/color]] = 0;current_position[[color=#006699]Y_AXIS[/color]] = 0;
  1212.  
  1213.        #ifndef DUAL_X_CARRIAGE
  1214.         [color=#CC6600]int[/color] x_axis_home_dir = home_dir([color=#006699]X_AXIS[/color]);
  1215.        #else
  1216.         [color=#CC6600]int[/color] x_axis_home_dir = x_home_dir(active_extruder);
  1217.         extruder_duplication_enabled = [color=#CC6600]false[/color];
  1218.        #endif
  1219.  
  1220.         plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1221.         destination[[color=#006699]X_AXIS[/color]] = 1.5 * max_length([color=#006699]X_AXIS[/color]) * x_axis_home_dir;destination[[color=#006699]Y_AXIS[/color]] = 1.5 * max_length([color=#006699]Y_AXIS[/color]) * home_dir([color=#006699]Y_AXIS[/color]);
  1222.         feedrate = homing_feedrate[[color=#006699]X_AXIS[/color]];
  1223.         [color=#CC6600]if[/color](homing_feedrate[[color=#006699]Y_AXIS[/color]]<feedrate)
  1224.           feedrate =homing_feedrate[[color=#006699]Y_AXIS[/color]];
  1225.         plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1226.         st_synchronize();
  1227.  
  1228.         axis_is_at_home([color=#006699]X_AXIS[/color]);
  1229.         axis_is_at_home([color=#006699]Y_AXIS[/color]);
  1230.         plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1231.         destination[[color=#006699]X_AXIS[/color]] = current_position[[color=#006699]X_AXIS[/color]];
  1232.         destination[[color=#006699]Y_AXIS[/color]] = current_position[[color=#006699]Y_AXIS[/color]];
  1233.         plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  1234.         feedrate = 0.0;
  1235.         st_synchronize();
  1236.         endstops_hit_on_purpose();
  1237.  
  1238.         current_position[[color=#006699]X_AXIS[/color]] = destination[[color=#006699]X_AXIS[/color]];
  1239.         current_position[[color=#006699]Y_AXIS[/color]] = destination[[color=#006699]Y_AXIS[/color]];
  1240.         current_position[[color=#006699]Z_AXIS[/color]] = destination[[color=#006699]Z_AXIS[/color]];
  1241.       }
  1242.       #endif
  1243.  
  1244.       [color=#CC6600]if[/color]((home_all_axis) || (code_seen(axis_codes[[color=#006699]X_AXIS[/color]])))
  1245.       {
  1246.       #ifdef DUAL_X_CARRIAGE
  1247.         [color=#CC6600]int[/color] tmp_extruder = active_extruder;
  1248.         extruder_duplication_enabled = [color=#CC6600]false[/color];
  1249.         active_extruder = !active_extruder;
  1250.         HOMEAXIS(X);
  1251.         inactive_extruder_x_pos = current_position[[color=#006699]X_AXIS[/color]];
  1252.         active_extruder = tmp_extruder;
  1253.         HOMEAXIS(X);
  1254.         [color=#7E7E7E]// reset state used by the different modes[/color]
  1255.         memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
  1256.         delayed_move_time = 0;
  1257.         active_extruder_parked = [color=#CC6600]true[/color];
  1258.       #else
  1259.         HOMEAXIS(X);
  1260.       #endif
  1261.       }
  1262.  
  1263.       [color=#CC6600]if[/color]((home_all_axis) || (code_seen(axis_codes[[color=#006699]Y_AXIS[/color]]))) {
  1264.         HOMEAXIS(Y);
  1265.       }
  1266.  
  1267.       [color=#CC6600]if[/color](code_seen(axis_codes[[color=#006699]X_AXIS[/color]]))
  1268.       {
  1269.         [color=#CC6600]if[/color](code_value_long() != 0) {
  1270.           current_position[[color=#006699]X_AXIS[/color]]=code_value()+add_homeing[0];
  1271.         }
  1272.       }
  1273.  
  1274.       [color=#CC6600]if[/color](code_seen(axis_codes[[color=#006699]Y_AXIS[/color]])) {
  1275.         [color=#CC6600]if[/color](code_value_long() != 0) {
  1276.           current_position[[color=#006699]Y_AXIS[/color]]=code_value()+add_homeing[1];
  1277.         }
  1278.       }
  1279.  
  1280.       #if Z_HOME_DIR < 0                      [color=#7E7E7E]// If homing towards BED do Z last[/color]
  1281.         #ifndef Z_SAFE_HOMING
  1282.           [color=#CC6600]if[/color]((home_all_axis) || (code_seen(axis_codes[[color=#006699]Z_AXIS[/color]]))) {
  1283.             #if defined (Z_RAISE_BEFORE_HOMING) && (Z_RAISE_BEFORE_HOMING > 0)
  1284.               destination[[color=#006699]Z_AXIS[/color]] = Z_RAISE_BEFORE_HOMING * home_dir([color=#006699]Z_AXIS[/color]) * (-1); [color=#7E7E7E]// Set destination away from bed[/color]
  1285.               feedrate = max_feedrate[[color=#006699]Z_AXIS[/color]];
  1286.               plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate, active_extruder);
  1287.               st_synchronize();
  1288.             #endif
  1289.             HOMEAXIS(Z);
  1290.           }
  1291.         #else                      [color=#7E7E7E]// Z Safe mode activated.[/color]
  1292.           [color=#CC6600]if[/color](home_all_axis) {
  1293.             destination[[color=#006699]X_AXIS[/color]] = [color=#CC6600]round[/color](Z_SAFE_HOMING_X_POINT - X_PROBE_OFFSET_FROM_EXTRUDER);
  1294.             destination[[color=#006699]Y_AXIS[/color]] = [color=#CC6600]round[/color](Z_SAFE_HOMING_Y_POINT - Y_PROBE_OFFSET_FROM_EXTRUDER);
  1295.             destination[[color=#006699]Z_AXIS[/color]] = Z_RAISE_BEFORE_HOMING * home_dir([color=#006699]Z_AXIS[/color]) * (-1); [color=#7E7E7E]// Set destination away from bed[/color]
  1296.             feedrate = XY_TRAVEL_SPEED;
  1297.             current_position[[color=#006699]Z_AXIS[/color]] = 0;
  1298.  
  1299.             plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1300.             plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate, active_extruder);
  1301.             st_synchronize();
  1302.             current_position[[color=#006699]X_AXIS[/color]] = destination[[color=#006699]X_AXIS[/color]];
  1303.             current_position[[color=#006699]Y_AXIS[/color]] = destination[[color=#006699]Y_AXIS[/color]];
  1304.  
  1305.             HOMEAXIS(Z);
  1306.           }
  1307.                                                 [color=#7E7E7E]// Let's see if X and Y are homed and probe is inside bed area.[/color]
  1308.           [color=#CC6600]if[/color](code_seen(axis_codes[[color=#006699]Z_AXIS[/color]])) {
  1309.             [color=#CC6600]if[/color] ( (axis_known_position[[color=#006699]X_AXIS[/color]]) && (axis_known_position[[color=#006699]Y_AXIS[/color]]) \
  1310.               && (current_position[[color=#006699]X_AXIS[/color]]+X_PROBE_OFFSET_FROM_EXTRUDER >= X_MIN_POS) \
  1311.               && (current_position[[color=#006699]X_AXIS[/color]]+X_PROBE_OFFSET_FROM_EXTRUDER <= X_MAX_POS) \
  1312.               && (current_position[[color=#006699]Y_AXIS[/color]]+Y_PROBE_OFFSET_FROM_EXTRUDER >= Y_MIN_POS) \
  1313.               && (current_position[[color=#006699]Y_AXIS[/color]]+Y_PROBE_OFFSET_FROM_EXTRUDER <= Y_MAX_POS)) {
  1314.  
  1315.               current_position[[color=#006699]Z_AXIS[/color]] = 0;
  1316.               plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1317.               destination[[color=#006699]Z_AXIS[/color]] = Z_RAISE_BEFORE_HOMING * home_dir([color=#006699]Z_AXIS[/color]) * (-1); [color=#7E7E7E]// Set destination away from bed[/color]
  1318.               feedrate = max_feedrate[[color=#006699]Z_AXIS[/color]];
  1319.               plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate, active_extruder);
  1320.               st_synchronize();
  1321.  
  1322.               HOMEAXIS(Z);
  1323.             } [color=#CC6600]else[/color] [color=#CC6600]if[/color] (!((axis_known_position[[color=#006699]X_AXIS[/color]]) && (axis_known_position[[color=#006699]Y_AXIS[/color]]))) {
  1324.                 LCD_MESSAGEPGM(MSG_POSITION_UNKNOWN);
  1325.                 SERIAL_ECHO_START;
  1326.                 SERIAL_ECHOLNPGM(MSG_POSITION_UNKNOWN);
  1327.             } [color=#CC6600]else[/color] {
  1328.                 LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
  1329.                 SERIAL_ECHO_START;
  1330.                 SERIAL_ECHOLNPGM(MSG_ZPROBE_OUT);
  1331.             }
  1332.           }
  1333.         #endif
  1334.       #endif
  1335.  
  1336.  
  1337.  
  1338.       [color=#CC6600]if[/color](code_seen(axis_codes[[color=#006699]Z_AXIS[/color]])) {
  1339.         [color=#CC6600]if[/color](code_value_long() != 0) {
  1340.           current_position[[color=#006699]Z_AXIS[/color]]=code_value()+add_homeing[2];
  1341.         }
  1342.       }
  1343.       #ifdef ENABLE_AUTO_BED_LEVELING
  1344.         [color=#CC6600]if[/color]((home_all_axis) || (code_seen(axis_codes[[color=#006699]Z_AXIS[/color]]))) {
  1345.           current_position[[color=#006699]Z_AXIS[/color]] += zprobe_zoffset; [color=#7E7E7E]//Add Z_Probe offset (the distance is negative)[/color]
  1346.         }
  1347.       #endif
  1348.       plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1349. #endif [color=#7E7E7E]// else DELTA[/color]
  1350.  
  1351.       #ifdef ENDSTOPS_ONLY_FOR_HOMING
  1352.         enable_endstops([color=#CC6600]false[/color]);
  1353.       #endif
  1354.  
  1355.       feedrate = saved_feedrate;
  1356.       feedmultiply = saved_feedmultiply;
  1357.       previous_millis_cmd = [color=#CC6600]millis[/color]();
  1358.       endstops_hit_on_purpose();
  1359.       [color=#CC6600]break[/color];
  1360.  
  1361. #ifdef ENABLE_AUTO_BED_LEVELING
  1362.     [color=#CC6600]case[/color] 29: [color=#7E7E7E]// G29 Detailed Z-Probe, probes the bed at 3 points.[/color]
  1363.         {
  1364.             #if Z_MIN_PIN == -1
  1365.             #error [color=#006699]"You must have a Z_MIN endstop in order to enable Auto Bed Leveling feature!!! Z_MIN_PIN must point to a valid hardware pin."[/color]
  1366.             #endif
  1367.  
  1368.             st_synchronize();
  1369.             [color=#7E7E7E]// make sure the bed_level_rotation_matrix is identity or the planner will get it incorectly[/color]
  1370.             [color=#7E7E7E]//vector_3 corrected_position = plan_get_position_mm();[/color]
  1371.             [color=#7E7E7E]//corrected_position.debug("position before G29");[/color]
  1372.             plan_bed_level_matrix.set_to_identity();
  1373.             vector_3 uncorrected_position = plan_get_position();
  1374.             [color=#7E7E7E]//uncorrected_position.debug("position durring G29");[/color]
  1375.             current_position[[color=#006699]X_AXIS[/color]] = uncorrected_position.x;
  1376.             current_position[[color=#006699]Y_AXIS[/color]] = uncorrected_position.y;
  1377.             current_position[[color=#006699]Z_AXIS[/color]] = uncorrected_position.z;
  1378.             plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1379.             setup_for_endstop_move();
  1380.  
  1381.             feedrate = homing_feedrate[[color=#006699]Z_AXIS[/color]];
  1382. #ifdef ACCURATE_BED_LEVELING
  1383.  
  1384.             [color=#CC6600]int[/color] xGridSpacing = (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION) / (ACCURATE_BED_LEVELING_POINTS-1);
  1385.             [color=#CC6600]int[/color] yGridSpacing = (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION) / (ACCURATE_BED_LEVELING_POINTS-1);
  1386.  
  1387.  
  1388.             [color=#7E7E7E]// solve the plane equation ax + by + d = z[/color]
  1389.             [color=#7E7E7E]// A is the matrix with rows [x y 1] for all the probed points[/color]
  1390.             [color=#7E7E7E]// B is the vector of the Z positions[/color]
  1391.             [color=#7E7E7E]// the normal vector to the plane is formed by the coefficients of the plane equation in the standard form, which is Vx*x+Vy*y+Vz*z+d = 0[/color]
  1392.             [color=#7E7E7E]// so Vx = -a Vy = -b Vz = 1 (we want the vector facing towards positive Z[/color]
  1393.  
  1394.             [color=#7E7E7E]// "A" matrix of the linear system of equations[/color]
  1395.             [color=#CC6600]double[/color] eqnAMatrix[ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS*3];
  1396.             [color=#7E7E7E]// "B" vector of Z points[/color]
  1397.             [color=#CC6600]double[/color] eqnBVector[ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS];
  1398.  
  1399.  
  1400.             [color=#CC6600]int[/color] probePointCounter = 0;
  1401.             bool zig = [color=#CC6600]true[/color];
  1402.  
  1403.             [color=#CC6600]for[/color] ([color=#CC6600]int[/color] yProbe=FRONT_PROBE_BED_POSITION; yProbe <= BACK_PROBE_BED_POSITION; yProbe += yGridSpacing)
  1404.             {
  1405.               [color=#CC6600]int[/color] xProbe, xInc;
  1406.               [color=#CC6600]if[/color] (zig)
  1407.               {
  1408.                 xProbe = LEFT_PROBE_BED_POSITION;
  1409.                 [color=#7E7E7E]//xEnd = RIGHT_PROBE_BED_POSITION;[/color]
  1410.                 xInc = xGridSpacing;
  1411.                 zig = [color=#CC6600]false[/color];
  1412.               } [color=#CC6600]else[/color] [color=#7E7E7E]// zag[/color]
  1413.               {
  1414.                 xProbe = RIGHT_PROBE_BED_POSITION;
  1415.                 [color=#7E7E7E]//xEnd = LEFT_PROBE_BED_POSITION;[/color]
  1416.                 xInc = -xGridSpacing;
  1417.                 zig = [color=#CC6600]true[/color];
  1418.               }
  1419.  
  1420.               [color=#CC6600]for[/color] ([color=#CC6600]int[/color] xCount=0; xCount < ACCURATE_BED_LEVELING_POINTS; xCount++)
  1421.               {
  1422.                 [color=#CC6600]if[/color] (probePointCounter == 0)
  1423.                 {
  1424.                   [color=#7E7E7E]// raise before probing[/color]
  1425.                   do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + Z_RAISE_BEFORE_PROBING);
  1426.                 } [color=#CC6600]else[/color]
  1427.                 {
  1428.                   [color=#7E7E7E]// raise extruder[/color]
  1429.                   do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + Z_RAISE_BETWEEN_PROBINGS);
  1430.                 }
  1431.  
  1432.  
  1433.                 do_blocking_move_to(xProbe - X_PROBE_OFFSET_FROM_EXTRUDER, yProbe - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[[color=#006699]Z_AXIS[/color]]);
  1434.  
  1435.                 engage_z_probe();   [color=#7E7E7E]// Engage Z Servo endstop if available[/color]
  1436.                 run_z_probe();
  1437.                 eqnBVector[probePointCounter] = current_position[[color=#006699]Z_AXIS[/color]];
  1438.                  do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + 1);
  1439.                 retract_z_probe();
  1440.  
  1441.                 SERIAL_PROTOCOLPGM([color=#006699]"Bed x: "[/color]);
  1442.                 SERIAL_PROTOCOL(xProbe);
  1443.                 SERIAL_PROTOCOLPGM([color=#006699]" y: "[/color]);
  1444.                 SERIAL_PROTOCOL(yProbe);
  1445.                 SERIAL_PROTOCOLPGM([color=#006699]" z: "[/color]);
  1446.                 SERIAL_PROTOCOL(current_position[[color=#006699]Z_AXIS[/color]]);
  1447.                 SERIAL_PROTOCOLPGM([color=#006699]"\n"[/color]);
  1448.  
  1449.                 eqnAMatrix[probePointCounter + 0*ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS] = xProbe;
  1450.                 eqnAMatrix[probePointCounter + 1*ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS] = yProbe;
  1451.                 eqnAMatrix[probePointCounter + 2*ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS] = 1;
  1452.                 probePointCounter++;
  1453.                 xProbe += xInc;
  1454.               }
  1455.             }
  1456.             clean_up_after_endstop_move();
  1457.  
  1458.             [color=#7E7E7E]// solve lsq problem[/color]
  1459.             [color=#CC6600]double[/color] *plane_equation_coefficients = qr_solve(ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS, 3, eqnAMatrix, eqnBVector);
  1460.  
  1461.             SERIAL_PROTOCOLPGM([color=#006699]"Eqn coefficients: a: "[/color]);
  1462.             SERIAL_PROTOCOL(plane_equation_coefficients[0]);
  1463.             SERIAL_PROTOCOLPGM([color=#006699]" b: "[/color]);
  1464.             SERIAL_PROTOCOL(plane_equation_coefficients[1]);
  1465.             SERIAL_PROTOCOLPGM([color=#006699]" d: "[/color]);
  1466.             SERIAL_PROTOCOLLN(plane_equation_coefficients[2]);
  1467.  
  1468.  
  1469.             set_bed_level_equation_lsq(plane_equation_coefficients);
  1470.  
  1471.             free(plane_equation_coefficients);
  1472.  
  1473. #else [color=#7E7E7E]// ACCURATE_BED_LEVELING not defined[/color]
  1474.  
  1475.  
  1476.             [color=#7E7E7E]// prob 1[/color]
  1477.             do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], Z_RAISE_BEFORE_PROBING);
  1478.             do_blocking_move_to(LEFT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, BACK_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[[color=#006699]Z_AXIS[/color]]);
  1479.  
  1480.             engage_z_probe();   [color=#7E7E7E]// Engage Z Servo endstop if available[/color]
  1481.             run_z_probe();
  1482.             [color=#CC6600]float[/color] z_at_xLeft_yBack = current_position[[color=#006699]Z_AXIS[/color]];
  1483.              do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + 1);
  1484.             retract_z_probe();
  1485.  
  1486.             SERIAL_PROTOCOLPGM([color=#006699]"Bed x: "[/color]);
  1487.             SERIAL_PROTOCOL(LEFT_PROBE_BED_POSITION);
  1488.             SERIAL_PROTOCOLPGM([color=#006699]" y: "[/color]);
  1489.             SERIAL_PROTOCOL(BACK_PROBE_BED_POSITION);
  1490.             SERIAL_PROTOCOLPGM([color=#006699]" z: "[/color]);
  1491.             SERIAL_PROTOCOL(current_position[[color=#006699]Z_AXIS[/color]]);
  1492.             SERIAL_PROTOCOLPGM([color=#006699]"\n"[/color]);
  1493.  
  1494.             [color=#7E7E7E]// prob 2[/color]
  1495.             do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + Z_RAISE_BETWEEN_PROBINGS);
  1496.             do_blocking_move_to(LEFT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, FRONT_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[[color=#006699]Z_AXIS[/color]]);
  1497.  
  1498.             engage_z_probe();   [color=#7E7E7E]// Engage Z Servo endstop if available[/color]
  1499.             run_z_probe();
  1500.             [color=#CC6600]float[/color] z_at_xLeft_yFront = current_position[[color=#006699]Z_AXIS[/color]];
  1501.              do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + 1);
  1502.             retract_z_probe();
  1503.  
  1504.             SERIAL_PROTOCOLPGM([color=#006699]"Bed x: "[/color]);
  1505.             SERIAL_PROTOCOL(LEFT_PROBE_BED_POSITION);
  1506.             SERIAL_PROTOCOLPGM([color=#006699]" y: "[/color]);
  1507.             SERIAL_PROTOCOL(FRONT_PROBE_BED_POSITION);
  1508.             SERIAL_PROTOCOLPGM([color=#006699]" z: "[/color]);
  1509.             SERIAL_PROTOCOL(current_position[[color=#006699]Z_AXIS[/color]]);
  1510.             SERIAL_PROTOCOLPGM([color=#006699]"\n"[/color]);
  1511.  
  1512.             [color=#7E7E7E]// prob 3[/color]
  1513.             do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + Z_RAISE_BETWEEN_PROBINGS);
  1514.             [color=#7E7E7E]// the current position will be updated by the blocking move so the head will not lower on this next call.[/color]
  1515.             do_blocking_move_to(RIGHT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, FRONT_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[[color=#006699]Z_AXIS[/color]]);
  1516.  
  1517.             engage_z_probe();   [color=#7E7E7E]// Engage Z Servo endstop if available[/color]
  1518.             run_z_probe();
  1519.             [color=#CC6600]float[/color] z_at_xRight_yFront = current_position[[color=#006699]Z_AXIS[/color]];
  1520.              do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + 1);
  1521.             retract_z_probe(); [color=#7E7E7E]// Retract Z Servo endstop if available[/color]
  1522.  
  1523.             SERIAL_PROTOCOLPGM([color=#006699]"Bed x: "[/color]);
  1524.             SERIAL_PROTOCOL(RIGHT_PROBE_BED_POSITION);
  1525.             SERIAL_PROTOCOLPGM([color=#006699]" y: "[/color]);
  1526.             SERIAL_PROTOCOL(FRONT_PROBE_BED_POSITION);
  1527.             SERIAL_PROTOCOLPGM([color=#006699]" z: "[/color]);
  1528.             SERIAL_PROTOCOL(current_position[[color=#006699]Z_AXIS[/color]]);
  1529.             SERIAL_PROTOCOLPGM([color=#006699]"\n"[/color]);
  1530.  
  1531.             clean_up_after_endstop_move();
  1532.  
  1533.             set_bed_level_equation(z_at_xLeft_yFront, z_at_xRight_yFront, z_at_xLeft_yBack);
  1534.  
  1535.  
  1536. #endif [color=#7E7E7E]// ACCURATE_BED_LEVELING[/color]
  1537.             st_synchronize();
  1538.  
  1539.             [color=#7E7E7E]// The following code correct the Z height difference from z-probe position and hotend tip position.[/color]
  1540.             [color=#7E7E7E]// The Z height on homing is measured by Z-Probe, but the probe is quite far from the hotend.[/color]
  1541.             [color=#7E7E7E]// When the bed is uneven, this height must be corrected.[/color]
  1542.             real_z = [color=#CC6600]float[/color](st_get_position([color=#006699]Z_AXIS[/color]))/axis_steps_per_unit[[color=#006699]Z_AXIS[/color]]; [color=#7E7E7E]//get the real Z (since the auto bed leveling is already correcting the plane)[/color]
  1543.             x_tmp = current_position[[color=#006699]X_AXIS[/color]] + X_PROBE_OFFSET_FROM_EXTRUDER;
  1544.             y_tmp = current_position[[color=#006699]Y_AXIS[/color]] + Y_PROBE_OFFSET_FROM_EXTRUDER;
  1545.             z_tmp = current_position[[color=#006699]Z_AXIS[/color]];
  1546.  
  1547.             apply_rotation_xyz(plan_bed_level_matrix, x_tmp, y_tmp, z_tmp);         [color=#7E7E7E]//Apply the correction sending the probe offset[/color]
  1548.             current_position[[color=#006699]Z_AXIS[/color]] = z_tmp - real_z + current_position[[color=#006699]Z_AXIS[/color]]; [color=#7E7E7E]//The difference is added to current position and sent to planner.[/color]
  1549.             plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1550.         }
  1551.         [color=#CC6600]break[/color];
  1552.  
  1553.     [color=#CC6600]case[/color] 30: [color=#7E7E7E]// G30 Single Z Probe[/color]
  1554.         {
  1555.             engage_z_probe(); [color=#7E7E7E]// Engage Z Servo endstop if available[/color]
  1556.  
  1557.             st_synchronize();
  1558.             [color=#7E7E7E]// TODO: make sure the bed_level_rotation_matrix is identity or the planner will get set incorectly[/color]
  1559.             setup_for_endstop_move();
  1560.  
  1561.             feedrate = homing_feedrate[[color=#006699]Z_AXIS[/color]];
  1562.  
  1563.             run_z_probe();
  1564.             SERIAL_PROTOCOLPGM([color=#006699]"Bed Position X: "[/color]);
  1565.             SERIAL_PROTOCOL(current_position[[color=#006699]X_AXIS[/color]]);
  1566.             SERIAL_PROTOCOLPGM([color=#006699]" Y: "[/color]);
  1567.             SERIAL_PROTOCOL(current_position[[color=#006699]Y_AXIS[/color]]);
  1568.             SERIAL_PROTOCOLPGM([color=#006699]" Z: "[/color]);
  1569.             SERIAL_PROTOCOL(current_position[[color=#006699]Z_AXIS[/color]]);
  1570.             SERIAL_PROTOCOLPGM([color=#006699]"\n"[/color]);
  1571.  
  1572.             clean_up_after_endstop_move();
  1573.  do_blocking_move_to(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + 1);
  1574.             retract_z_probe(); [color=#7E7E7E]// Retract Z Servo endstop if available[/color]
  1575.         }
  1576.         [color=#CC6600]break[/color];
  1577. #endif [color=#7E7E7E]// ENABLE_AUTO_BED_LEVELING[/color]
  1578.     [color=#CC6600]case[/color] 90: [color=#7E7E7E]// G90[/color]
  1579.       relative_mode = [color=#CC6600]false[/color];
  1580.       [color=#CC6600]break[/color];
  1581.     [color=#CC6600]case[/color] 91: [color=#7E7E7E]// G91[/color]
  1582.       relative_mode = [color=#CC6600]true[/color];
  1583.       [color=#CC6600]break[/color];
  1584.     [color=#CC6600]case[/color] 92: [color=#7E7E7E]// G92[/color]
  1585.       [color=#CC6600]if[/color](!code_seen(axis_codes[E_AXIS]))
  1586.         st_synchronize();
  1587.       [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  1588.         [color=#CC6600]if[/color](code_seen(axis_codes[i])) {
  1589.            [color=#CC6600]if[/color](i == E_AXIS) {
  1590.              current_position[i] = code_value();
  1591.              plan_set_e_position(current_position[E_AXIS]);
  1592.            }
  1593.            [color=#CC6600]else[/color] {
  1594.              current_position[i] = code_value()+add_homeing[i];
  1595.              plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  1596.            }
  1597.         }
  1598.       }
  1599.       [color=#CC6600]break[/color];
  1600.     }
  1601.   }
  1602.  
  1603.   [color=#CC6600]else[/color] [color=#CC6600]if[/color](code_seen([color=#006699]'M'[/color]))
  1604.   {
  1605.     [color=#CC6600]switch[/color]( ([color=#CC6600]int[/color])code_value() )
  1606.     {
  1607. #ifdef ULTIPANEL
  1608.     [color=#CC6600]case[/color] 0: [color=#7E7E7E]// M0 - Unconditional stop - Wait for user button press on LCD[/color]
  1609.     [color=#CC6600]case[/color] 1: [color=#7E7E7E]// M1 - Conditional stop - Wait for user button press on LCD[/color]
  1610.     {
  1611.       LCD_MESSAGEPGM(MSG_USERWAIT);
  1612.       codenum = 0;
  1613.       [color=#CC6600]if[/color](code_seen([color=#006699]'P'[/color])) codenum = code_value(); [color=#7E7E7E]// milliseconds to wait[/color]
  1614.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) codenum = code_value() * 1000; [color=#7E7E7E]// seconds to wait[/color]
  1615.  
  1616.       st_synchronize();
  1617.       previous_millis_cmd = [color=#CC6600]millis[/color]();
  1618.       [color=#CC6600]if[/color] (codenum > 0){
  1619.         codenum += [color=#CC6600]millis[/color](); [color=#7E7E7E]// keep track of when we started waiting[/color]
  1620.         [color=#CC6600]while[/color]([color=#CC6600]millis[/color]() < codenum && !lcd_clicked()){
  1621.           manage_heater();
  1622.           manage_inactivity();
  1623.           lcd_update();
  1624.         }
  1625.       }[color=#CC6600]else[/color]{
  1626.         [color=#CC6600]while[/color](!lcd_clicked()){
  1627.           manage_heater();
  1628.           manage_inactivity();
  1629.           lcd_update();
  1630.         }
  1631.       }
  1632.       LCD_MESSAGEPGM(MSG_RESUMING);
  1633.     }
  1634.     [color=#CC6600]break[/color];
  1635. #endif
  1636.     [color=#CC6600]case[/color] 17:
  1637.         LCD_MESSAGEPGM(MSG_NO_MOVE);
  1638.         enable_x();
  1639.         enable_y();
  1640.         enable_z();
  1641.         enable_e0();
  1642.         enable_e1();
  1643.         enable_e2();
  1644.       [color=#CC6600]break[/color];
  1645.  
  1646. #ifdef SDSUPPORT
  1647.     [color=#CC6600]case[/color] 20: [color=#7E7E7E]// M20 - list SD card[/color]
  1648.       SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST);
  1649.       card.ls();
  1650.       SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST);
  1651.       [color=#CC6600]break[/color];
  1652.     [color=#CC6600]case[/color] 21: [color=#7E7E7E]// M21 - init SD card[/color]
  1653.  
  1654.       card.initsd();
  1655.  
  1656.       [color=#CC6600]break[/color];
  1657.     [color=#CC6600]case[/color] 22: [color=#7E7E7E]//M22 - release SD card[/color]
  1658.       card.[color=#CC6600]release[/color]();
  1659.  
  1660.       [color=#CC6600]break[/color];
  1661.     [color=#CC6600]case[/color] 23: [color=#7E7E7E]//M23 - Select file[/color]
  1662.       starpos = (strchr(strchr_pointer + 4,[color=#006699]'*'[/color]));
  1663.       [color=#CC6600]if[/color](starpos!=NULL)
  1664.         *(starpos-1)=[color=#006699]'\0'[/color];
  1665.       card.openFile(strchr_pointer + 4,[color=#CC6600]true[/color]);
  1666.       [color=#CC6600]break[/color];
  1667.     [color=#CC6600]case[/color] 24: [color=#7E7E7E]//M24 - Start SD print[/color]
  1668.       card.startFileprint();
  1669.       starttime=[color=#CC6600]millis[/color]();
  1670.       [color=#CC6600]break[/color];
  1671.     [color=#CC6600]case[/color] 25: [color=#7E7E7E]//M25 - Pause SD print[/color]
  1672.       card.pauseSDPrint();
  1673.       [color=#CC6600]break[/color];
  1674.     [color=#CC6600]case[/color] 26: [color=#7E7E7E]//M26 - Set SD index[/color]
  1675.       [color=#CC6600]if[/color](card.cardOK && code_seen([color=#006699]'S'[/color])) {
  1676.         card.setIndex(code_value_long());
  1677.       }
  1678.       [color=#CC6600]break[/color];
  1679.     [color=#CC6600]case[/color] 27: [color=#7E7E7E]//M27 - Get SD status[/color]
  1680.       card.getStatus();
  1681.       [color=#CC6600]break[/color];
  1682.     [color=#CC6600]case[/color] 28: [color=#7E7E7E]//M28 - Start SD write[/color]
  1683.       starpos = (strchr(strchr_pointer + 4,[color=#006699]'*'[/color]));
  1684.       [color=#CC6600]if[/color](starpos != NULL){
  1685.         [color=#CC6600]char[/color]* npos = strchr(cmdbuffer[bufindr], [color=#006699]'N'[/color]);
  1686.         strchr_pointer = strchr(npos,[color=#006699]' '[/color]) + 1;
  1687.         *(starpos-1) = [color=#006699]'\0'[/color];
  1688.       }
  1689.       card.openFile(strchr_pointer+4,[color=#CC6600]false[/color]);
  1690.       [color=#CC6600]break[/color];
  1691.     [color=#CC6600]case[/color] 29: [color=#7E7E7E]//M29 - Stop SD write[/color]
  1692.       [color=#7E7E7E]//processed in write to file routine above[/color]
  1693.       [color=#7E7E7E]//card,saving = false;[/color]
  1694.       [color=#CC6600]break[/color];
  1695.     [color=#CC6600]case[/color] 30: [color=#7E7E7E]//M30 <filename> Delete File[/color]
  1696.       [color=#CC6600]if[/color] (card.cardOK){
  1697.         card.closefile();
  1698.         starpos = (strchr(strchr_pointer + 4,[color=#006699]'*'[/color]));
  1699.         [color=#CC6600]if[/color](starpos != NULL){
  1700.           [color=#CC6600]char[/color]* npos = strchr(cmdbuffer[bufindr], [color=#006699]'N'[/color]);
  1701.           strchr_pointer = strchr(npos,[color=#006699]' '[/color]) + 1;
  1702.           *(starpos-1) = [color=#006699]'\0'[/color];
  1703.         }
  1704.         card.removeFile(strchr_pointer + 4);
  1705.       }
  1706.       [color=#CC6600]break[/color];
  1707.     [color=#CC6600]case[/color] 32: [color=#7E7E7E]//M32 - Select file and start SD print[/color]
  1708.     {
  1709.       [color=#CC6600]if[/color](card.sdprinting) {
  1710.         st_synchronize();
  1711.  
  1712.       }
  1713.       starpos = (strchr(strchr_pointer + 4,[color=#006699]'*'[/color]));
  1714.  
  1715.       [color=#CC6600]char[/color]* namestartpos = (strchr(strchr_pointer + 4,[color=#006699]'!'[/color])); [color=#7E7E7E]//find ! to indicate filename string start.[/color]
  1716.       [color=#CC6600]if[/color](namestartpos==NULL)
  1717.       {
  1718.         namestartpos=strchr_pointer + 4; [color=#7E7E7E]//default name position, 4 letters after the M[/color]
  1719.       }
  1720.       [color=#CC6600]else[/color]
  1721.         namestartpos++; [color=#7E7E7E]//to skip the '!'[/color]
  1722.  
  1723.       [color=#CC6600]if[/color](starpos!=NULL)
  1724.         *(starpos-1)=[color=#006699]'\0'[/color];
  1725.  
  1726.       bool call_procedure=(code_seen([color=#006699]'P'[/color]));
  1727.  
  1728.       [color=#CC6600]if[/color](strchr_pointer>namestartpos)
  1729.         call_procedure=[color=#CC6600]false[/color]; [color=#7E7E7E]//false alert, 'P' found within filename[/color]
  1730.  
  1731.       [color=#CC6600]if[/color]( card.cardOK )
  1732.       {
  1733.         card.openFile(namestartpos,[color=#CC6600]true[/color],!call_procedure);
  1734.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color]))
  1735.           [color=#CC6600]if[/color](strchr_pointer<namestartpos) [color=#7E7E7E]//only if "S" is occuring _before_ the filename[/color]
  1736.             card.setIndex(code_value_long());
  1737.         card.startFileprint();
  1738.         [color=#CC6600]if[/color](!call_procedure)
  1739.           starttime=[color=#CC6600]millis[/color](); [color=#7E7E7E]//procedure calls count as normal print time.[/color]
  1740.       }
  1741.     } [color=#CC6600]break[/color];
  1742.     [color=#CC6600]case[/color] 928: [color=#7E7E7E]//M928 - Start SD write[/color]
  1743.       starpos = (strchr(strchr_pointer + 5,[color=#006699]'*'[/color]));
  1744.       [color=#CC6600]if[/color](starpos != NULL){
  1745.         [color=#CC6600]char[/color]* npos = strchr(cmdbuffer[bufindr], [color=#006699]'N'[/color]);
  1746.         strchr_pointer = strchr(npos,[color=#006699]' '[/color]) + 1;
  1747.         *(starpos-1) = [color=#006699]'\0'[/color];
  1748.       }
  1749.       card.openLogFile(strchr_pointer+5);
  1750.       [color=#CC6600]break[/color];
  1751.  
  1752. #endif [color=#7E7E7E]//SDSUPPORT[/color]
  1753.  
  1754.     [color=#CC6600]case[/color] 31: [color=#7E7E7E]//M31 take time since the start of the SD print or an M109 command[/color]
  1755.       {
  1756.       stoptime=[color=#CC6600]millis[/color]();
  1757.       [color=#CC6600]char[/color] time[30];
  1758.       [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] t=(stoptime-starttime)/1000;
  1759.       [color=#CC6600]int[/color] sec,[color=#CC6600]min[/color];
  1760.       [color=#CC6600]min[/color]=t/60;
  1761.       sec=t%60;
  1762.       sprintf_P(time, PSTR([color=#006699]"%i min, %i sec"[/color]), [color=#CC6600]min[/color], sec);
  1763.       SERIAL_ECHO_START;
  1764.       SERIAL_ECHOLN(time);
  1765.       lcd_setstatus(time);
  1766.       autotempShutdown();
  1767.       }
  1768.       [color=#CC6600]break[/color];
  1769.     [color=#CC6600]case[/color] 42: [color=#7E7E7E]//M42 -Change pin status via gcode[/color]
  1770.       [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color]))
  1771.       {
  1772.         [color=#CC6600]int[/color] pin_status = code_value();
  1773.         [color=#CC6600]int[/color] pin_number = LED_PIN;
  1774.         [color=#CC6600]if[/color] (code_seen([color=#006699]'P'[/color]) && pin_status >= 0 && pin_status <= 255)
  1775.           pin_number = code_value();
  1776.         [color=#CC6600]for[/color](int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++)
  1777.         {
  1778.           [color=#CC6600]if[/color] (sensitive_pins[i] == pin_number)
  1779.           {
  1780.             pin_number = -1;
  1781.             [color=#CC6600]break[/color];
  1782.           }
  1783.         }
  1784.       #if defined(FAN_PIN) && FAN_PIN > -1
  1785.         [color=#CC6600]if[/color] (pin_number == FAN_PIN)
  1786.           fanSpeed = pin_status;
  1787.       #endif
  1788.         [color=#CC6600]if[/color] (pin_number > -1)
  1789.         {
  1790.           [color=#CC6600]pinMode[/color](pin_number, [color=#006699]OUTPUT[/color]);
  1791.           [color=#CC6600]digitalWrite[/color](pin_number, pin_status);
  1792.           [color=#CC6600]analogWrite[/color](pin_number, pin_status);
  1793.         }
  1794.       }
  1795.      [color=#CC6600]break[/color];
  1796.     [color=#CC6600]case[/color] 104: [color=#7E7E7E]// M104[/color]
  1797.       [color=#CC6600]if[/color](setTargetedHotend(104)){
  1798.         [color=#CC6600]break[/color];
  1799.       }
  1800.       [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) setTargetHotend(code_value(), tmp_extruder);
  1801. #ifdef DUAL_X_CARRIAGE
  1802.       [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
  1803.         setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
  1804. #endif
  1805.       setWatch();
  1806.       [color=#CC6600]break[/color];
  1807.     [color=#CC6600]case[/color] 140: [color=#7E7E7E]// M140 set bed temp[/color]
  1808.       [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) setTargetBed(code_value());
  1809.       [color=#CC6600]break[/color];
  1810.     [color=#CC6600]case[/color] 105 : [color=#7E7E7E]// M105[/color]
  1811.       [color=#CC6600]if[/color](setTargetedHotend(105)){
  1812.         [color=#CC6600]break[/color];
  1813.         }
  1814.       #if defined(TEMP_0_PIN) && TEMP_0_PIN > -1
  1815.         SERIAL_PROTOCOLPGM([color=#006699]"ok T:"[/color]);
  1816.         SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1);
  1817.         SERIAL_PROTOCOLPGM([color=#006699]" /"[/color]);
  1818.         SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1);
  1819.         #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
  1820.           SERIAL_PROTOCOLPGM([color=#006699]" B:"[/color]);
  1821.           SERIAL_PROTOCOL_F(degBed(),1);
  1822.           SERIAL_PROTOCOLPGM([color=#006699]" /"[/color]);
  1823.           SERIAL_PROTOCOL_F(degTargetBed(),1);
  1824.         #endif [color=#7E7E7E]//TEMP_BED_PIN[/color]
  1825.         [color=#CC6600]for[/color] (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
  1826.           SERIAL_PROTOCOLPGM([color=#006699]" T"[/color]);
  1827.           SERIAL_PROTOCOL(cur_extruder);
  1828.           SERIAL_PROTOCOLPGM([color=#006699]":"[/color]);
  1829.           SERIAL_PROTOCOL_F(degHotend(cur_extruder),1);
  1830.           SERIAL_PROTOCOLPGM([color=#006699]" /"[/color]);
  1831.           SERIAL_PROTOCOL_F(degTargetHotend(cur_extruder),1);
  1832.         }
  1833.       #else
  1834.         SERIAL_ERROR_START;
  1835.         SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
  1836.       #endif
  1837.  
  1838.         SERIAL_PROTOCOLPGM([color=#006699]" @:"[/color]);
  1839.       #ifdef EXTRUDER_WATTS
  1840.         SERIAL_PROTOCOL((EXTRUDER_WATTS * getHeaterPower(tmp_extruder))/127);
  1841.         SERIAL_PROTOCOLPGM([color=#006699]"W"[/color]);
  1842.       #else
  1843.         SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));
  1844.       #endif
  1845.  
  1846.         SERIAL_PROTOCOLPGM([color=#006699]" B@:"[/color]);
  1847.       #ifdef BED_WATTS
  1848.         SERIAL_PROTOCOL((BED_WATTS * getHeaterPower(-1))/127);
  1849.         SERIAL_PROTOCOLPGM([color=#006699]"W"[/color]);
  1850.       #else
  1851.         SERIAL_PROTOCOL(getHeaterPower(-1));
  1852.       #endif
  1853.  
  1854.         #ifdef SHOW_TEMP_ADC_VALUES
  1855.           #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
  1856.             SERIAL_PROTOCOLPGM([color=#006699]" ADC B:"[/color]);
  1857.             SERIAL_PROTOCOL_F(degBed(),1);
  1858.             SERIAL_PROTOCOLPGM([color=#006699]"C->"[/color]);
  1859.             SERIAL_PROTOCOL_F(rawBedTemp()/OVERSAMPLENR,0);
  1860.           #endif
  1861.           [color=#CC6600]for[/color] (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
  1862.             SERIAL_PROTOCOLPGM([color=#006699]" T"[/color]);
  1863.             SERIAL_PROTOCOL(cur_extruder);
  1864.             SERIAL_PROTOCOLPGM([color=#006699]":"[/color]);
  1865.             SERIAL_PROTOCOL_F(degHotend(cur_extruder),1);
  1866.             SERIAL_PROTOCOLPGM([color=#006699]"C->"[/color]);
  1867.             SERIAL_PROTOCOL_F(rawHotendTemp(cur_extruder)/OVERSAMPLENR,0);
  1868.           }
  1869.         #endif
  1870.  
  1871.         SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  1872.       [color=#CC6600]return[/color];
  1873.       [color=#CC6600]break[/color];
  1874.     [color=#CC6600]case[/color] 109:
  1875.     {[color=#7E7E7E]// M109 - Wait for extruder heater to reach target.[/color]
  1876.       [color=#CC6600]if[/color](setTargetedHotend(109)){
  1877.         [color=#CC6600]break[/color];
  1878.       }
  1879.       LCD_MESSAGEPGM(MSG_HEATING);
  1880.       #ifdef AUTOTEMP
  1881.         autotemp_enabled=[color=#CC6600]false[/color];
  1882.       #endif
  1883.       [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) {
  1884.         setTargetHotend(code_value(), tmp_extruder);
  1885. #ifdef DUAL_X_CARRIAGE
  1886.         [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
  1887.           setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
  1888. #endif
  1889.         CooldownNoWait = [color=#CC6600]true[/color];
  1890.       } [color=#CC6600]else[/color] [color=#CC6600]if[/color] (code_seen([color=#006699]'R'[/color])) {
  1891.         setTargetHotend(code_value(), tmp_extruder);
  1892. #ifdef DUAL_X_CARRIAGE
  1893.         [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE && tmp_extruder == 0)
  1894.           setTargetHotend1(code_value() == 0.0 ? 0.0 : code_value() + duplicate_extruder_temp_offset);
  1895. #endif
  1896.         CooldownNoWait = [color=#CC6600]false[/color];
  1897.       }
  1898.       #ifdef AUTOTEMP
  1899.         [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) autotemp_min=code_value();
  1900.         [color=#CC6600]if[/color] (code_seen([color=#006699]'B'[/color])) autotemp_max=code_value();
  1901.         [color=#CC6600]if[/color] (code_seen([color=#006699]'F'[/color]))
  1902.         {
  1903.           autotemp_factor=code_value();
  1904.           autotemp_enabled=[color=#CC6600]true[/color];
  1905.         }
  1906.       #endif
  1907.  
  1908.       setWatch();
  1909.       codenum = [color=#CC6600]millis[/color]();
  1910.  
  1911.       [color=#7E7E7E]/* See if we are heating up or cooling down */[/color]
  1912.       target_direction = isHeatingHotend(tmp_extruder); [color=#7E7E7E]// true if heating, false if cooling[/color]
  1913.  
  1914.       #ifdef TEMP_RESIDENCY_TIME
  1915.         [color=#CC6600]long[/color] residencyStart;
  1916.         residencyStart = -1;
  1917.         [color=#7E7E7E]/* continue to loop until we have reached the target temp[/color]
  1918. [color=#7E7E7E]          _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */[/color]
  1919.         [color=#CC6600]while[/color]((residencyStart == -1) ||
  1920.               (residencyStart >= 0 && ((([color=#CC6600]unsigned[/color] [color=#CC6600]int[/color]) ([color=#CC6600]millis[/color]() - residencyStart)) < (TEMP_RESIDENCY_TIME * 1000UL))) ) {
  1921.       #else
  1922.         [color=#CC6600]while[/color] ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==[color=#CC6600]false[/color])) ) {
  1923.       #endif [color=#7E7E7E]//TEMP_RESIDENCY_TIME[/color]
  1924.           [color=#CC6600]if[/color]( ([color=#CC6600]millis[/color]() - codenum) > 1000UL )
  1925.           { [color=#7E7E7E]//Print Temp Reading and remaining time every 1 second while heating up/cooling down[/color]
  1926.             SERIAL_PROTOCOLPGM([color=#006699]"T:"[/color]);
  1927.             SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1);
  1928.             SERIAL_PROTOCOLPGM([color=#006699]" E:"[/color]);
  1929.             SERIAL_PROTOCOL(([color=#CC6600]int[/color])tmp_extruder);
  1930.             #ifdef TEMP_RESIDENCY_TIME
  1931.               SERIAL_PROTOCOLPGM([color=#006699]" W:"[/color]);
  1932.               [color=#CC6600]if[/color](residencyStart > -1)
  1933.               {
  1934.                  codenum = ((TEMP_RESIDENCY_TIME * 1000UL) - ([color=#CC6600]millis[/color]() - residencyStart)) / 1000UL;
  1935.                  SERIAL_PROTOCOLLN( codenum );
  1936.               }
  1937.               [color=#CC6600]else[/color]
  1938.               {
  1939.                  SERIAL_PROTOCOLLN( [color=#006699]"?"[/color] );
  1940.               }
  1941.             #else
  1942.               SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  1943.             #endif
  1944.             codenum = [color=#CC6600]millis[/color]();
  1945.           }
  1946.           manage_heater();
  1947.           manage_inactivity();
  1948.           lcd_update();
  1949.         #ifdef TEMP_RESIDENCY_TIME
  1950.             [color=#7E7E7E]/* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time[/color]
  1951. [color=#7E7E7E]              or when current temp falls outside the hysteresis after target temp was reached */[/color]
  1952.           [color=#CC6600]if[/color] ((residencyStart == -1 && target_direction && (degHotend(tmp_extruder) >= (degTargetHotend(tmp_extruder)-TEMP_WINDOW))) ||
  1953.               (residencyStart == -1 && !target_direction && (degHotend(tmp_extruder) <= (degTargetHotend(tmp_extruder)+TEMP_WINDOW))) ||
  1954.               (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) )
  1955.           {
  1956.             residencyStart = [color=#CC6600]millis[/color]();
  1957.           }
  1958.         #endif [color=#7E7E7E]//TEMP_RESIDENCY_TIME[/color]
  1959.         }
  1960.         LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
  1961.         starttime=[color=#CC6600]millis[/color]();
  1962.         previous_millis_cmd = [color=#CC6600]millis[/color]();
  1963.       }
  1964.       [color=#CC6600]break[/color];
  1965.     [color=#CC6600]case[/color] 190: [color=#7E7E7E]// M190 - Wait for bed heater to reach target.[/color]
  1966.     #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
  1967.         LCD_MESSAGEPGM(MSG_BED_HEATING);
  1968.         [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) {
  1969.           setTargetBed(code_value());
  1970.           CooldownNoWait = [color=#CC6600]true[/color];
  1971.         } [color=#CC6600]else[/color] [color=#CC6600]if[/color] (code_seen([color=#006699]'R'[/color])) {
  1972.           setTargetBed(code_value());
  1973.           CooldownNoWait = [color=#CC6600]false[/color];
  1974.         }
  1975.         codenum = [color=#CC6600]millis[/color]();
  1976.  
  1977.         target_direction = isHeatingBed(); [color=#7E7E7E]// true if heating, false if cooling[/color]
  1978.  
  1979.         [color=#CC6600]while[/color] ( target_direction ? (isHeatingBed()) : (isCoolingBed()&&(CooldownNoWait==[color=#CC6600]false[/color])) )
  1980.         {
  1981.           [color=#CC6600]if[/color](( [color=#CC6600]millis[/color]() - codenum) > 1000 ) [color=#7E7E7E]//Print Temp Reading every 1 second while heating up.[/color]
  1982.           {
  1983.             [color=#CC6600]float[/color] tt=degHotend(active_extruder);
  1984.             SERIAL_PROTOCOLPGM([color=#006699]"T:"[/color]);
  1985.             SERIAL_PROTOCOL(tt);
  1986.             SERIAL_PROTOCOLPGM([color=#006699]" E:"[/color]);
  1987.             SERIAL_PROTOCOL(([color=#CC6600]int[/color])active_extruder);
  1988.             SERIAL_PROTOCOLPGM([color=#006699]" B:"[/color]);
  1989.             SERIAL_PROTOCOL_F(degBed(),1);
  1990.             SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  1991.             codenum = [color=#CC6600]millis[/color]();
  1992.           }
  1993.           manage_heater();
  1994.           manage_inactivity();
  1995.           lcd_update();
  1996.         }
  1997.         LCD_MESSAGEPGM(MSG_BED_DONE);
  1998.         previous_millis_cmd = [color=#CC6600]millis[/color]();
  1999.     #endif
  2000.         [color=#CC6600]break[/color];
  2001.  
  2002.     #if defined(FAN_PIN) && FAN_PIN > -1
  2003.       [color=#CC6600]case[/color] 106: [color=#7E7E7E]//M106 Fan On[/color]
  2004.         [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])){
  2005.            fanSpeed=[color=#CC6600]constrain[/color](code_value(),0,255);
  2006.         }
  2007.         [color=#CC6600]else[/color] {
  2008.           fanSpeed=255;
  2009.         }
  2010.         [color=#CC6600]break[/color];
  2011.       [color=#CC6600]case[/color] 107: [color=#7E7E7E]//M107 Fan Off[/color]
  2012.         fanSpeed = 0;
  2013.         [color=#CC6600]break[/color];
  2014.     #endif [color=#7E7E7E]//FAN_PIN[/color]
  2015.     #ifdef BARICUDA
  2016.       [color=#7E7E7E]// PWM for HEATER_1_PIN[/color]
  2017.       #if defined(HEATER_1_PIN) && HEATER_1_PIN > -1
  2018.         [color=#CC6600]case[/color] 126: [color=#7E7E7E]//M126 valve open[/color]
  2019.           [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])){
  2020.              ValvePressure=[color=#CC6600]constrain[/color](code_value(),0,255);
  2021.           }
  2022.           [color=#CC6600]else[/color] {
  2023.             ValvePressure=255;
  2024.           }
  2025.           [color=#CC6600]break[/color];
  2026.         [color=#CC6600]case[/color] 127: [color=#7E7E7E]//M127 valve closed[/color]
  2027.           ValvePressure = 0;
  2028.           [color=#CC6600]break[/color];
  2029.       #endif [color=#7E7E7E]//HEATER_1_PIN[/color]
  2030.  
  2031.       [color=#7E7E7E]// PWM for HEATER_2_PIN[/color]
  2032.       #if defined(HEATER_2_PIN) && HEATER_2_PIN > -1
  2033.         [color=#CC6600]case[/color] 128: [color=#7E7E7E]//M128 valve open[/color]
  2034.           [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])){
  2035.              EtoPPressure=[color=#CC6600]constrain[/color](code_value(),0,255);
  2036.           }
  2037.           [color=#CC6600]else[/color] {
  2038.             EtoPPressure=255;
  2039.           }
  2040.           [color=#CC6600]break[/color];
  2041.         [color=#CC6600]case[/color] 129: [color=#7E7E7E]//M129 valve closed[/color]
  2042.           EtoPPressure = 0;
  2043.           [color=#CC6600]break[/color];
  2044.       #endif [color=#7E7E7E]//HEATER_2_PIN[/color]
  2045.     #endif
  2046.  
  2047.     #if defined(PS_ON_PIN) && PS_ON_PIN > -1
  2048.       [color=#CC6600]case[/color] 80: [color=#7E7E7E]// M80 - Turn on Power Supply[/color]
  2049.         SET_OUTPUT(PS_ON_PIN); [color=#7E7E7E]//GND[/color]
  2050.         WRITE(PS_ON_PIN, PS_ON_AWAKE);
  2051.  
  2052.         [color=#7E7E7E]// If you have a switch on suicide pin, this is useful[/color]
  2053.         [color=#7E7E7E]// if you want to start another print with suicide feature after[/color]
  2054.         [color=#7E7E7E]// a print without suicide...[/color]
  2055.         #if defined SUICIDE_PIN && SUICIDE_PIN > -1
  2056.             SET_OUTPUT(SUICIDE_PIN);
  2057.             WRITE(SUICIDE_PIN, [color=#006699]HIGH[/color]);
  2058.         #endif
  2059.  
  2060.         #ifdef ULTIPANEL
  2061.           powersupply = [color=#CC6600]true[/color];
  2062.           LCD_MESSAGEPGM(WELCOME_MSG);
  2063.           lcd_update();
  2064.         #endif
  2065.         [color=#CC6600]break[/color];
  2066.       #endif
  2067.  
  2068.       [color=#CC6600]case[/color] 81: [color=#7E7E7E]// M81 - Turn off Power Supply[/color]
  2069.         disable_heater();
  2070.         st_synchronize();
  2071.         disable_e0();
  2072.         disable_e1();
  2073.         disable_e2();
  2074.         finishAndDisableSteppers();
  2075.         fanSpeed = 0;
  2076.         [color=#CC6600]delay[/color](1000); [color=#7E7E7E]// Wait a little before to switch off[/color]
  2077.       #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1
  2078.         st_synchronize();
  2079.         suicide();
  2080.       #elif defined(PS_ON_PIN) && PS_ON_PIN > -1
  2081.         SET_OUTPUT(PS_ON_PIN);
  2082.         WRITE(PS_ON_PIN, PS_ON_ASLEEP);
  2083.       #endif
  2084.       #ifdef ULTIPANEL
  2085.         powersupply = [color=#CC6600]false[/color];
  2086.         LCD_MESSAGEPGM(MACHINE_NAME[color=#006699]" "[/color]MSG_OFF[color=#006699]"."[/color]);
  2087.         lcd_update();
  2088.       #endif
  2089.   [color=#CC6600]break[/color];
  2090.  
  2091.     [color=#CC6600]case[/color] 82:
  2092.       axis_relative_modes[3] = [color=#CC6600]false[/color];
  2093.       [color=#CC6600]break[/color];
  2094.     [color=#CC6600]case[/color] 83:
  2095.       axis_relative_modes[3] = [color=#CC6600]true[/color];
  2096.       [color=#CC6600]break[/color];
  2097.     [color=#CC6600]case[/color] 18: [color=#7E7E7E]//compatibility[/color]
  2098.     [color=#CC6600]case[/color] 84: [color=#7E7E7E]// M84[/color]
  2099.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])){
  2100.         stepper_inactive_time = code_value() * 1000;
  2101.       }
  2102.       [color=#CC6600]else[/color]
  2103.       {
  2104.         bool all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))|| (code_seen(axis_codes[3])));
  2105.         [color=#CC6600]if[/color](all_axis)
  2106.         {
  2107.           st_synchronize();
  2108.           disable_e0();
  2109.           disable_e1();
  2110.           disable_e2();
  2111.           finishAndDisableSteppers();
  2112.         }
  2113.         [color=#CC6600]else[/color]
  2114.         {
  2115.           st_synchronize();
  2116.           [color=#CC6600]if[/color](code_seen([color=#006699]'X'[/color])) disable_x();
  2117.           [color=#CC6600]if[/color](code_seen([color=#006699]'Y'[/color])) disable_y();
  2118.           [color=#CC6600]if[/color](code_seen([color=#006699]'Z'[/color])) disable_z();
  2119.           #if ((E0_ENABLE_PIN != X_ENABLE_PIN) && (E1_ENABLE_PIN != Y_ENABLE_PIN)) [color=#7E7E7E]// Only enable on boards that have seperate ENABLE_PINS[/color]
  2120.             [color=#CC6600]if[/color](code_seen([color=#006699]'E'[/color])) {
  2121.               disable_e0();
  2122.               disable_e1();
  2123.               disable_e2();
  2124.             }
  2125.           #endif
  2126.         }
  2127.       }
  2128.       [color=#CC6600]break[/color];
  2129.     [color=#CC6600]case[/color] 85: [color=#7E7E7E]// M85[/color]
  2130.       code_seen([color=#006699]'S'[/color]);
  2131.       max_inactive_time = code_value() * 1000;
  2132.       [color=#CC6600]break[/color];
  2133.     [color=#CC6600]case[/color] 92: [color=#7E7E7E]// M92[/color]
  2134.       [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++)
  2135.       {
  2136.         [color=#CC6600]if[/color](code_seen(axis_codes[i]))
  2137.         {
  2138.           [color=#CC6600]if[/color](i == 3) { [color=#7E7E7E]// E[/color]
  2139.             [color=#CC6600]float[/color] value = code_value();
  2140.             [color=#CC6600]if[/color](value < 20.0) {
  2141.               [color=#CC6600]float[/color] factor = axis_steps_per_unit[i] / value; [color=#7E7E7E]// increase e constants if M92 E14 is given for netfab.[/color]
  2142.               max_e_jerk *= factor;
  2143.               max_feedrate[i] *= factor;
  2144.               axis_steps_per_sqr_second[i] *= factor;
  2145.             }
  2146.             axis_steps_per_unit[i] = value;
  2147.           }
  2148.           [color=#CC6600]else[/color] {
  2149.             axis_steps_per_unit[i] = code_value();
  2150.           }
  2151.         }
  2152.       }
  2153.       [color=#CC6600]break[/color];
  2154.     [color=#CC6600]case[/color] 115: [color=#7E7E7E]// M115[/color]
  2155.       SERIAL_PROTOCOLPGM(MSG_M115_REPORT);
  2156.       [color=#CC6600]break[/color];
  2157.     [color=#CC6600]case[/color] 117: [color=#7E7E7E]// M117 display message[/color]
  2158.       starpos = (strchr(strchr_pointer + 5,[color=#006699]'*'[/color]));
  2159.       [color=#CC6600]if[/color](starpos!=NULL)
  2160.         *(starpos-1)=[color=#006699]'\0'[/color];
  2161.       lcd_setstatus(strchr_pointer + 5);
  2162.       [color=#CC6600]break[/color];
  2163.     [color=#CC6600]case[/color] 114: [color=#7E7E7E]// M114[/color]
  2164.       SERIAL_PROTOCOLPGM([color=#006699]"X:"[/color]);
  2165.       SERIAL_PROTOCOL(current_position[[color=#006699]X_AXIS[/color]]);
  2166.       SERIAL_PROTOCOLPGM([color=#006699]"Y:"[/color]);
  2167.       SERIAL_PROTOCOL(current_position[[color=#006699]Y_AXIS[/color]]);
  2168.       SERIAL_PROTOCOLPGM([color=#006699]"Z:"[/color]);
  2169.       SERIAL_PROTOCOL(current_position[[color=#006699]Z_AXIS[/color]]);
  2170.       SERIAL_PROTOCOLPGM([color=#006699]"E:"[/color]);
  2171.       SERIAL_PROTOCOL(current_position[E_AXIS]);
  2172.  
  2173.       SERIAL_PROTOCOLPGM(MSG_COUNT_X);
  2174.       SERIAL_PROTOCOL([color=#CC6600]float[/color](st_get_position([color=#006699]X_AXIS[/color]))/axis_steps_per_unit[[color=#006699]X_AXIS[/color]]);
  2175.       SERIAL_PROTOCOLPGM([color=#006699]"Y:"[/color]);
  2176.       SERIAL_PROTOCOL([color=#CC6600]float[/color](st_get_position([color=#006699]Y_AXIS[/color]))/axis_steps_per_unit[[color=#006699]Y_AXIS[/color]]);
  2177.       SERIAL_PROTOCOLPGM([color=#006699]"Z:"[/color]);
  2178.       SERIAL_PROTOCOL([color=#CC6600]float[/color](st_get_position([color=#006699]Z_AXIS[/color]))/axis_steps_per_unit[[color=#006699]Z_AXIS[/color]]);
  2179.  
  2180.       SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  2181.       [color=#CC6600]break[/color];
  2182.     [color=#CC6600]case[/color] 120: [color=#7E7E7E]// M120[/color]
  2183.       enable_endstops([color=#CC6600]false[/color]) ;
  2184.       [color=#CC6600]break[/color];
  2185.     [color=#CC6600]case[/color] 121: [color=#7E7E7E]// M121[/color]
  2186.       enable_endstops([color=#CC6600]true[/color]) ;
  2187.       [color=#CC6600]break[/color];
  2188.     [color=#CC6600]case[/color] 119: [color=#7E7E7E]// M119[/color]
  2189.     SERIAL_PROTOCOLLN(MSG_M119_REPORT);
  2190.       #if defined(X_MIN_PIN) && X_MIN_PIN > -1
  2191.         SERIAL_PROTOCOLPGM(MSG_X_MIN);
  2192.         SERIAL_PROTOCOLLN(((READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN));
  2193.       #endif
  2194.       #if defined(X_MAX_PIN) && X_MAX_PIN > -1
  2195.         SERIAL_PROTOCOLPGM(MSG_X_MAX);
  2196.         SERIAL_PROTOCOLLN(((READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN));
  2197.       #endif
  2198.       #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
  2199.         SERIAL_PROTOCOLPGM(MSG_Y_MIN);
  2200.         SERIAL_PROTOCOLLN(((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN));
  2201.       #endif
  2202.       #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
  2203.         SERIAL_PROTOCOLPGM(MSG_Y_MAX);
  2204.         SERIAL_PROTOCOLLN(((READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN));
  2205.       #endif
  2206.       #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
  2207.         SERIAL_PROTOCOLPGM(MSG_Z_MIN);
  2208.         SERIAL_PROTOCOLLN(((READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN));
  2209.       #endif
  2210.       #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
  2211.         SERIAL_PROTOCOLPGM(MSG_Z_MAX);
  2212.         SERIAL_PROTOCOLLN(((READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN));
  2213.       #endif
  2214.       [color=#CC6600]break[/color];
  2215.       [color=#7E7E7E]//TODO: update for all axis, use for loop[/color]
  2216.     #ifdef BLINKM
  2217.     [color=#CC6600]case[/color] 150: [color=#7E7E7E]// M150[/color]
  2218.       {
  2219.         [color=#CC6600]byte[/color] red;
  2220.         [color=#CC6600]byte[/color] grn;
  2221.         [color=#CC6600]byte[/color] blu;
  2222.  
  2223.         [color=#CC6600]if[/color](code_seen([color=#006699]'R'[/color])) red = code_value();
  2224.         [color=#CC6600]if[/color](code_seen([color=#006699]'U'[/color])) grn = code_value();
  2225.         [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color])) blu = code_value();
  2226.  
  2227.         SendColors(red,grn,blu);
  2228.       }
  2229.       [color=#CC6600]break[/color];
  2230.     #endif [color=#7E7E7E]//BLINKM[/color]
  2231.     [color=#CC6600]case[/color] 200: [color=#7E7E7E]// M200 D<millimeters> set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).[/color]
  2232.       {
  2233.         [color=#CC6600]float[/color] area = .0;
  2234.         [color=#CC6600]float[/color] radius = .0;
  2235.         [color=#CC6600]if[/color](code_seen([color=#006699]'D'[/color])) {
  2236.           radius = ([color=#CC6600]float[/color])code_value() * .5;
  2237.           [color=#CC6600]if[/color](radius == 0) {
  2238.             area = 1;
  2239.           } [color=#CC6600]else[/color] {
  2240.             area = M_PI * pow(radius, 2);
  2241.           }
  2242.         } [color=#CC6600]else[/color] {
  2243.           [color=#7E7E7E]//reserved for setting filament diameter via UFID or filament measuring device[/color]
  2244.           [color=#CC6600]break[/color];
  2245.         }
  2246.         tmp_extruder = active_extruder;
  2247.         [color=#CC6600]if[/color](code_seen([color=#006699]'T'[/color])) {
  2248.           tmp_extruder = code_value();
  2249.           [color=#CC6600]if[/color](tmp_extruder >= EXTRUDERS) {
  2250.             SERIAL_ECHO_START;
  2251.             SERIAL_ECHO(MSG_M200_INVALID_EXTRUDER);
  2252.           }
  2253.           SERIAL_ECHOLN(tmp_extruder);
  2254.           [color=#CC6600]break[/color];
  2255.         }
  2256.         volumetric_multiplier[tmp_extruder] = 1 / area;
  2257.       }
  2258.       [color=#CC6600]break[/color];
  2259.     [color=#CC6600]case[/color] 201: [color=#7E7E7E]// M201[/color]
  2260.       [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++)
  2261.       {
  2262.         [color=#CC6600]if[/color](code_seen(axis_codes[i]))
  2263.         {
  2264.           max_acceleration_units_per_sq_second[i] = code_value();
  2265.         }
  2266.       }
  2267.       [color=#7E7E7E]// steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner)[/color]
  2268.       reset_acceleration_rates();
  2269.       [color=#CC6600]break[/color];
  2270.     #if 0 [color=#7E7E7E]// Not used for Sprinter/grbl gen6[/color]
  2271.     [color=#CC6600]case[/color] 202: [color=#7E7E7E]// M202[/color]
  2272.       [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  2273.         [color=#CC6600]if[/color](code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
  2274.       }
  2275.       [color=#CC6600]break[/color];
  2276.     #endif
  2277.     [color=#CC6600]case[/color] 203: [color=#7E7E7E]// M203 max feedrate mm/sec[/color]
  2278.       [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  2279.         [color=#CC6600]if[/color](code_seen(axis_codes[i])) max_feedrate[i] = code_value();
  2280.       }
  2281.       [color=#CC6600]break[/color];
  2282.     [color=#CC6600]case[/color] 204: [color=#7E7E7E]// M204 acclereration S normal moves T filmanent only moves[/color]
  2283.       {
  2284.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) acceleration = code_value() ;
  2285.         [color=#CC6600]if[/color](code_seen([color=#006699]'T'[/color])) retract_acceleration = code_value() ;
  2286.       }
  2287.       [color=#CC6600]break[/color];
  2288.     [color=#CC6600]case[/color] 205: [color=#7E7E7E]//M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk[/color]
  2289.     {
  2290.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) minimumfeedrate = code_value();
  2291.       [color=#CC6600]if[/color](code_seen([color=#006699]'T'[/color])) mintravelfeedrate = code_value();
  2292.       [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color])) minsegmenttime = code_value() ;
  2293.       [color=#CC6600]if[/color](code_seen([color=#006699]'X'[/color])) max_xy_jerk = code_value() ;
  2294.       [color=#CC6600]if[/color](code_seen([color=#006699]'Z'[/color])) max_z_jerk = code_value() ;
  2295.       [color=#CC6600]if[/color](code_seen([color=#006699]'E'[/color])) max_e_jerk = code_value() ;
  2296.     }
  2297.     [color=#CC6600]break[/color];
  2298.     [color=#CC6600]case[/color] 206: [color=#7E7E7E]// M206 additional homeing offset[/color]
  2299.       [color=#CC6600]for[/color](int8_t i=0; i < 3; i++)
  2300.       {
  2301.         [color=#CC6600]if[/color](code_seen(axis_codes[i])) add_homeing[i] = code_value();
  2302.       }
  2303.       [color=#CC6600]break[/color];
  2304.     #ifdef DELTA
  2305.     [color=#CC6600]case[/color] 666: [color=#7E7E7E]// M666 set delta endstop adjustemnt[/color]
  2306.       [color=#CC6600]for[/color](int8_t i=0; i < 3; i++)
  2307.       {
  2308.         [color=#CC6600]if[/color](code_seen(axis_codes[i])) endstop_adj[i] = code_value();
  2309.       }
  2310.       [color=#CC6600]break[/color];
  2311.     #endif
  2312.     #ifdef FWRETRACT
  2313.     [color=#CC6600]case[/color] 207: [color=#7E7E7E]//M207 - set retract length S[positive mm] F[feedrate mm/sec] Z[additional zlift/hop][/color]
  2314.     {
  2315.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color]))
  2316.       {
  2317.         retract_length = code_value() ;
  2318.       }
  2319.       [color=#CC6600]if[/color](code_seen([color=#006699]'F'[/color]))
  2320.       {
  2321.         retract_feedrate = code_value() ;
  2322.       }
  2323.       [color=#CC6600]if[/color](code_seen([color=#006699]'Z'[/color]))
  2324.       {
  2325.         retract_zlift = code_value() ;
  2326.       }
  2327.     }[color=#CC6600]break[/color];
  2328.     [color=#CC6600]case[/color] 208: [color=#7E7E7E]// M208 - set retract recover length S[positive mm surplus to the M207 S*] F[feedrate mm/sec][/color]
  2329.     {
  2330.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color]))
  2331.       {
  2332.         retract_recover_length = code_value() ;
  2333.       }
  2334.       [color=#CC6600]if[/color](code_seen([color=#006699]'F'[/color]))
  2335.       {
  2336.         retract_recover_feedrate = code_value() ;
  2337.       }
  2338.     }[color=#CC6600]break[/color];
  2339.     [color=#CC6600]case[/color] 209: [color=#7E7E7E]// M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.[/color]
  2340.     {
  2341.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color]))
  2342.       {
  2343.         [color=#CC6600]int[/color] t= code_value() ;
  2344.         [color=#CC6600]switch[/color](t)
  2345.         {
  2346.           [color=#CC6600]case[/color] 0: autoretract_enabled=[color=#CC6600]false[/color];retracted=[color=#CC6600]false[/color];[color=#CC6600]break[/color];
  2347.           [color=#CC6600]case[/color] 1: autoretract_enabled=[color=#CC6600]true[/color];retracted=[color=#CC6600]false[/color];[color=#CC6600]break[/color];
  2348.           [color=#CC6600]default[/color]:
  2349.             SERIAL_ECHO_START;
  2350.             SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
  2351.             SERIAL_ECHO(cmdbuffer[bufindr]);
  2352.             SERIAL_ECHOLNPGM([color=#006699]"\""[/color]);
  2353.         }
  2354.       }
  2355.  
  2356.     }[color=#CC6600]break[/color];
  2357.     #endif [color=#7E7E7E]// FWRETRACT[/color]
  2358.     #if EXTRUDERS > 1
  2359.     [color=#CC6600]case[/color] 218: [color=#7E7E7E]// M218 - set hotend offset (in mm), T<extruder_number> X<offset_on_X> Y<offset_on_Y>[/color]
  2360.     {
  2361.       [color=#CC6600]if[/color](setTargetedHotend(218)){
  2362.         [color=#CC6600]break[/color];
  2363.       }
  2364.       [color=#CC6600]if[/color](code_seen([color=#006699]'X'[/color]))
  2365.       {
  2366.         extruder_offset[[color=#006699]X_AXIS[/color]][tmp_extruder] = code_value();
  2367.       }
  2368.       [color=#CC6600]if[/color](code_seen([color=#006699]'Y'[/color]))
  2369.       {
  2370.         extruder_offset[[color=#006699]Y_AXIS[/color]][tmp_extruder] = code_value();
  2371.       }
  2372.       #ifdef DUAL_X_CARRIAGE
  2373.       [color=#CC6600]if[/color](code_seen([color=#006699]'Z'[/color]))
  2374.       {
  2375.         extruder_offset[[color=#006699]Z_AXIS[/color]][tmp_extruder] = code_value();
  2376.       }
  2377.       #endif
  2378.       SERIAL_ECHO_START;
  2379.       SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
  2380.       [color=#CC6600]for[/color](tmp_extruder = 0; tmp_extruder < EXTRUDERS; tmp_extruder++)
  2381.       {
  2382.          SERIAL_ECHO([color=#006699]" "[/color]);
  2383.          SERIAL_ECHO(extruder_offset[[color=#006699]X_AXIS[/color]][tmp_extruder]);
  2384.          SERIAL_ECHO([color=#006699]","[/color]);
  2385.          SERIAL_ECHO(extruder_offset[[color=#006699]Y_AXIS[/color]][tmp_extruder]);
  2386.       #ifdef DUAL_X_CARRIAGE
  2387.          SERIAL_ECHO([color=#006699]","[/color]);
  2388.          SERIAL_ECHO(extruder_offset[[color=#006699]Z_AXIS[/color]][tmp_extruder]);
  2389.       #endif
  2390.       }
  2391.       SERIAL_ECHOLN([color=#006699]""[/color]);
  2392.     }[color=#CC6600]break[/color];
  2393.     #endif
  2394.     [color=#CC6600]case[/color] 220: [color=#7E7E7E]// M220 S<factor in percent>- set speed factor override percentage[/color]
  2395.     {
  2396.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color]))
  2397.       {
  2398.         feedmultiply = code_value() ;
  2399.       }
  2400.     }
  2401.     [color=#CC6600]break[/color];
  2402.     [color=#CC6600]case[/color] 221: [color=#7E7E7E]// M221 S<factor in percent>- set extrude factor override percentage[/color]
  2403.     {
  2404.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color]))
  2405.       {
  2406.         extrudemultiply = code_value() ;
  2407.       }
  2408.     }
  2409.     [color=#CC6600]break[/color];
  2410.  
  2411. [color=#CC6600]case[/color] 226: [color=#7E7E7E]// M226 P<pin number> S<pin state>- Wait until the specified pin reaches the state required[/color]
  2412. {
  2413.       [color=#CC6600]if[/color](code_seen([color=#006699]'P'[/color])){
  2414.         [color=#CC6600]int[/color] pin_number = code_value(); [color=#7E7E7E]// pin number[/color]
  2415.         [color=#CC6600]int[/color] pin_state = -1; [color=#7E7E7E]// required pin state - default is inverted[/color]
  2416.  
  2417.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) pin_state = code_value(); [color=#7E7E7E]// required pin state[/color]
  2418.  
  2419.         [color=#CC6600]if[/color](pin_state >= -1 && pin_state <= 1){
  2420.  
  2421.           [color=#CC6600]for[/color](int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++)
  2422.           {
  2423.             [color=#CC6600]if[/color] (sensitive_pins[i] == pin_number)
  2424.             {
  2425.               pin_number = -1;
  2426.               [color=#CC6600]break[/color];
  2427.             }
  2428.           }
  2429.  
  2430.           [color=#CC6600]if[/color] (pin_number > -1)
  2431.           {
  2432.             st_synchronize();
  2433.  
  2434.             [color=#CC6600]pinMode[/color](pin_number, [color=#006699]INPUT[/color]);
  2435.  
  2436.             [color=#CC6600]int[/color] target;
  2437.             [color=#CC6600]switch[/color](pin_state){
  2438.             [color=#CC6600]case[/color] 1:
  2439.               target = [color=#006699]HIGH[/color];
  2440.               [color=#CC6600]break[/color];
  2441.  
  2442.             [color=#CC6600]case[/color] 0:
  2443.               target = [color=#006699]LOW[/color];
  2444.               [color=#CC6600]break[/color];
  2445.  
  2446.             [color=#CC6600]case[/color] -1:
  2447.               target = ![color=#CC6600]digitalRead[/color](pin_number);
  2448.               [color=#CC6600]break[/color];
  2449.             }
  2450.  
  2451.             [color=#CC6600]while[/color]([color=#CC6600]digitalRead[/color](pin_number) != target){
  2452.               manage_heater();
  2453.               manage_inactivity();
  2454.               lcd_update();
  2455.             }
  2456.           }
  2457.         }
  2458.       }
  2459.     }
  2460.     [color=#CC6600]break[/color];
  2461.  
  2462.     #if NUM_SERVOS > 0
  2463.     [color=#CC6600]case[/color] 280: [color=#7E7E7E]// M280 - set servo position absolute. P: servo index, S: angle or microseconds[/color]
  2464.       {
  2465.         [color=#CC6600]int[/color] servo_index = -1;
  2466.         [color=#CC6600]int[/color] servo_position = 0;
  2467.         [color=#CC6600]if[/color] (code_seen([color=#006699]'P'[/color]))
  2468.           servo_index = code_value();
  2469.         [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) {
  2470.           servo_position = code_value();
  2471.           [color=#CC6600]if[/color] ((servo_index >= 0) && (servo_index < NUM_SERVOS)) {
  2472. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  2473.       servos[servo_index].[color=#CC6600]attach[/color](0);
  2474. #endif
  2475.             servos[servo_index].[color=#CC6600]write[/color](servo_position);
  2476. #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
  2477.               [color=#CC6600]delay[/color](PROBE_SERVO_DEACTIVATION_DELAY);
  2478.               servos[servo_index].[color=#CC6600]detach[/color]();
  2479. #endif
  2480.           }
  2481.           [color=#CC6600]else[/color] {
  2482.             SERIAL_ECHO_START;
  2483.             SERIAL_ECHO([color=#006699]"Servo "[/color]);
  2484.             SERIAL_ECHO(servo_index);
  2485.             SERIAL_ECHOLN([color=#006699]" out of range"[/color]);
  2486.           }
  2487.         }
  2488.         [color=#CC6600]else[/color] [color=#CC6600]if[/color] (servo_index >= 0) {
  2489.           SERIAL_PROTOCOL(MSG_OK);
  2490.           SERIAL_PROTOCOL([color=#006699]" Servo "[/color]);
  2491.           SERIAL_PROTOCOL(servo_index);
  2492.           SERIAL_PROTOCOL([color=#006699]": "[/color]);
  2493.           SERIAL_PROTOCOL(servos[servo_index].[color=#CC6600]read[/color]());
  2494.           SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  2495.         }
  2496.       }
  2497.       [color=#CC6600]break[/color];
  2498.     #endif [color=#7E7E7E]// NUM_SERVOS > 0[/color]
  2499.  
  2500.     #if (LARGE_FLASH == [color=#CC6600]true[/color] && ( BEEPER > 0 || defined(ULTRALCD) || defined(LCD_USE_I2C_BUZZER)))
  2501.     [color=#CC6600]case[/color] 300: [color=#7E7E7E]// M300[/color]
  2502.     {
  2503.       [color=#CC6600]int[/color] beepS = code_seen([color=#006699]'S'[/color]) ? code_value() : 110;
  2504.       [color=#CC6600]int[/color] beepP = code_seen([color=#006699]'P'[/color]) ? code_value() : 1000;
  2505.       [color=#CC6600]if[/color] (beepS > 0)
  2506.       {
  2507.         #if BEEPER > 0
  2508.           [color=#CC6600]tone[/color](BEEPER, beepS);
  2509.           [color=#CC6600]delay[/color](beepP);
  2510.           [color=#CC6600]noTone[/color](BEEPER);
  2511.         #elif defined(ULTRALCD)
  2512.   lcd_buzz(beepS, beepP);
  2513. #elif defined(LCD_USE_I2C_BUZZER)
  2514.   lcd_buzz(beepP, beepS);
  2515.         #endif
  2516.       }
  2517.       [color=#CC6600]else[/color]
  2518.       {
  2519.         [color=#CC6600]delay[/color](beepP);
  2520.       }
  2521.     }
  2522.     [color=#CC6600]break[/color];
  2523.     #endif [color=#7E7E7E]// M300[/color]
  2524.  
  2525.     #ifdef PIDTEMP
  2526.     [color=#CC6600]case[/color] 301: [color=#7E7E7E]// M301[/color]
  2527.       {
  2528.         [color=#CC6600]if[/color](code_seen([color=#006699]'P'[/color])) Kp = code_value();
  2529.         [color=#CC6600]if[/color](code_seen([color=#006699]'I'[/color])) Ki = scalePID_i(code_value());
  2530.         [color=#CC6600]if[/color](code_seen([color=#006699]'D'[/color])) Kd = scalePID_d(code_value());
  2531.  
  2532.         #ifdef PID_ADD_EXTRUSION_RATE
  2533.         [color=#CC6600]if[/color](code_seen([color=#006699]'C'[/color])) Kc = code_value();
  2534.         #endif
  2535.  
  2536.         updatePID();
  2537.         SERIAL_PROTOCOL(MSG_OK);
  2538.         SERIAL_PROTOCOL([color=#006699]" p:"[/color]);
  2539.         SERIAL_PROTOCOL(Kp);
  2540.         SERIAL_PROTOCOL([color=#006699]" i:"[/color]);
  2541.         SERIAL_PROTOCOL(unscalePID_i(Ki));
  2542.         SERIAL_PROTOCOL([color=#006699]" d:"[/color]);
  2543.         SERIAL_PROTOCOL(unscalePID_d(Kd));
  2544.         #ifdef PID_ADD_EXTRUSION_RATE
  2545.         SERIAL_PROTOCOL([color=#006699]" c:"[/color]);
  2546.         [color=#7E7E7E]//Kc does not have scaling applied above, or in resetting defaults[/color]
  2547.         SERIAL_PROTOCOL(Kc);
  2548.         #endif
  2549.         SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  2550.       }
  2551.       [color=#CC6600]break[/color];
  2552.     #endif [color=#7E7E7E]//PIDTEMP[/color]
  2553.     #ifdef PIDTEMPBED
  2554.     [color=#CC6600]case[/color] 304: [color=#7E7E7E]// M304[/color]
  2555.       {
  2556.         [color=#CC6600]if[/color](code_seen([color=#006699]'P'[/color])) bedKp = code_value();
  2557.         [color=#CC6600]if[/color](code_seen([color=#006699]'I'[/color])) bedKi = scalePID_i(code_value());
  2558.         [color=#CC6600]if[/color](code_seen([color=#006699]'D'[/color])) bedKd = scalePID_d(code_value());
  2559.  
  2560.         updatePID();
  2561.         SERIAL_PROTOCOL(MSG_OK);
  2562.         SERIAL_PROTOCOL([color=#006699]" p:"[/color]);
  2563.         SERIAL_PROTOCOL(bedKp);
  2564.         SERIAL_PROTOCOL([color=#006699]" i:"[/color]);
  2565.         SERIAL_PROTOCOL(unscalePID_i(bedKi));
  2566.         SERIAL_PROTOCOL([color=#006699]" d:"[/color]);
  2567.         SERIAL_PROTOCOL(unscalePID_d(bedKd));
  2568.         SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  2569.       }
  2570.       [color=#CC6600]break[/color];
  2571.     #endif [color=#7E7E7E]//PIDTEMP[/color]
  2572.     [color=#CC6600]case[/color] 240: [color=#7E7E7E]// M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/[/color]
  2573.      {
  2574.       #if defined(PHOTOGRAPH_PIN) && PHOTOGRAPH_PIN > -1
  2575.         [color=#CC6600]const[/color] uint8_t NUM_PULSES=16;
  2576.         [color=#CC6600]const[/color] [color=#CC6600]float[/color] PULSE_LENGTH=0.01524;
  2577.         [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0; i < NUM_PULSES; i++) {
  2578.           WRITE(PHOTOGRAPH_PIN, [color=#006699]HIGH[/color]);
  2579.           _delay_ms(PULSE_LENGTH);
  2580.           WRITE(PHOTOGRAPH_PIN, [color=#006699]LOW[/color]);
  2581.           _delay_ms(PULSE_LENGTH);
  2582.         }
  2583.         [color=#CC6600]delay[/color](7.33);
  2584.         [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0; i < NUM_PULSES; i++) {
  2585.           WRITE(PHOTOGRAPH_PIN, [color=#006699]HIGH[/color]);
  2586.           _delay_ms(PULSE_LENGTH);
  2587.           WRITE(PHOTOGRAPH_PIN, [color=#006699]LOW[/color]);
  2588.           _delay_ms(PULSE_LENGTH);
  2589.         }
  2590.       #endif
  2591.      }
  2592.     [color=#CC6600]break[/color];
  2593. #ifdef DOGLCD
  2594.     [color=#CC6600]case[/color] 250: [color=#7E7E7E]// M250 Set LCD contrast value: C<value> (value 0..63)[/color]
  2595.      {
  2596.   [color=#CC6600]if[/color] (code_seen([color=#006699]'C'[/color])) {
  2597.    lcd_setcontrast( (([color=#CC6600]int[/color])code_value())&63 );
  2598.           }
  2599.           SERIAL_PROTOCOLPGM([color=#006699]"lcd contrast value: "[/color]);
  2600.           SERIAL_PROTOCOL(lcd_contrast);
  2601.           SERIAL_PROTOCOLLN([color=#006699]""[/color]);
  2602.      }
  2603.     [color=#CC6600]break[/color];
  2604. #endif
  2605.     #ifdef PREVENT_DANGEROUS_EXTRUDE
  2606.     [color=#CC6600]case[/color] 302: [color=#7E7E7E]// allow cold extrudes, or set the minimum extrude temperature[/color]
  2607.     {
  2608.   [color=#CC6600]float[/color] temp = .0;
  2609.   [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) temp=code_value();
  2610.       set_extrude_min_temp(temp);
  2611.     }
  2612.     [color=#CC6600]break[/color];
  2613. #endif
  2614.     [color=#CC6600]case[/color] 303: [color=#7E7E7E]// M303 PID autotune[/color]
  2615.     {
  2616.       [color=#CC6600]float[/color] temp = 150.0;
  2617.       [color=#CC6600]int[/color] e=0;
  2618.       [color=#CC6600]int[/color] c=5;
  2619.       [color=#CC6600]if[/color] (code_seen([color=#006699]'E'[/color])) e=code_value();
  2620.         [color=#CC6600]if[/color] (e<0)
  2621.           temp=70;
  2622.       [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color])) temp=code_value();
  2623.       [color=#CC6600]if[/color] (code_seen([color=#006699]'C'[/color])) c=code_value();
  2624.       PID_autotune(temp, e, c);
  2625.     }
  2626.     [color=#CC6600]break[/color];
  2627.     [color=#CC6600]case[/color] 400: [color=#7E7E7E]// M400 finish all moves[/color]
  2628.     {
  2629.       st_synchronize();
  2630.     }
  2631.     [color=#CC6600]break[/color];
  2632. #if defined(ENABLE_AUTO_BED_LEVELING) && defined(SERVO_ENDSTOPS)
  2633.     [color=#CC6600]case[/color] 401:
  2634.     {
  2635.         engage_z_probe();    [color=#7E7E7E]// Engage Z Servo endstop if available[/color]
  2636.     }
  2637.     [color=#CC6600]break[/color];
  2638.  
  2639.     [color=#CC6600]case[/color] 402:
  2640.     {
  2641.         retract_z_probe();    [color=#7E7E7E]// Retract Z Servo endstop if enabled[/color]
  2642.     }
  2643.     [color=#CC6600]break[/color];
  2644. #endif
  2645.     [color=#CC6600]case[/color] 500: [color=#7E7E7E]// M500 Store settings in EEPROM[/color]
  2646.     {
  2647.         Config_StoreSettings();
  2648.     }
  2649.     [color=#CC6600]break[/color];
  2650.     [color=#CC6600]case[/color] 501: [color=#7E7E7E]// M501 Read settings from EEPROM[/color]
  2651.     {
  2652.         Config_RetrieveSettings();
  2653.     }
  2654.     [color=#CC6600]break[/color];
  2655.     [color=#CC6600]case[/color] 502: [color=#7E7E7E]// M502 Revert to default settings[/color]
  2656.     {
  2657.         Config_ResetDefault();
  2658.     }
  2659.     [color=#CC6600]break[/color];
  2660.     [color=#CC6600]case[/color] 503: [color=#7E7E7E]// M503 print settings currently in memory[/color]
  2661.     {
  2662.         Config_PrintSettings();
  2663.     }
  2664.     [color=#CC6600]break[/color];
  2665.     #ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
  2666.     [color=#CC6600]case[/color] 540:
  2667.     {
  2668.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) abort_on_endstop_hit = code_value() > 0;
  2669.     }
  2670.     [color=#CC6600]break[/color];
  2671.     #endif
  2672.     #ifdef FILAMENTCHANGEENABLE
  2673.     [color=#CC6600]case[/color] 600: [color=#7E7E7E]//Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal][/color]
  2674.     {
  2675.         [color=#CC6600]float[/color] target[4];
  2676.         [color=#CC6600]float[/color] lastpos[4];
  2677.         target[[color=#006699]X_AXIS[/color]]=current_position[[color=#006699]X_AXIS[/color]];
  2678.         target[[color=#006699]Y_AXIS[/color]]=current_position[[color=#006699]Y_AXIS[/color]];
  2679.         target[[color=#006699]Z_AXIS[/color]]=current_position[[color=#006699]Z_AXIS[/color]];
  2680.         target[E_AXIS]=current_position[E_AXIS];
  2681.         lastpos[[color=#006699]X_AXIS[/color]]=current_position[[color=#006699]X_AXIS[/color]];
  2682.         lastpos[[color=#006699]Y_AXIS[/color]]=current_position[[color=#006699]Y_AXIS[/color]];
  2683.         lastpos[[color=#006699]Z_AXIS[/color]]=current_position[[color=#006699]Z_AXIS[/color]];
  2684.         lastpos[E_AXIS]=current_position[E_AXIS];
  2685.         [color=#7E7E7E]//retract by E[/color]
  2686.         [color=#CC6600]if[/color](code_seen([color=#006699]'E'[/color]))
  2687.         {
  2688.           target[E_AXIS]+= code_value();
  2689.         }
  2690.         [color=#CC6600]else[/color]
  2691.         {
  2692.           #ifdef FILAMENTCHANGE_FIRSTRETRACT
  2693.             target[E_AXIS]+= FILAMENTCHANGE_FIRSTRETRACT ;
  2694.           #endif
  2695.         }
  2696.         plan_buffer_line(target[[color=#006699]X_AXIS[/color]], target[[color=#006699]Y_AXIS[/color]], target[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder);
  2697.  
  2698.         [color=#7E7E7E]//lift Z[/color]
  2699.         [color=#CC6600]if[/color](code_seen([color=#006699]'Z'[/color]))
  2700.         {
  2701.           target[[color=#006699]Z_AXIS[/color]]+= code_value();
  2702.         }
  2703.         [color=#CC6600]else[/color]
  2704.         {
  2705.           #ifdef FILAMENTCHANGE_ZADD
  2706.             target[[color=#006699]Z_AXIS[/color]]+= FILAMENTCHANGE_ZADD ;
  2707.           #endif
  2708.         }
  2709.         plan_buffer_line(target[[color=#006699]X_AXIS[/color]], target[[color=#006699]Y_AXIS[/color]], target[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder);
  2710.  
  2711.         [color=#7E7E7E]//move xy[/color]
  2712.         [color=#CC6600]if[/color](code_seen([color=#006699]'X'[/color]))
  2713.         {
  2714.           target[[color=#006699]X_AXIS[/color]]+= code_value();
  2715.         }
  2716.         [color=#CC6600]else[/color]
  2717.         {
  2718.           #ifdef FILAMENTCHANGE_XPOS
  2719.             target[[color=#006699]X_AXIS[/color]]= FILAMENTCHANGE_XPOS ;
  2720.           #endif
  2721.         }
  2722.         [color=#CC6600]if[/color](code_seen([color=#006699]'Y'[/color]))
  2723.         {
  2724.           target[[color=#006699]Y_AXIS[/color]]= code_value();
  2725.         }
  2726.         [color=#CC6600]else[/color]
  2727.         {
  2728.           #ifdef FILAMENTCHANGE_YPOS
  2729.             target[[color=#006699]Y_AXIS[/color]]= FILAMENTCHANGE_YPOS ;
  2730.           #endif
  2731.         }
  2732.  
  2733.         plan_buffer_line(target[[color=#006699]X_AXIS[/color]], target[[color=#006699]Y_AXIS[/color]], target[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder);
  2734.  
  2735.         [color=#CC6600]if[/color](code_seen([color=#006699]'L'[/color]))
  2736.         {
  2737.           target[E_AXIS]+= code_value();
  2738.         }
  2739.         [color=#CC6600]else[/color]
  2740.         {
  2741.           #ifdef FILAMENTCHANGE_FINALRETRACT
  2742.             target[E_AXIS]+= FILAMENTCHANGE_FINALRETRACT ;
  2743.           #endif
  2744.         }
  2745.  
  2746.         plan_buffer_line(target[[color=#006699]X_AXIS[/color]], target[[color=#006699]Y_AXIS[/color]], target[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder);
  2747.  
  2748.         [color=#7E7E7E]//finish moves[/color]
  2749.         st_synchronize();
  2750.         [color=#7E7E7E]//disable extruder steppers so filament can be removed[/color]
  2751.         disable_e0();
  2752.         disable_e1();
  2753.         disable_e2();
  2754.         [color=#CC6600]delay[/color](100);
  2755.         LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE);
  2756.         uint8_t cnt=0;
  2757.         [color=#CC6600]while[/color](!lcd_clicked()){
  2758.           cnt++;
  2759.           manage_heater();
  2760.           manage_inactivity();
  2761.           lcd_update();
  2762.           [color=#CC6600]if[/color](cnt==0)
  2763.           {
  2764.           #if BEEPER > 0
  2765.             SET_OUTPUT(BEEPER);
  2766.  
  2767.             WRITE(BEEPER,[color=#006699]HIGH[/color]);
  2768.             [color=#CC6600]delay[/color](3);
  2769.             WRITE(BEEPER,[color=#006699]LOW[/color]);
  2770.             [color=#CC6600]delay[/color](3);
  2771.           #else
  2772. #if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
  2773.               lcd_buzz(1000/6,100);
  2774. #else
  2775.   lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS,LCD_FEEDBACK_FREQUENCY_HZ);
  2776. #endif
  2777.           #endif
  2778.           }
  2779.         }
  2780.  
  2781.         [color=#7E7E7E]//return to normal[/color]
  2782.         [color=#CC6600]if[/color](code_seen([color=#006699]'L'[/color]))
  2783.         {
  2784.           target[E_AXIS]+= -code_value();
  2785.         }
  2786.         [color=#CC6600]else[/color]
  2787.         {
  2788.           #ifdef FILAMENTCHANGE_FINALRETRACT
  2789.             target[E_AXIS]+=(-1)*FILAMENTCHANGE_FINALRETRACT ;
  2790.           #endif
  2791.         }
  2792.         current_position[E_AXIS]=target[E_AXIS]; [color=#7E7E7E]//the long retract of L is compensated by manual filament feeding[/color]
  2793.         plan_set_e_position(current_position[E_AXIS]);
  2794.         plan_buffer_line(target[[color=#006699]X_AXIS[/color]], target[[color=#006699]Y_AXIS[/color]], target[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder); [color=#7E7E7E]//should do nothing[/color]
  2795.         plan_buffer_line(lastpos[[color=#006699]X_AXIS[/color]], lastpos[[color=#006699]Y_AXIS[/color]], target[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder); [color=#7E7E7E]//move xy back[/color]
  2796.         plan_buffer_line(lastpos[[color=#006699]X_AXIS[/color]], lastpos[[color=#006699]Y_AXIS[/color]], lastpos[[color=#006699]Z_AXIS[/color]], target[E_AXIS], feedrate/60, active_extruder); [color=#7E7E7E]//move z back[/color]
  2797.         plan_buffer_line(lastpos[[color=#006699]X_AXIS[/color]], lastpos[[color=#006699]Y_AXIS[/color]], lastpos[[color=#006699]Z_AXIS[/color]], lastpos[E_AXIS], feedrate/60, active_extruder); [color=#7E7E7E]//final untretract[/color]
  2798.     }
  2799.     [color=#CC6600]break[/color];
  2800.     #endif [color=#7E7E7E]//FILAMENTCHANGEENABLE[/color]
  2801.     #ifdef DUAL_X_CARRIAGE
  2802.     [color=#CC6600]case[/color] 605: [color=#7E7E7E]// Set dual x-carriage movement mode:[/color]
  2803.               [color=#7E7E7E]// M605 S0: Full control mode. The slicer has full control over x-carriage movement[/color]
  2804.               [color=#7E7E7E]// M605 S1: Auto-park mode. The inactive head will auto park/unpark without slicer involvement[/color]
  2805.               [color=#7E7E7E]// M605 S2 [Xnnn] [Rmmm]: Duplication mode. The second extruder will duplicate the first with nnn[/color]
  2806.               [color=#7E7E7E]// millimeters x-offset and an optional differential hotend temperature of[/color]
  2807.               [color=#7E7E7E]// mmm degrees. E.g., with "M605 S2 X100 R2" the second extruder will duplicate[/color]
  2808.               [color=#7E7E7E]// the first with a spacing of 100mm in the x direction and 2 degrees hotter.[/color]
  2809.               [color=#7E7E7E]//[/color]
  2810.               [color=#7E7E7E]// Note: the X axis should be homed after changing dual x-carriage mode.[/color]
  2811.     {
  2812.         st_synchronize();
  2813.  
  2814.         [color=#CC6600]if[/color] (code_seen([color=#006699]'S'[/color]))
  2815.           dual_x_carriage_mode = code_value();
  2816.  
  2817.         [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
  2818.         {
  2819.           [color=#CC6600]if[/color] (code_seen([color=#006699]'X'[/color]))
  2820.             duplicate_extruder_x_offset = [color=#CC6600]max[/color](code_value(),X2_MIN_POS - x_home_pos(0));
  2821.  
  2822.           [color=#CC6600]if[/color] (code_seen([color=#006699]'R'[/color]))
  2823.             duplicate_extruder_temp_offset = code_value();
  2824.  
  2825.           SERIAL_ECHO_START;
  2826.           SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
  2827.           SERIAL_ECHO([color=#006699]" "[/color]);
  2828.           SERIAL_ECHO(extruder_offset[[color=#006699]X_AXIS[/color]][0]);
  2829.           SERIAL_ECHO([color=#006699]","[/color]);
  2830.           SERIAL_ECHO(extruder_offset[[color=#006699]Y_AXIS[/color]][0]);
  2831.           SERIAL_ECHO([color=#006699]" "[/color]);
  2832.           SERIAL_ECHO(duplicate_extruder_x_offset);
  2833.           SERIAL_ECHO([color=#006699]","[/color]);
  2834.           SERIAL_ECHOLN(extruder_offset[[color=#006699]Y_AXIS[/color]][1]);
  2835.         }
  2836.         [color=#CC6600]else[/color] [color=#CC6600]if[/color] (dual_x_carriage_mode != DXC_FULL_CONTROL_MODE && dual_x_carriage_mode != DXC_AUTO_PARK_MODE)
  2837.         {
  2838.           dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
  2839.         }
  2840.  
  2841.         active_extruder_parked = [color=#CC6600]false[/color];
  2842.         extruder_duplication_enabled = [color=#CC6600]false[/color];
  2843.         delayed_move_time = 0;
  2844.     }
  2845.     [color=#CC6600]break[/color];
  2846.     #endif [color=#7E7E7E]//DUAL_X_CARRIAGE[/color]
  2847.  
  2848.     [color=#CC6600]case[/color] 907: [color=#7E7E7E]// M907 Set digital trimpot motor current using axis codes.[/color]
  2849.     {
  2850.       #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
  2851.         [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<NUM_AXIS;i++) [color=#CC6600]if[/color](code_seen(axis_codes[i])) digipot_current(i,code_value());
  2852.         [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color])) digipot_current(4,code_value());
  2853.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<=4;i++) digipot_current(i,code_value());
  2854.       #endif
  2855.       #ifdef MOTOR_CURRENT_PWM_XY_PIN
  2856.         [color=#CC6600]if[/color](code_seen([color=#006699]'X'[/color])) digipot_current(0, code_value());
  2857.       #endif
  2858.       #ifdef MOTOR_CURRENT_PWM_Z_PIN
  2859.         [color=#CC6600]if[/color](code_seen([color=#006699]'Z'[/color])) digipot_current(1, code_value());
  2860.       #endif
  2861.       #ifdef MOTOR_CURRENT_PWM_E_PIN
  2862.         [color=#CC6600]if[/color](code_seen([color=#006699]'E'[/color])) digipot_current(2, code_value());
  2863.       #endif
  2864.       #ifdef DIGIPOT_I2C
  2865.         [color=#7E7E7E]// this one uses actual amps in floating point[/color]
  2866.         [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<NUM_AXIS;i++) [color=#CC6600]if[/color](code_seen(axis_codes[i])) digipot_i2c_set_current(i, code_value());
  2867.         [color=#7E7E7E]// for each additional extruder (named B,C,D,E..., channels 4,5,6,7...)[/color]
  2868.         [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=NUM_AXIS;i<DIGIPOT_I2C_NUM_CHANNELS;i++) [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color]+i-NUM_AXIS)) digipot_i2c_set_current(i, code_value());
  2869.       #endif
  2870.     }
  2871.     [color=#CC6600]break[/color];
  2872.     [color=#CC6600]case[/color] 908: [color=#7E7E7E]// M908 Control digital trimpot directly.[/color]
  2873.     {
  2874.       #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
  2875.         uint8_t channel,current;
  2876.         [color=#CC6600]if[/color](code_seen([color=#006699]'P'[/color])) channel=code_value();
  2877.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) current=code_value();
  2878.         digitalPotWrite(channel, current);
  2879.       #endif
  2880.     }
  2881.     [color=#CC6600]break[/color];
  2882.     [color=#CC6600]case[/color] 350: [color=#7E7E7E]// M350 Set microstepping mode. Warning: Steps per unit remains unchanged. S code sets stepping mode for all drivers.[/color]
  2883.     {
  2884.       #if defined(X_MS1_PIN) && X_MS1_PIN > -1
  2885.         [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<=4;i++) microstep_mode(i,code_value());
  2886.         [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<NUM_AXIS;i++) [color=#CC6600]if[/color](code_seen(axis_codes[i])) microstep_mode(i,(uint8_t)code_value());
  2887.         [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color])) microstep_mode(4,code_value());
  2888.         microstep_readings();
  2889.       #endif
  2890.     }
  2891.     [color=#CC6600]break[/color];
  2892.     [color=#CC6600]case[/color] 351: [color=#7E7E7E]// M351 Toggle MS1 MS2 pins directly, S# determines MS1 or MS2, X# sets the pin high/low.[/color]
  2893.     {
  2894.       #if defined(X_MS1_PIN) && X_MS1_PIN > -1
  2895.       [color=#CC6600]if[/color](code_seen([color=#006699]'S'[/color])) [color=#CC6600]switch[/color](([color=#CC6600]int[/color])code_value())
  2896.       {
  2897.         [color=#CC6600]case[/color] 1:
  2898.           [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<NUM_AXIS;i++) [color=#CC6600]if[/color](code_seen(axis_codes[i])) microstep_ms(i,code_value(),-1);
  2899.           [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color])) microstep_ms(4,code_value(),-1);
  2900.           [color=#CC6600]break[/color];
  2901.         [color=#CC6600]case[/color] 2:
  2902.           [color=#CC6600]for[/color]([color=#CC6600]int[/color] i=0;i<NUM_AXIS;i++) [color=#CC6600]if[/color](code_seen(axis_codes[i])) microstep_ms(i,-1,code_value());
  2903.           [color=#CC6600]if[/color](code_seen([color=#006699]'B'[/color])) microstep_ms(4,-1,code_value());
  2904.           [color=#CC6600]break[/color];
  2905.       }
  2906.       microstep_readings();
  2907.       #endif
  2908.     }
  2909.     [color=#CC6600]break[/color];
  2910.     [color=#CC6600]case[/color] 999: [color=#7E7E7E]// M999: Restart after being stopped[/color]
  2911.       Stopped = [color=#CC6600]false[/color];
  2912.       lcd_reset_alert_level();
  2913.       gcode_LastN = Stopped_gcode_LastN;
  2914.       FlushSerialRequestResend();
  2915.     [color=#CC6600]break[/color];
  2916.     }
  2917.   }
  2918.  
  2919.   [color=#CC6600]else[/color] [color=#CC6600]if[/color](code_seen([color=#006699]'T'[/color]))
  2920.   {
  2921.     tmp_extruder = code_value();
  2922.     [color=#CC6600]if[/color](tmp_extruder >= EXTRUDERS) {
  2923.       SERIAL_ECHO_START;
  2924.       SERIAL_ECHO([color=#006699]"T"[/color]);
  2925.       SERIAL_ECHO(tmp_extruder);
  2926.       SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
  2927.     }
  2928.     [color=#CC6600]else[/color] {
  2929.       [color=#CC6600]boolean[/color] make_move = [color=#CC6600]false[/color];
  2930.       [color=#CC6600]if[/color](code_seen([color=#006699]'F'[/color])) {
  2931.         make_move = [color=#CC6600]true[/color];
  2932.         next_feedrate = code_value();
  2933.         [color=#CC6600]if[/color](next_feedrate > 0.0) {
  2934.           feedrate = next_feedrate;
  2935.         }
  2936.       }
  2937.       #if EXTRUDERS > 1
  2938.       [color=#CC6600]if[/color](tmp_extruder != active_extruder) {
  2939.         [color=#7E7E7E]// Save current position to return to after applying extruder offset[/color]
  2940.         memcpy(destination, current_position, sizeof(destination));
  2941.       #ifdef DUAL_X_CARRIAGE
  2942.         [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && Stopped == [color=#CC6600]false[/color] &&
  2943.             (delayed_move_time != 0 || current_position[[color=#006699]X_AXIS[/color]] != x_home_pos(active_extruder)))
  2944.         {
  2945.           [color=#7E7E7E]// Park old head: 1) raise 2) move to park position 3) lower[/color]
  2946.           plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + TOOLCHANGE_PARK_ZLIFT,
  2947.                 current_position[E_AXIS], max_feedrate[[color=#006699]Z_AXIS[/color]], active_extruder);
  2948.           plan_buffer_line(x_home_pos(active_extruder), current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]] + TOOLCHANGE_PARK_ZLIFT,
  2949.                 current_position[E_AXIS], max_feedrate[[color=#006699]X_AXIS[/color]], active_extruder);
  2950.           plan_buffer_line(x_home_pos(active_extruder), current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]],
  2951.                 current_position[E_AXIS], max_feedrate[[color=#006699]Z_AXIS[/color]], active_extruder);
  2952.           st_synchronize();
  2953.         }
  2954.  
  2955.         [color=#7E7E7E]// apply Y & Z extruder offset (x offset is already used in determining home pos)[/color]
  2956.         current_position[[color=#006699]Y_AXIS[/color]] = current_position[[color=#006699]Y_AXIS[/color]] -
  2957.                      extruder_offset[[color=#006699]Y_AXIS[/color]][active_extruder] +
  2958.                      extruder_offset[[color=#006699]Y_AXIS[/color]][tmp_extruder];
  2959.         current_position[[color=#006699]Z_AXIS[/color]] = current_position[[color=#006699]Z_AXIS[/color]] -
  2960.                      extruder_offset[[color=#006699]Z_AXIS[/color]][active_extruder] +
  2961.                      extruder_offset[[color=#006699]Z_AXIS[/color]][tmp_extruder];
  2962.  
  2963.         active_extruder = tmp_extruder;
  2964.  
  2965.         [color=#7E7E7E]// This function resets the max/min values - the current position may be overwritten below.[/color]
  2966.         axis_is_at_home([color=#006699]X_AXIS[/color]);
  2967.  
  2968.         [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_FULL_CONTROL_MODE)
  2969.         {
  2970.           current_position[[color=#006699]X_AXIS[/color]] = inactive_extruder_x_pos;
  2971.           inactive_extruder_x_pos = destination[[color=#006699]X_AXIS[/color]];
  2972.         }
  2973.         [color=#CC6600]else[/color] [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
  2974.         {
  2975.           active_extruder_parked = (active_extruder == 0); [color=#7E7E7E]// this triggers the second extruder to move into the duplication position[/color]
  2976.           [color=#CC6600]if[/color] (active_extruder == 0 || active_extruder_parked)
  2977.             current_position[[color=#006699]X_AXIS[/color]] = inactive_extruder_x_pos;
  2978.           [color=#CC6600]else[/color]
  2979.             current_position[[color=#006699]X_AXIS[/color]] = destination[[color=#006699]X_AXIS[/color]] + duplicate_extruder_x_offset;
  2980.           inactive_extruder_x_pos = destination[[color=#006699]X_AXIS[/color]];
  2981.           extruder_duplication_enabled = [color=#CC6600]false[/color];
  2982.         }
  2983.         [color=#CC6600]else[/color]
  2984.         {
  2985.           [color=#7E7E7E]// record raised toolhead position for use by unpark[/color]
  2986.           memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
  2987.           raised_parked_position[[color=#006699]Z_AXIS[/color]] += TOOLCHANGE_UNPARK_ZLIFT;
  2988.           active_extruder_parked = [color=#CC6600]true[/color];
  2989.           delayed_move_time = 0;
  2990.         }
  2991.       #else
  2992.         [color=#7E7E7E]// Offset extruder (only by XY)[/color]
  2993.         [color=#CC6600]int[/color] i;
  2994.         [color=#CC6600]for[/color](i = 0; i < 2; i++) {
  2995.            current_position[i] = current_position[i] -
  2996.                                  extruder_offset[i][active_extruder] +
  2997.                                  extruder_offset[i][tmp_extruder];
  2998.         }
  2999.         [color=#7E7E7E]// Set the new active extruder and position[/color]
  3000.         active_extruder = tmp_extruder;
  3001.       #endif [color=#7E7E7E]//else DUAL_X_CARRIAGE[/color]
  3002.         plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  3003.         [color=#7E7E7E]// Move to the old position if 'F' was in the parameters[/color]
  3004.         [color=#CC6600]if[/color](make_move && Stopped == [color=#CC6600]false[/color]) {
  3005.            prepare_move();
  3006.         }
  3007.       }
  3008.       #endif
  3009.       SERIAL_ECHO_START;
  3010.       SERIAL_ECHO(MSG_ACTIVE_EXTRUDER);
  3011.       SERIAL_PROTOCOLLN(([color=#CC6600]int[/color])active_extruder);
  3012.     }
  3013.   }
  3014.  
  3015.   [color=#CC6600]else[/color]
  3016.   {
  3017.     SERIAL_ECHO_START;
  3018.     SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
  3019.     SERIAL_ECHO(cmdbuffer[bufindr]);
  3020.     SERIAL_ECHOLNPGM([color=#006699]"\""[/color]);
  3021.   }
  3022.  
  3023.   ClearToSend();
  3024. }
  3025.  
  3026. [color=#CC6600]void[/color] FlushSerialRequestResend()
  3027. {
  3028.   [color=#7E7E7E]//char cmdbuffer[bufindr][100]="Resend:";[/color]
  3029.   MYSERIAL.[color=#CC6600]flush[/color]();
  3030.   SERIAL_PROTOCOLPGM(MSG_RESEND);
  3031.   SERIAL_PROTOCOLLN(gcode_LastN + 1);
  3032.   ClearToSend();
  3033. }
  3034.  
  3035. [color=#CC6600]void[/color] ClearToSend()
  3036. {
  3037.   previous_millis_cmd = [color=#CC6600]millis[/color]();
  3038.   #ifdef SDSUPPORT
  3039.   [color=#CC6600]if[/color](fromsd[bufindr])
  3040.     [color=#CC6600]return[/color];
  3041.   #endif [color=#7E7E7E]//SDSUPPORT[/color]
  3042.   SERIAL_PROTOCOLLNPGM(MSG_OK);
  3043. }
  3044.  
  3045. [color=#CC6600]void[/color] get_coordinates()
  3046. {
  3047.   bool seen[4]={[color=#CC6600]false[/color],[color=#CC6600]false[/color],[color=#CC6600]false[/color],[color=#CC6600]false[/color]};
  3048.   [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  3049.     [color=#CC6600]if[/color](code_seen(axis_codes[i]))
  3050.     {
  3051.       destination[i] = ([color=#CC6600]float[/color])code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i];
  3052.       seen[i]=[color=#CC6600]true[/color];
  3053.     }
  3054.     [color=#CC6600]else[/color] destination[i] = current_position[i]; [color=#7E7E7E]//Are these else lines really needed?[/color]
  3055.   }
  3056.   [color=#CC6600]if[/color](code_seen([color=#006699]'F'[/color])) {
  3057.     next_feedrate = code_value();
  3058.     [color=#CC6600]if[/color](next_feedrate > 0.0) feedrate = next_feedrate;
  3059.   }
  3060.   #ifdef FWRETRACT
  3061.   [color=#CC6600]if[/color](autoretract_enabled)
  3062.   [color=#CC6600]if[/color]( !(seen[[color=#006699]X_AXIS[/color]] || seen[[color=#006699]Y_AXIS[/color]] || seen[[color=#006699]Z_AXIS[/color]]) && seen[E_AXIS])
  3063.   {
  3064.     [color=#CC6600]float[/color] echange=destination[E_AXIS]-current_position[E_AXIS];
  3065.     [color=#CC6600]if[/color](echange<-MIN_RETRACT) [color=#7E7E7E]//retract[/color]
  3066.     {
  3067.       [color=#CC6600]if[/color](!retracted)
  3068.       {
  3069.  
  3070.       destination[[color=#006699]Z_AXIS[/color]]+=retract_zlift; [color=#7E7E7E]//not sure why chaninging current_position negatively does not work.[/color]
  3071.       [color=#7E7E7E]//if slicer retracted by echange=-1mm and you want to retract 3mm, corrrectede=-2mm additionally[/color]
  3072.       [color=#CC6600]float[/color] correctede=-echange-retract_length;
  3073.       [color=#7E7E7E]//to generate the additional steps, not the destination is changed, but inversely the current position[/color]
  3074.       current_position[E_AXIS]+=-correctede;
  3075.       feedrate=retract_feedrate;
  3076.       retracted=[color=#CC6600]true[/color];
  3077.       }
  3078.  
  3079.     }
  3080.     [color=#CC6600]else[/color]
  3081.       [color=#CC6600]if[/color](echange>MIN_RETRACT) [color=#7E7E7E]//retract_recover[/color]
  3082.     {
  3083.       [color=#CC6600]if[/color](retracted)
  3084.       {
  3085.       [color=#7E7E7E]//current_position[Z_AXIS]+=-retract_zlift;[/color]
  3086.       [color=#7E7E7E]//if slicer retracted_recovered by echange=+1mm and you want to retract_recover 3mm, corrrectede=2mm additionally[/color]
  3087.       [color=#CC6600]float[/color] correctede=-echange+1*retract_length+retract_recover_length; [color=#7E7E7E]//total unretract=retract_length+retract_recover_length[surplus][/color]
  3088.       current_position[E_AXIS]+=correctede; [color=#7E7E7E]//to generate the additional steps, not the destination is changed, but inversely the current position[/color]
  3089.       feedrate=retract_recover_feedrate;
  3090.       retracted=[color=#CC6600]false[/color];
  3091.       }
  3092.     }
  3093.  
  3094.   }
  3095.   #endif [color=#7E7E7E]//FWRETRACT[/color]
  3096. }
  3097.  
  3098. [color=#CC6600]void[/color] get_arc_coordinates()
  3099. {
  3100. #ifdef SF_ARC_FIX
  3101.    bool relative_mode_backup = relative_mode;
  3102.    relative_mode = [color=#CC6600]true[/color];
  3103. #endif
  3104.    get_coordinates();
  3105. #ifdef SF_ARC_FIX
  3106.    relative_mode=relative_mode_backup;
  3107. #endif
  3108.  
  3109.    [color=#CC6600]if[/color](code_seen([color=#006699]'I'[/color])) {
  3110.      offset[0] = code_value();
  3111.    }
  3112.    [color=#CC6600]else[/color] {
  3113.      offset[0] = 0.0;
  3114.    }
  3115.    [color=#CC6600]if[/color](code_seen([color=#006699]'J'[/color])) {
  3116.      offset[1] = code_value();
  3117.    }
  3118.    [color=#CC6600]else[/color] {
  3119.      offset[1] = 0.0;
  3120.    }
  3121. }
  3122.  
  3123. [color=#CC6600]void[/color] clamp_to_software_endstops([color=#CC6600]float[/color] target[3])
  3124. {
  3125.   [color=#CC6600]if[/color] (min_software_endstops) {
  3126.     [color=#CC6600]if[/color] (target[[color=#006699]X_AXIS[/color]] < min_pos[[color=#006699]X_AXIS[/color]]) target[[color=#006699]X_AXIS[/color]] = min_pos[[color=#006699]X_AXIS[/color]];
  3127.     [color=#CC6600]if[/color] (target[[color=#006699]Y_AXIS[/color]] < min_pos[[color=#006699]Y_AXIS[/color]]) target[[color=#006699]Y_AXIS[/color]] = min_pos[[color=#006699]Y_AXIS[/color]];
  3128.     [color=#CC6600]if[/color] (target[[color=#006699]Z_AXIS[/color]] < min_pos[[color=#006699]Z_AXIS[/color]]) target[[color=#006699]Z_AXIS[/color]] = min_pos[[color=#006699]Z_AXIS[/color]];
  3129.   }
  3130.  
  3131.   [color=#CC6600]if[/color] (max_software_endstops) {
  3132.     [color=#CC6600]if[/color] (target[[color=#006699]X_AXIS[/color]] > max_pos[[color=#006699]X_AXIS[/color]]) target[[color=#006699]X_AXIS[/color]] = max_pos[[color=#006699]X_AXIS[/color]];
  3133.     [color=#CC6600]if[/color] (target[[color=#006699]Y_AXIS[/color]] > max_pos[[color=#006699]Y_AXIS[/color]]) target[[color=#006699]Y_AXIS[/color]] = max_pos[[color=#006699]Y_AXIS[/color]];
  3134.     [color=#CC6600]if[/color] (target[[color=#006699]Z_AXIS[/color]] > max_pos[[color=#006699]Z_AXIS[/color]]) target[[color=#006699]Z_AXIS[/color]] = max_pos[[color=#006699]Z_AXIS[/color]];
  3135.   }
  3136. }
  3137.  
  3138. #ifdef DELTA
  3139. [color=#CC6600]void[/color] calculate_delta([color=#CC6600]float[/color] cartesian[3])
  3140. {
  3141.   delta[[color=#006699]X_AXIS[/color]] = [color=#CC6600]sqrt[/color](DELTA_DIAGONAL_ROD_2
  3142.                        - [color=#CC6600]sq[/color](DELTA_TOWER1_X-cartesian[[color=#006699]X_AXIS[/color]])
  3143.                        - [color=#CC6600]sq[/color](DELTA_TOWER1_Y-cartesian[[color=#006699]Y_AXIS[/color]])
  3144.                        ) + cartesian[[color=#006699]Z_AXIS[/color]];
  3145.   delta[[color=#006699]Y_AXIS[/color]] = [color=#CC6600]sqrt[/color](DELTA_DIAGONAL_ROD_2
  3146.                        - [color=#CC6600]sq[/color](DELTA_TOWER2_X-cartesian[[color=#006699]X_AXIS[/color]])
  3147.                        - [color=#CC6600]sq[/color](DELTA_TOWER2_Y-cartesian[[color=#006699]Y_AXIS[/color]])
  3148.                        ) + cartesian[[color=#006699]Z_AXIS[/color]];
  3149.   delta[[color=#006699]Z_AXIS[/color]] = [color=#CC6600]sqrt[/color](DELTA_DIAGONAL_ROD_2
  3150.                        - [color=#CC6600]sq[/color](DELTA_TOWER3_X-cartesian[[color=#006699]X_AXIS[/color]])
  3151.                        - [color=#CC6600]sq[/color](DELTA_TOWER3_Y-cartesian[[color=#006699]Y_AXIS[/color]])
  3152.                        ) + cartesian[[color=#006699]Z_AXIS[/color]];
  3153.   [color=#7E7E7E]/*[/color]
  3154. [color=#7E7E7E]  SERIAL_ECHOPGM("cartesian x="); SERIAL_ECHO(cartesian[X_AXIS]);[/color]
  3155. [color=#7E7E7E]  SERIAL_ECHOPGM(" y="); SERIAL_ECHO(cartesian[Y_AXIS]);[/color]
  3156. [color=#7E7E7E]  SERIAL_ECHOPGM(" z="); SERIAL_ECHOLN(cartesian[Z_AXIS]);[/color]
  3157.  
  3158. [color=#7E7E7E]  SERIAL_ECHOPGM("delta x="); SERIAL_ECHO(delta[X_AXIS]);[/color]
  3159. [color=#7E7E7E]  SERIAL_ECHOPGM(" y="); SERIAL_ECHO(delta[Y_AXIS]);[/color]
  3160. [color=#7E7E7E]  SERIAL_ECHOPGM(" z="); SERIAL_ECHOLN(delta[Z_AXIS]);[/color]
  3161. [color=#7E7E7E]  */[/color]
  3162. }
  3163. #endif
  3164.  
  3165. [color=#CC6600]void[/color] prepare_move()
  3166. {
  3167.   clamp_to_software_endstops(destination);
  3168.  
  3169.   previous_millis_cmd = [color=#CC6600]millis[/color]();
  3170. #ifdef DELTA
  3171.   [color=#CC6600]float[/color] difference[NUM_AXIS];
  3172.   [color=#CC6600]for[/color] (int8_t i=0; i < NUM_AXIS; i++) {
  3173.     difference[i] = destination[i] - current_position[i];
  3174.   }
  3175.   [color=#CC6600]float[/color] cartesian_mm = [color=#CC6600]sqrt[/color]([color=#CC6600]sq[/color](difference[[color=#006699]X_AXIS[/color]]) +
  3176.                             [color=#CC6600]sq[/color](difference[[color=#006699]Y_AXIS[/color]]) +
  3177.                             [color=#CC6600]sq[/color](difference[[color=#006699]Z_AXIS[/color]]));
  3178.   [color=#CC6600]if[/color] (cartesian_mm < 0.000001) { cartesian_mm = [color=#CC6600]abs[/color](difference[E_AXIS]); }
  3179.   [color=#CC6600]if[/color] (cartesian_mm < 0.000001) { [color=#CC6600]return[/color]; }
  3180.   [color=#CC6600]float[/color] seconds = 6000 * cartesian_mm / feedrate / feedmultiply;
  3181.   [color=#CC6600]int[/color] steps = [color=#CC6600]max[/color](1, [color=#CC6600]int[/color](DELTA_SEGMENTS_PER_SECOND * seconds));
  3182.   [color=#7E7E7E]// SERIAL_ECHOPGM("mm="); SERIAL_ECHO(cartesian_mm);[/color]
  3183.   [color=#7E7E7E]// SERIAL_ECHOPGM(" seconds="); SERIAL_ECHO(seconds);[/color]
  3184.   [color=#7E7E7E]// SERIAL_ECHOPGM(" steps="); SERIAL_ECHOLN(steps);[/color]
  3185.   [color=#CC6600]for[/color] ([color=#CC6600]int[/color] s = 1; s <= steps; s++) {
  3186.     [color=#CC6600]float[/color] fraction = [color=#CC6600]float[/color](s) / [color=#CC6600]float[/color](steps);
  3187.     [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  3188.       destination[i] = current_position[i] + difference[i] * fraction;
  3189.     }
  3190.     calculate_delta(destination);
  3191.     plan_buffer_line(delta[[color=#006699]X_AXIS[/color]], delta[[color=#006699]Y_AXIS[/color]], delta[[color=#006699]Z_AXIS[/color]],
  3192.                      destination[E_AXIS], feedrate*feedmultiply/60/100.0,
  3193.                      active_extruder);
  3194.   }
  3195. #else
  3196.  
  3197. #ifdef DUAL_X_CARRIAGE
  3198.   [color=#CC6600]if[/color] (active_extruder_parked)
  3199.   {
  3200.     [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0)
  3201.     {
  3202.       [color=#7E7E7E]// move duplicate extruder into correct duplication position.[/color]
  3203.       plan_set_position(inactive_extruder_x_pos, current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  3204.       plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]] + duplicate_extruder_x_offset, current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]],
  3205.           current_position[E_AXIS], max_feedrate[[color=#006699]X_AXIS[/color]], 1);
  3206.       plan_set_position(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS]);
  3207.       st_synchronize();
  3208.       extruder_duplication_enabled = [color=#CC6600]true[/color];
  3209.       active_extruder_parked = [color=#CC6600]false[/color];
  3210.     }
  3211.     [color=#CC6600]else[/color] [color=#CC6600]if[/color] (dual_x_carriage_mode == DXC_AUTO_PARK_MODE) [color=#7E7E7E]// handle unparking of head[/color]
  3212.     {
  3213.       [color=#CC6600]if[/color] (current_position[E_AXIS] == destination[E_AXIS])
  3214.       {
  3215.         [color=#7E7E7E]// this is a travel move - skit it but keep track of current position (so that it can later[/color]
  3216.         [color=#7E7E7E]// be used as start of first non-travel move)[/color]
  3217.         [color=#CC6600]if[/color] (delayed_move_time != 0xFFFFFFFFUL)
  3218.         {
  3219.           memcpy(current_position, destination, sizeof(current_position));
  3220.           [color=#CC6600]if[/color] (destination[[color=#006699]Z_AXIS[/color]] > raised_parked_position[[color=#006699]Z_AXIS[/color]])
  3221.             raised_parked_position[[color=#006699]Z_AXIS[/color]] = destination[[color=#006699]Z_AXIS[/color]];
  3222.           delayed_move_time = [color=#CC6600]millis[/color]();
  3223.           [color=#CC6600]return[/color];
  3224.         }
  3225.       }
  3226.       delayed_move_time = 0;
  3227.       [color=#7E7E7E]// unpark extruder: 1) raise, 2) move into starting XY position, 3) lower[/color]
  3228.       plan_buffer_line(raised_parked_position[[color=#006699]X_AXIS[/color]], raised_parked_position[[color=#006699]Y_AXIS[/color]], raised_parked_position[[color=#006699]Z_AXIS[/color]], current_position[E_AXIS], max_feedrate[[color=#006699]Z_AXIS[/color]], active_extruder);
  3229.       plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], raised_parked_position[[color=#006699]Z_AXIS[/color]],
  3230.           current_position[E_AXIS], [color=#CC6600]min[/color](max_feedrate[[color=#006699]X_AXIS[/color]],max_feedrate[[color=#006699]Y_AXIS[/color]]), active_extruder);
  3231.       plan_buffer_line(current_position[[color=#006699]X_AXIS[/color]], current_position[[color=#006699]Y_AXIS[/color]], current_position[[color=#006699]Z_AXIS[/color]],
  3232.           current_position[E_AXIS], max_feedrate[[color=#006699]Z_AXIS[/color]], active_extruder);
  3233.       active_extruder_parked = [color=#CC6600]false[/color];
  3234.     }
  3235.   }
  3236. #endif [color=#7E7E7E]//DUAL_X_CARRIAGE[/color]
  3237.  
  3238.   [color=#7E7E7E]// Do not use feedmultiply for E or Z only moves[/color]
  3239.   [color=#CC6600]if[/color]( (current_position[[color=#006699]X_AXIS[/color]] == destination [[color=#006699]X_AXIS[/color]]) && (current_position[[color=#006699]Y_AXIS[/color]] == destination [[color=#006699]Y_AXIS[/color]])) {
  3240.       plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate/60, active_extruder);
  3241.   }
  3242.   [color=#CC6600]else[/color] {
  3243.     plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder);
  3244.   }
  3245. #endif [color=#7E7E7E]//else DELTA[/color]
  3246.   [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  3247.     current_position[i] = destination[i];
  3248.   }
  3249. }
  3250.  
  3251. [color=#CC6600]void[/color] prepare_arc_move([color=#CC6600]char[/color] isclockwise) {
  3252.   [color=#CC6600]float[/color] r = hypot(offset[[color=#006699]X_AXIS[/color]], offset[[color=#006699]Y_AXIS[/color]]); [color=#7E7E7E]// Compute arc radius for mc_arc[/color]
  3253.  
  3254.   [color=#7E7E7E]// Trace the arc[/color]
  3255.   mc_arc(current_position, destination, offset, [color=#006699]X_AXIS[/color], [color=#006699]Y_AXIS[/color], [color=#006699]Z_AXIS[/color], feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder);
  3256.  
  3257.   [color=#7E7E7E]// As far as the parser is concerned, the position is now == target. In reality the[/color]
  3258.   [color=#7E7E7E]// motion control system might still be processing the action and the real tool position[/color]
  3259.   [color=#7E7E7E]// in any intermediate location.[/color]
  3260.   [color=#CC6600]for[/color](int8_t i=0; i < NUM_AXIS; i++) {
  3261.     current_position[i] = destination[i];
  3262.   }
  3263.   previous_millis_cmd = [color=#CC6600]millis[/color]();
  3264. }
  3265.  
  3266. #if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
  3267.  
  3268. #if defined(FAN_PIN)
  3269.   #if CONTROLLERFAN_PIN == FAN_PIN
  3270.     #error [color=#006699]"You cannot set CONTROLLERFAN_PIN equal to FAN_PIN"[/color]
  3271.   #endif
  3272. #endif
  3273.  
  3274. [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] lastMotor = 0; [color=#7E7E7E]//Save the time for when a motor was turned on last[/color]
  3275. [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] lastMotorCheck = 0;
  3276.  
  3277. [color=#CC6600]void[/color] controllerFan()
  3278. {
  3279.   [color=#CC6600]if[/color] (([color=#CC6600]millis[/color]() - lastMotorCheck) >= 2500) [color=#7E7E7E]//Not a time critical function, so we only check every 2500ms[/color]
  3280.   {
  3281.     lastMotorCheck = [color=#CC6600]millis[/color]();
  3282.  
  3283.     [color=#CC6600]if[/color](!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) || (soft_pwm_bed > 0)
  3284.     #if EXTRUDERS > 2
  3285.        || !READ(E2_ENABLE_PIN)
  3286.     #endif
  3287.     #if EXTRUDER > 1
  3288.       #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
  3289.        || !READ(X2_ENABLE_PIN)
  3290.       #endif
  3291.        || !READ(E1_ENABLE_PIN)
  3292.     #endif
  3293.        || !READ(E0_ENABLE_PIN)) [color=#7E7E7E]//If any of the drivers are enabled...[/color]
  3294.     {
  3295.       lastMotor = [color=#CC6600]millis[/color](); [color=#7E7E7E]//... set time to NOW so the fan will turn on[/color]
  3296.     }
  3297.  
  3298.     [color=#CC6600]if[/color] (([color=#CC6600]millis[/color]() - lastMotor) >= (CONTROLLERFAN_SECS*1000UL) || lastMotor == 0) [color=#7E7E7E]//If the last time any driver was enabled, is longer since than CONTROLLERSEC...[/color]
  3299.     {
  3300.         [color=#CC6600]digitalWrite[/color](CONTROLLERFAN_PIN, 0);
  3301.         [color=#CC6600]analogWrite[/color](CONTROLLERFAN_PIN, 0);
  3302.     }
  3303.     [color=#CC6600]else[/color]
  3304.     {
  3305.         [color=#7E7E7E]// allows digital or PWM fan output to be used (see M42 handling)[/color]
  3306.         [color=#CC6600]digitalWrite[/color](CONTROLLERFAN_PIN, CONTROLLERFAN_SPEED);
  3307.         [color=#CC6600]analogWrite[/color](CONTROLLERFAN_PIN, CONTROLLERFAN_SPEED);
  3308.     }
  3309.   }
  3310. }
  3311. #endif
  3312.  
  3313. #ifdef TEMP_STAT_LEDS
  3314. [color=#CC6600]static[/color] bool blue_led = [color=#CC6600]false[/color];
  3315. [color=#CC6600]static[/color] bool red_led = [color=#CC6600]false[/color];
  3316. [color=#CC6600]static[/color] uint32_t stat_update = 0;
  3317.  
  3318. [color=#CC6600]void[/color] handle_status_leds([color=#CC6600]void[/color]) {
  3319.   [color=#CC6600]float[/color] max_temp = 0.0;
  3320.   [color=#CC6600]if[/color]([color=#CC6600]millis[/color]() > stat_update) {
  3321.     stat_update += 500; [color=#7E7E7E]// Update every 0.5s[/color]
  3322.     [color=#CC6600]for[/color] (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
  3323.        max_temp = [color=#CC6600]max[/color](max_temp, degHotend(cur_extruder));
  3324.        max_temp = [color=#CC6600]max[/color](max_temp, degTargetHotend(cur_extruder));
  3325.     }
  3326.     #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
  3327.       max_temp = [color=#CC6600]max[/color](max_temp, degTargetBed());
  3328.       max_temp = [color=#CC6600]max[/color](max_temp, degBed());
  3329.     #endif
  3330.     [color=#CC6600]if[/color]((max_temp > 55.0) && (red_led == [color=#CC6600]false[/color])) {
  3331.       [color=#CC6600]digitalWrite[/color](STAT_LED_RED, 1);
  3332.       [color=#CC6600]digitalWrite[/color](STAT_LED_BLUE, 0);
  3333.       red_led = [color=#CC6600]true[/color];
  3334.       blue_led = [color=#CC6600]false[/color];
  3335.     }
  3336.     [color=#CC6600]if[/color]((max_temp < 54.0) && (blue_led == [color=#CC6600]false[/color])) {
  3337.       [color=#CC6600]digitalWrite[/color](STAT_LED_RED, 0);
  3338.       [color=#CC6600]digitalWrite[/color](STAT_LED_BLUE, 1);
  3339.       red_led = [color=#CC6600]false[/color];
  3340.       blue_led = [color=#CC6600]true[/color];
  3341.     }
  3342.   }
  3343. }
  3344. #endif
  3345.  
  3346. [color=#CC6600]void[/color] manage_inactivity()
  3347. {
  3348.   [color=#CC6600]if[/color]( ([color=#CC6600]millis[/color]() - previous_millis_cmd) > max_inactive_time )
  3349.     [color=#CC6600]if[/color](max_inactive_time)
  3350.       kill();
  3351.   [color=#CC6600]if[/color](stepper_inactive_time) {
  3352.     [color=#CC6600]if[/color]( ([color=#CC6600]millis[/color]() - previous_millis_cmd) > stepper_inactive_time )
  3353.     {
  3354.       [color=#CC6600]if[/color](blocks_queued() == [color=#CC6600]false[/color]) {
  3355.         disable_x();
  3356.         disable_y();
  3357.         disable_z();
  3358.         disable_e0();
  3359.         disable_e1();
  3360.         disable_e2();
  3361.       }
  3362.     }
  3363.   }
  3364.   #if defined(KILL_PIN) && KILL_PIN > -1
  3365.     [color=#CC6600]if[/color]( 0 == READ(KILL_PIN) )
  3366.       kill();
  3367.   #endif
  3368.   #if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
  3369.     controllerFan(); [color=#7E7E7E]//Check if fan should be turned on to cool stepper drivers down[/color]
  3370.   #endif
  3371.   #ifdef EXTRUDER_RUNOUT_PREVENT
  3372.     [color=#CC6600]if[/color]( ([color=#CC6600]millis[/color]() - previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 )
  3373.     [color=#CC6600]if[/color](degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP)
  3374.     {
  3375.      bool oldstatus=READ(E0_ENABLE_PIN);
  3376.      enable_e0();
  3377.      [color=#CC6600]float[/color] oldepos=current_position[E_AXIS];
  3378.      [color=#CC6600]float[/color] oldedes=destination[E_AXIS];
  3379.      plan_buffer_line(destination[[color=#006699]X_AXIS[/color]], destination[[color=#006699]Y_AXIS[/color]], destination[[color=#006699]Z_AXIS[/color]],
  3380.                       destination[E_AXIS]+EXTRUDER_RUNOUT_EXTRUDE*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS],
  3381.                       EXTRUDER_RUNOUT_SPEED/60.*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], active_extruder);
  3382.      current_position[E_AXIS]=oldepos;
  3383.      destination[E_AXIS]=oldedes;
  3384.      plan_set_e_position(oldepos);
  3385.      previous_millis_cmd=[color=#CC6600]millis[/color]();
  3386.      st_synchronize();
  3387.      WRITE(E0_ENABLE_PIN,oldstatus);
  3388.     }
  3389.   #endif
  3390.   #if defined(DUAL_X_CARRIAGE)
  3391.     [color=#7E7E7E]// handle delayed move timeout[/color]
  3392.     [color=#CC6600]if[/color] (delayed_move_time != 0 && ([color=#CC6600]millis[/color]() - delayed_move_time) > 1000 && Stopped == [color=#CC6600]false[/color])
  3393.     {
  3394.       [color=#7E7E7E]// travel moves have been received so enact them[/color]
  3395.       delayed_move_time = 0xFFFFFFFFUL; [color=#7E7E7E]// force moves to be done[/color]
  3396.       memcpy(destination,current_position,sizeof(destination));
  3397.       prepare_move();
  3398.     }
  3399.   #endif
  3400.   #ifdef TEMP_STAT_LEDS
  3401.       handle_status_leds();
  3402.   #endif
  3403.   check_axes_activity();
  3404. }
  3405.  
  3406. [color=#CC6600]void[/color] kill()
  3407. {
  3408.   cli(); [color=#7E7E7E]// Stop interrupts[/color]
  3409.   disable_heater();
  3410.  
  3411.   disable_x();
  3412.   disable_y();
  3413.   disable_z();
  3414.   disable_e0();
  3415.   disable_e1();
  3416.   disable_e2();
  3417.  
  3418. #if defined(PS_ON_PIN) && PS_ON_PIN > -1
  3419.   [color=#CC6600]pinMode[/color](PS_ON_PIN,[color=#006699]INPUT[/color]);
  3420. #endif
  3421.   SERIAL_ERROR_START;
  3422.   SERIAL_ERRORLNPGM(MSG_ERR_KILLED);
  3423.   LCD_ALERTMESSAGEPGM(MSG_KILLED);
  3424.   suicide();
  3425.   [color=#CC6600]while[/color](1) { [color=#7E7E7E]/* Intentionally left empty */[/color] } [color=#7E7E7E]// Wait for reset[/color]
  3426. }
  3427.  
  3428. [color=#CC6600]void[/color] Stop()
  3429. {
  3430.   disable_heater();
  3431.   [color=#CC6600]if[/color](Stopped == [color=#CC6600]false[/color]) {
  3432.     Stopped = [color=#CC6600]true[/color];
  3433.     Stopped_gcode_LastN = gcode_LastN; [color=#7E7E7E]// Save last g_code for restart[/color]
  3434.     SERIAL_ERROR_START;
  3435.     SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
  3436.     LCD_MESSAGEPGM(MSG_STOPPED);
  3437.   }
  3438. }
  3439.  
  3440. bool IsStopped() { [color=#CC6600]return[/color] Stopped; };
  3441.  
  3442. #ifdef FAST_PWM_FAN
  3443. [color=#CC6600]void[/color] setPwmFrequency(uint8_t pin, [color=#CC6600]int[/color] val)
  3444. {
  3445.   val &= 0x07;
  3446.   [color=#CC6600]switch[/color](digitalPinToTimer(pin))
  3447.   {
  3448.  
  3449.     #if defined(TCCR0A)
  3450.     [color=#CC6600]case[/color] TIMER0A:
  3451.     [color=#CC6600]case[/color] TIMER0B:
  3452. [color=#7E7E7E]//         TCCR0B &= ~(_BV(CS00) | _BV(CS01) | _BV(CS02));[/color]
  3453. [color=#7E7E7E]//         TCCR0B |= val;[/color]
  3454.          [color=#CC6600]break[/color];
  3455.     #endif
  3456.  
  3457.     #if defined(TCCR1A)
  3458.     [color=#CC6600]case[/color] TIMER1A:
  3459.     [color=#CC6600]case[/color] TIMER1B:
  3460. [color=#7E7E7E]//         TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));[/color]
  3461. [color=#7E7E7E]//         TCCR1B |= val;[/color]
  3462.          [color=#CC6600]break[/color];
  3463.     #endif
  3464.  
  3465.     #if defined(TCCR2)
  3466.     [color=#CC6600]case[/color] TIMER2:
  3467.     [color=#CC6600]case[/color] TIMER2:
  3468.          TCCR2 &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
  3469.          TCCR2 |= val;
  3470.          [color=#CC6600]break[/color];
  3471.     #endif
  3472.  
  3473.     #if defined(TCCR2A)
  3474.     [color=#CC6600]case[/color] TIMER2A:
  3475.     [color=#CC6600]case[/color] TIMER2B:
  3476.          TCCR2B &= ~(_BV(CS20) | _BV(CS21) | _BV(CS22));
  3477.          TCCR2B |= val;
  3478.          [color=#CC6600]break[/color];
  3479.     #endif
  3480.  
  3481.     #if defined(TCCR3A)
  3482.     [color=#CC6600]case[/color] TIMER3A:
  3483.     [color=#CC6600]case[/color] TIMER3B:
  3484.     [color=#CC6600]case[/color] TIMER3C:
  3485.          TCCR3B &= ~(_BV(CS30) | _BV(CS31) | _BV(CS32));
  3486.          TCCR3B |= val;
  3487.          [color=#CC6600]break[/color];
  3488.     #endif
  3489.  
  3490.     #if defined(TCCR4A)
  3491.     [color=#CC6600]case[/color] TIMER4A:
  3492.     [color=#CC6600]case[/color] TIMER4B:
  3493.     [color=#CC6600]case[/color] TIMER4C:
  3494.          TCCR4B &= ~(_BV(CS40) | _BV(CS41) | _BV(CS42));
  3495.          TCCR4B |= val;
  3496.          [color=#CC6600]break[/color];
  3497.    #endif
  3498.  
  3499.     #if defined(TCCR5A)
  3500.     [color=#CC6600]case[/color] TIMER5A:
  3501.     [color=#CC6600]case[/color] TIMER5B:
  3502.     [color=#CC6600]case[/color] TIMER5C:
  3503.          TCCR5B &= ~(_BV(CS50) | _BV(CS51) | _BV(CS52));
  3504.          TCCR5B |= val;
  3505.          [color=#CC6600]break[/color];
  3506.    #endif
  3507.  
  3508.   }
  3509. }
  3510. #endif [color=#7E7E7E]//FAST_PWM_FAN[/color]
  3511.  
  3512. bool setTargetedHotend([color=#CC6600]int[/color] code){
  3513.   tmp_extruder = active_extruder;
  3514.   [color=#CC6600]if[/color](code_seen([color=#006699]'T'[/color])) {
  3515.     tmp_extruder = code_value();
  3516.     [color=#CC6600]if[/color](tmp_extruder >= EXTRUDERS) {
  3517.       SERIAL_ECHO_START;
  3518.       [color=#CC6600]switch[/color](code){
  3519.         [color=#CC6600]case[/color] 104:
  3520.           SERIAL_ECHO(MSG_M104_INVALID_EXTRUDER);
  3521.           [color=#CC6600]break[/color];
  3522.         [color=#CC6600]case[/color] 105:
  3523.           SERIAL_ECHO(MSG_M105_INVALID_EXTRUDER);
  3524.           [color=#CC6600]break[/color];
  3525.         [color=#CC6600]case[/color] 109:
  3526.           SERIAL_ECHO(MSG_M109_INVALID_EXTRUDER);
  3527.           [color=#CC6600]break[/color];
  3528.         [color=#CC6600]case[/color] 218:
  3529.           SERIAL_ECHO(MSG_M218_INVALID_EXTRUDER);
  3530.           [color=#CC6600]break[/color];
  3531.       }
  3532.       SERIAL_ECHOLN(tmp_extruder);
  3533.       [color=#CC6600]return[/color] [color=#CC6600]true[/color];
  3534.     }
  3535.   }
  3536.   [color=#CC6600]return[/color] [color=#CC6600]false[/color];
  3537. }
  3538.  
  3539. [/quote]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement