@ -67,136 +67,149 @@
# include <SPI.h>
# include <SPI.h>
# endif
# endif
// look here for descriptions of G-codes: http://linuxcnc.org/handbook/gcode/g-code.html
/**
// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
* Look here for descriptions of G - codes :
* - http : //linuxcnc.org/handbook/gcode/g-code.html
//Implemented Codes
* - http : //objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
//-------------------
*
// G0 -> G1
* Help us document these G - codes online :
// G1 - Coordinated Movement X Y Z E
* - http : //reprap.org/wiki/G-code
// G2 - CW ARC
* - https : //github.com/MarlinFirmware/Marlin/wiki/Marlin-G-Code
// G3 - CCW ARC
*/
// G4 - Dwell S<seconds> or P<milliseconds>
// G10 - retract filament according to settings of M207
/**
// G11 - retract recover filament according to settings of M208
* Implemented Codes
// G28 - Home one or more axes
* - - - - - - - - - - - - - - - - - - -
// G29 - Detailed Z-Probe, probes the bed at 3 or more points. Will fail if you haven't homed yet.
*
// G30 - Single Z Probe, probes bed at current XY location.
* " G " Codes
// G31 - Dock sled (Z_PROBE_SLED only)
*
// G32 - Undock sled (Z_PROBE_SLED only)
* G0 - > G1
// G90 - Use Absolute Coordinates
* G1 - Coordinated Movement X Y Z E
// G91 - Use Relative Coordinates
* G2 - CW ARC
// G92 - Set current position to coordinates given
* G3 - CCW ARC
* G4 - Dwell S < seconds > or P < milliseconds >
// M Codes
* G10 - retract filament according to settings of M207
// M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
* G11 - retract recover filament according to settings of M208
// M1 - Same as M0
* G28 - Home one or more axes
// M17 - Enable/Power all stepper motors
* G29 - Detailed Z - Probe , probes the bed at 3 or more points . Will fail if you haven ' t homed yet .
// M18 - Disable all stepper motors; same as M84
* G30 - Single Z Probe , probes bed at current XY location .
// M20 - List SD card
* G31 - Dock sled ( Z_PROBE_SLED only )
// M21 - Init SD card
* G32 - Undock sled ( Z_PROBE_SLED only )
// M22 - Release SD card
* G90 - Use Absolute Coordinates
// M23 - Select SD file (M23 filename.g)
* G91 - Use Relative Coordinates
// M24 - Start/resume SD print
* G92 - Set current position to coordinates given
// M25 - Pause SD print
*
// M26 - Set SD position in bytes (M26 S12345)
* " M " Codes
// M27 - Report SD print status
*
// M28 - Start SD write (M28 filename.g)
* M0 - Unconditional stop - Wait for user to press a button on the LCD ( Only if ULTRA_LCD is enabled )
// M29 - Stop SD write
* M1 - Same as M0
// M30 - Delete file from SD (M30 filename.g)
* M17 - Enable / Power all stepper motors
// M31 - Output time since last M109 or SD card start to serial
* M18 - Disable all stepper motors ; same as M84
// M32 - Select file and start SD print (Can be used _while_ printing from SD card files):
* M20 - List SD card
// syntax "M32 /path/filename#", or "M32 S<startpos bytes> !filename#"
* M21 - Init SD card
// Call gcode file : "M32 P !filename#" and return to caller file after finishing (similar to #include).
* M22 - Release SD card
// The '#' is necessary when calling from within sd files, as it stops buffer prereading
* M23 - Select SD file ( M23 filename . g )
// 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.
* M24 - Start / resume SD print
// M48 - Measure Z_Probe repeatability. M48 [n # of points] [X position] [Y position] [V_erboseness #] [E_ngage Probe] [L # of legs of travel]
* M25 - Pause SD print
// M80 - Turn on Power Supply
* M26 - Set SD position in bytes ( M26 S12345 )
// M81 - Turn off Power Supply
* M27 - Report SD print status
// M82 - Set E codes absolute (default)
* M28 - Start SD write ( M28 filename . g )
// M83 - Set E codes relative while in Absolute Coordinates (G90) mode
* M29 - Stop SD write
// M84 - Disable steppers until next move,
* M30 - Delete file from SD ( M30 filename . g )
// or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout.
* M31 - Output time since last M109 or SD card start to serial
// M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
* M32 - Select file and start SD print ( Can be used _while_ printing from SD card files ) :
// M92 - Set axis_steps_per_unit - same syntax as G92
* syntax " M32 /path/filename# " , or " M32 S<startpos bytes> !filename# "
// M104 - Set extruder target temp
* Call gcode file : " M32 P !filename# " and return to caller file after finishing ( similar to # include ) .
// M105 - Read current temp
* The ' # ' is necessary when calling from within sd files , as it stops buffer prereading
// M106 - Fan on
* 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 .
// M107 - Fan off
* M48 - Measure Z_Probe repeatability . M48 [ n # of points ] [ X position ] [ Y position ] [ V_erboseness # ] [ E_ngage Probe ] [ L # of legs of travel ]
// M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating
* M80 - Turn on Power Supply
// Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
* M81 - Turn off Power Supply
// IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
* M82 - Set E codes absolute ( default )
// M112 - Emergency stop
* M83 - Set E codes relative while in Absolute Coordinates ( G90 ) mode
// M114 - Output current position to serial port
* M84 - Disable steppers until next move ,
// M115 - Capabilities string
* or use S < seconds > to specify an inactivity timeout , after which the steppers will be disabled . S0 to disable the timeout .
// M117 - display message
* M85 - Set inactivity shutdown timer with parameter S < seconds > . To disable set zero ( default )
// M119 - Output Endstop status to serial port
* M92 - Set axis_steps_per_unit - same syntax as G92
// M120 - Enable endstop detection
* M104 - Set extruder target temp
// M121 - Disable endstop detection
* M105 - Read current temp
// M126 - Solenoid Air Valve Open (BariCUDA support by jmil)
* M106 - Fan on
// M127 - Solenoid Air Valve Closed (BariCUDA vent to atmospheric pressure by jmil)
* M107 - Fan off
// M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M109 - Sxxx Wait for extruder current temp to reach target temp . Waits only when heating
// M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* Rxxx Wait for extruder current temp to reach target temp . Waits when heating and cooling
// M140 - Set bed target temp
* IF AUTOTEMP is enabled , S < mintemp > B < maxtemp > F < factor > . Exit autotemp by any M109 without F
// M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
* M112 - Emergency stop
// M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
* M114 - Output current position to serial port
// Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
* M115 - Capabilities string
// M200 - set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).:D<millimeters>-
* M117 - display message
// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
* M119 - Output Endstop status to serial port
// M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!!
* M120 - Enable endstop detection
// M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
* M121 - Disable endstop detection
// M204 - Set default acceleration: P for Printing moves, R for Retract only (no X, Y, Z) moves and T for Travel (non printing) moves (ex. M204 P800 T3000 R9000) in mm/sec^2
* M126 - Solenoid Air Valve Open ( BariCUDA support by jmil )
// 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
* M127 - Solenoid Air Valve Closed ( BariCUDA vent to atmospheric pressure by jmil )
// M206 - Set additional homing offset
* M128 - EtoP Open ( BariCUDA EtoP = electricity to air pressure transducer by jmil )
// M207 - Set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop], stays in mm regardless of M200 setting
* M129 - EtoP Closed ( BariCUDA EtoP = electricity to air pressure transducer by jmil )
// M208 - Set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/sec]
* M140 - Set bed target temp
// 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.
* M150 - Set BlinkM Color Output R : Red < 0 - 255 > U ( ! ) : Green < 0 - 255 > B : Blue < 0 - 255 > over i2c , G for green does not work .
// M218 - Set hotend offset (in mm): T<extruder_number> X<offset_on_X> Y<offset_on_Y>
* M190 - Sxxx Wait for bed current temp to reach target temp . Waits only when heating
// M220 - Set speed factor override percentage: S<factor in percent>
* Rxxx Wait for bed current temp to reach target temp . Waits when heating and cooling
// M221 - Set extrude factor override percentage: S<factor in percent>
* M200 - set filament diameter and set E axis units to cubic millimeters ( use S0 to set back to millimeters ) . : D < millimeters > -
// M226 - Wait until the specified pin reaches the state required: P<pin number> S<pin state>
* M201 - Set max acceleration in units / s ^ 2 for print moves ( M201 X1000 Y1000 )
// M240 - Trigger a camera to take a photograph
* M202 - Set max acceleration in units / s ^ 2 for travel moves ( M202 X1000 Y1000 ) Unused in Marlin ! !
// M250 - Set LCD contrast C<contrast value> (value 0..63)
* M203 - Set maximum feedrate that your machine can sustain ( M203 X200 Y200 Z300 E10000 ) in mm / sec
// M280 - Set servo position absolute. P: servo index, S: angle or microseconds
* M204 - Set default acceleration : P for Printing moves , R for Retract only ( no X , Y , Z ) moves and T for Travel ( non printing ) moves ( ex . M204 P800 T3000 R9000 ) in mm / sec ^ 2
// M300 - Play beep sound S<frequency Hz> P<duration ms>
* 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
// M301 - Set PID parameters P I and D
* M206 - Set additional homing offset
// M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
* M207 - Set retract length S [ positive mm ] F [ feedrate mm / min ] Z [ additional zlift / hop ] , stays in mm regardless of M200 setting
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
* M208 - Set recover = unretract length S [ positive mm surplus to the M207 S * ] F [ feedrate mm / sec ]
// M304 - Set bed PID parameters P I and D
* 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 .
// M380 - Activate solenoid on active extruder
* M218 - Set hotend offset ( in mm ) : T < extruder_number > X < offset_on_X > Y < offset_on_Y >
// M381 - Disable all solenoids
* M220 - Set speed factor override percentage : S < factor in percent >
// M400 - Finish all moves
* M221 - Set extrude factor override percentage : S < factor in percent >
// M401 - Lower z-probe if present
* M226 - Wait until the specified pin reaches the state required : P < pin number > S < pin state >
// M402 - Raise z-probe if present
* M240 - Trigger a camera to take a photograph
// M404 - N<dia in mm> Enter the nominal filament width (3mm, 1.75mm ) or will display nominal filament width without parameters
* M250 - Set LCD contrast C < contrast value > ( value 0. .63 )
// M405 - Turn on Filament Sensor extrusion control. Optional D<delay in cm> to set delay in centimeters between sensor and extruder
* M280 - Set servo position absolute . P : servo index , S : angle or microseconds
// M406 - Turn off Filament Sensor extrusion control
* M300 - Play beep sound S < frequency Hz > P < duration ms >
// M407 - Display measured filament diameter
* M301 - Set PID parameters P I and D
// M500 - Store parameters in EEPROM
* M302 - Allow cold extrudes , or set the minimum extrude S < temperature > .
// M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily).
* M303 - PID relay autotune S < temperature > sets the target temperature . ( default target temperature = 150 C )
// M502 - Revert to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
* M304 - Set bed PID parameters P I and D
// M503 - Print the current settings (from memory not from EEPROM). Use S0 to leave off headings.
* M380 - Activate solenoid on active extruder
// M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
* M381 - Disable all solenoids
// M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
* M400 - Finish all moves
// M665 - Set delta configurations: L<diagonal rod> R<delta radius> S<segments/s>
* M401 - Lower z - probe if present
// M666 - Set delta endstop adjustment
* M402 - Raise z - probe if present
// M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
* M404 - N < dia in mm > Enter the nominal filament width ( 3 mm , 1.75 mm ) or will display nominal filament width without parameters
// M907 - Set digital trimpot motor current using axis codes.
* M405 - Turn on Filament Sensor extrusion control . Optional D < delay in cm > to set delay in centimeters between sensor and extruder
// M908 - Control digital trimpot directly.
* M406 - Turn off Filament Sensor extrusion control
// M350 - Set microstepping mode.
* M407 - Display measured filament diameter
// M351 - Toggle MS1 MS2 pins directly.
* M500 - Store parameters in EEPROM
* M501 - Read parameters from EEPROM ( if you need reset them after you changed them temporarily ) .
// ************ SCARA Specific - This can change to suit future G-code regulations
* M502 - Revert to the default " factory settings " . You still need to store them in EEPROM afterwards if you want to .
// M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
* M503 - Print the current settings ( from memory not from EEPROM ) . Use S0 to leave off headings .
// M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
* M540 - Use S [ 0 | 1 ] to enable or disable the stop SD card print on endstop hit ( requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED )
// M362 - SCARA calibration: Move to cal-position PsiA (0 deg calibration)
* M600 - Pause for filament change X [ pos ] Y [ pos ] Z [ relative lift ] E [ initial retract ] L [ later retract distance for removal ]
// M363 - SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
* M665 - Set delta configurations : L < diagonal rod > R < delta radius > S < segments / s >
// M364 - SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
* M666 - Set delta endstop adjustment
// M365 - SCARA calibration: Scaling factor, X, Y, Z axis
* M605 - Set dual x - carriage movement mode : S < mode > [ X < duplication x - offset > R < duplication temp offset > ]
//************* SCARA End ***************
* M907 - Set digital trimpot motor current using axis codes .
* M908 - Control digital trimpot directly .
// M928 - Start SD logging (M928 filename.g) - ended by M29
* M350 - Set microstepping mode .
// M999 - Restart after being stopped by error
* M351 - Toggle MS1 MS2 pins directly .
*
* * * * * * * * * * * * * SCARA Specific - This can change to suit future G - code regulations
* M360 - SCARA calibration : Move to cal - position ThetaA ( 0 deg calibration )
* M361 - SCARA calibration : Move to cal - position ThetaB ( 90 deg calibration - steps per degree )
* M362 - SCARA calibration : Move to cal - position PsiA ( 0 deg calibration )
* M363 - SCARA calibration : Move to cal - position PsiB ( 90 deg calibration - steps per degree )
* M364 - SCARA calibration : Move to cal - position PSIC ( 90 deg to Theta calibration position )
* M365 - SCARA calibration : Scaling factor , X , Y , Z axis
* * * * * * * * * * * * * * SCARA End * * * * * * * * * * * * * * *
*
* M928 - Start SD logging ( M928 filename . g ) - ended by M29
* M999 - Restart after being stopped by error
*/
# ifdef SDSUPPORT
# ifdef SDSUPPORT
CardReader card ;
CardReader card ;
@ -210,12 +223,16 @@ static float destination[NUM_AXIS] = { 0.0 };
bool axis_known_position [ 3 ] = { false } ;
bool axis_known_position [ 3 ] = { false } ;
static long gcode_N , gcode_LastN , Stopped_gcode_LastN = 0 ;
static long gcode_N , gcode_LastN , Stopped_gcode_LastN = 0 ;
static char cmdbuffer [ BUFSIZE ] [ MAX_CMD_SIZE ] ;
static int cmd_queue_index_r = 0 ;
static int cmd_queue_index_w = 0 ;
static int commands_in_queue = 0 ;
static char command_queue [ BUFSIZE ] [ MAX_CMD_SIZE ] ;
float homing_feedrate [ ] = HOMING_FEEDRATE ;
float homing_feedrate [ ] = HOMING_FEEDRATE ;
bool axis_relative_modes [ ] = AXIS_RELATIVE_MODES ;
bool axis_relative_modes [ ] = AXIS_RELATIVE_MODES ;
int feedmultiply = 100 ; //100->1 200->2
int feed rate_multiplier = 100 ; //100->1 200->2
int saved_feed multiply ;
int saved_feed rate_multiplier ;
int extruder_multiply [ EXTRUDERS ] = ARRAY_BY_EXTRUDERS ( 100 , 100 , 100 , 100 ) ;
int extruder_multiply [ EXTRUDERS ] = ARRAY_BY_EXTRUDERS ( 100 , 100 , 100 , 100 ) ;
bool volumetric_enabled = false ;
bool volumetric_enabled = false ;
float filament_size [ EXTRUDERS ] = ARRAY_BY_EXTRUDERS ( DEFAULT_NOMINAL_FILAMENT_DIA , DEFAULT_NOMINAL_FILAMENT_DIA , DEFAULT_NOMINAL_FILAMENT_DIA , DEFAULT_NOMINAL_FILAMENT_DIA ) ;
float filament_size [ EXTRUDERS ] = ARRAY_BY_EXTRUDERS ( DEFAULT_NOMINAL_FILAMENT_DIA , DEFAULT_NOMINAL_FILAMENT_DIA , DEFAULT_NOMINAL_FILAMENT_DIA , DEFAULT_NOMINAL_FILAMENT_DIA ) ;
@ -234,9 +251,6 @@ const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
static float offset [ 3 ] = { 0 } ;
static float offset [ 3 ] = { 0 } ;
static bool relative_mode = false ; //Determines Absolute or Relative Coordinates
static bool relative_mode = false ; //Determines Absolute or Relative Coordinates
static int bufindr = 0 ;
static int bufindw = 0 ;
static int buflen = 0 ;
static char serial_char ;
static char serial_char ;
static int serial_count = 0 ;
static int serial_count = 0 ;
static boolean comment_mode = false ;
static boolean comment_mode = false ;
@ -247,10 +261,10 @@ const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
millis_t previous_cmd_ms = 0 ;
millis_t previous_cmd_ms = 0 ;
static millis_t max_inactive_time = 0 ;
static millis_t max_inactive_time = 0 ;
static millis_t stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME * 1000L ;
static millis_t stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME * 1000L ;
millis_t starttime = 0 ; ///< Print job start time
millis_t print_job_start_ms = 0 ; ///< Print job start time
millis_t stoptime = 0 ; ///< Print job stop time
millis_t print_job_stop_ms = 0 ; ///< Print job stop time
static uint8_t target_extruder ;
static uint8_t target_extruder ;
bool CooldownNoWait = true ;
bool no_wait_for_cooling = true ;
bool target_direction ;
bool target_direction ;
# ifdef ENABLE_AUTO_BED_LEVELING
# ifdef ENABLE_AUTO_BED_LEVELING
@ -357,7 +371,7 @@ bool target_direction;
# endif
# endif
# ifdef FILAMENT_RUNOUT_SENSOR
# ifdef FILAMENT_RUNOUT_SENSOR
static bool filrunoutEnque d = false ;
static bool filrunoutEnque ue d = false ;
# endif
# endif
# ifdef SDSUPPORT
# ifdef SDSUPPORT
@ -410,8 +424,10 @@ void serial_echopair_P(const char *s_P, unsigned long v) { serialprintPGM(s_P);
}
}
# endif //!SDSUPPORT
# endif //!SDSUPPORT
//Injects the next command from the pending sequence of commands, when possible
/**
//Return false if and only if no command was pending
* Inject the next command from the command queue , when possible
* Return false only if no command was pending
*/
static bool drain_queued_commands_P ( ) {
static bool drain_queued_commands_P ( ) {
if ( ! queued_commands_P ) return false ;
if ( ! queued_commands_P ) return false ;
@ -425,7 +441,7 @@ static bool drain_queued_commands_P() {
char c ;
char c ;
while ( ( c = cmd [ i ] ) & & c ! = ' \n ' ) i + + ; // find the end of this gcode command
while ( ( c = cmd [ i ] ) & & c ! = ' \n ' ) i + + ; // find the end of this gcode command
cmd [ i ] = ' \0 ' ;
cmd [ i ] = ' \0 ' ;
if ( enqueuecommand ( cmd ) ) { // buffer was not full (else we will retry later)
if ( enqueuecommand ( cmd ) ) { // buffer was not full (else we will retry later)
if ( c )
if ( c )
queued_commands_P + = i + 1 ; // move to next command
queued_commands_P + = i + 1 ; // move to next command
else
else
@ -434,45 +450,46 @@ static bool drain_queued_commands_P() {
return true ;
return true ;
}
}
//Record one or many commands to run from program memory.
/**
//Aborts the current queue, if any.
* Record one or many commands to run from program memory .
//Note: drain_queued_commands_P() must be called repeatedly to drain the commands afterwards
* Aborts the current queue , if any .
* Note : drain_queued_commands_P ( ) must be called repeatedly to drain the commands afterwards
*/
void enqueuecommands_P ( const char * pgcode ) {
void enqueuecommands_P ( const char * pgcode ) {
queued_commands_P = pgcode ;
queued_commands_P = pgcode ;
drain_queued_commands_P ( ) ; // first command executed asap (when possible)
drain_queued_commands_P ( ) ; // first command executed asap (when possible)
}
}
//adds a single command to the main command buffer, from RAM
/**
//that is really done in a non-safe way.
* Copy a command directly into the main command buffer , from RAM .
//needs overworking someday
*
//Returns false if it failed to do so
* This is done in a non - safe way and needs a rework someday .
bool enqueuecommand ( const char * cmd )
* Returns false if it doesn ' t add any command
{
*/
if ( * cmd = = ' ; ' )
bool enqueuecommand ( const char * cmd ) {
return false ;
if ( buflen > = BUFSIZE )
if ( * cmd = = ' ; ' | | commands_in_queue > = BUFSIZE ) return false ;
return false ;
//this is dangerous if a mixing of serial and this happens
// This is dangerous if a mixing of serial and this happens
strcpy ( & ( cmdbuffer [ bufindw ] [ 0 ] ) , cmd ) ;
char * command = command_queue [ cmd_queue_index_w ] ;
strcpy ( command , cmd ) ;
SERIAL_ECHO_START ;
SERIAL_ECHO_START ;
SERIAL_ECHOPGM ( MSG_Enque ing) ;
SERIAL_ECHOPGM ( MSG_Enque ue ing) ;
SERIAL_ECHO ( c mdbuffer[ bufindw ] ) ;
SERIAL_ECHO ( c ommand ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
bufindw= ( bufindw + 1 ) % BUFSIZE ;
cmd_queue_index_w = ( cmd_queue_index_w + 1 ) % BUFSIZE ;
buflen + = 1 ;
commands_in_queue+ + ;
return true ;
return true ;
}
}
void setup_killpin ( )
void setup_killpin ( ) {
{
# if HAS_KILL
# if HAS_KILL
SET_INPUT ( KILL_PIN ) ;
SET_INPUT ( KILL_PIN ) ;
WRITE ( KILL_PIN , HIGH ) ;
WRITE ( KILL_PIN , HIGH ) ;
# endif
# endif
}
}
void setup_filrunoutpin ( )
void setup_filrunoutpin ( ) {
{
# if HAS_FILRUNOUT
# if HAS_FILRUNOUT
pinMode ( FILRUNOUT_PIN , INPUT ) ;
pinMode ( FILRUNOUT_PIN , INPUT ) ;
# ifdef ENDSTOPPULLUP_FIL_RUNOUT
# ifdef ENDSTOPPULLUP_FIL_RUNOUT
@ -482,8 +499,7 @@ void setup_filrunoutpin()
}
}
// Set home pin
// Set home pin
void setup_homepin ( void )
void setup_homepin ( void ) {
{
# if HAS_HOME
# if HAS_HOME
SET_INPUT ( HOME_PIN ) ;
SET_INPUT ( HOME_PIN ) ;
WRITE ( HOME_PIN , HIGH ) ;
WRITE ( HOME_PIN , HIGH ) ;
@ -491,15 +507,13 @@ void setup_homepin(void)
}
}
void setup_photpin ( )
void setup_photpin ( ) {
{
# if HAS_PHOTOGRAPH
# if HAS_PHOTOGRAPH
OUT_WRITE ( PHOTOGRAPH_PIN , LOW ) ;
OUT_WRITE ( PHOTOGRAPH_PIN , LOW ) ;
# endif
# endif
}
}
void setup_powerhold ( )
void setup_powerhold ( ) {
{
# if HAS_SUICIDE
# if HAS_SUICIDE
OUT_WRITE ( SUICIDE_PIN , HIGH ) ;
OUT_WRITE ( SUICIDE_PIN , HIGH ) ;
# endif
# endif
@ -512,15 +526,13 @@ void setup_powerhold()
# endif
# endif
}
}
void suicide ( )
void suicide ( ) {
{
# if HAS_SUICIDE
# if HAS_SUICIDE
OUT_WRITE ( SUICIDE_PIN , LOW ) ;
OUT_WRITE ( SUICIDE_PIN , LOW ) ;
# endif
# endif
}
}
void servo_init ( )
void servo_init ( ) {
{
# if NUM_SERVOS >= 1 && HAS_SERVO_0
# if NUM_SERVOS >= 1 && HAS_SERVO_0
servos [ 0 ] . attach ( SERVO0_PIN ) ;
servos [ 0 ] . attach ( SERVO0_PIN ) ;
# endif
# endif
@ -547,6 +559,24 @@ void servo_init()
# endif
# endif
}
}
/**
* Marlin entry - point : Set up before the program loop
* - Set up the kill pin , filament runout , power hold
* - Start the serial port
* - Print startup messages and diagnostics
* - Get EEPROM or default settings
* - Initialize managers for :
* • temperature
* • planner
* • watchdog
* • stepper
* • photo pin
* • servos
* • LCD controller
* • Digipot I2C
* • Z probe sled
* • status LEDs
*/
void setup ( ) {
void setup ( ) {
setup_killpin ( ) ;
setup_killpin ( ) ;
setup_filrunoutpin ( ) ;
setup_filrunoutpin ( ) ;
@ -587,7 +617,7 @@ void setup() {
# ifdef SDSUPPORT
# ifdef SDSUPPORT
for ( int8_t i = 0 ; i < BUFSIZE ; i + + ) fromsd [ i ] = false ;
for ( int8_t i = 0 ; i < BUFSIZE ; i + + ) fromsd [ i ] = false ;
# endif // !SDSUPPORT
# endif
// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)
// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)
Config_RetrieveSettings ( ) ;
Config_RetrieveSettings ( ) ;
@ -628,36 +658,54 @@ void setup() {
# endif
# endif
}
}
/**
* The main Marlin program loop
*
* - Save or log commands to SD
* - Process available commands ( if not saving )
* - Call heater manager
* - Call inactivity manager
* - Call endstop manager
* - Call LCD update
*/
void loop ( ) {
void loop ( ) {
if ( buflen < BUFSIZE - 1 ) get_command ( ) ;
if ( commands_in_queue < BUFSIZE - 1 ) get_command ( ) ;
# ifdef SDSUPPORT
# ifdef SDSUPPORT
card . checkautostart ( false ) ;
card . checkautostart ( false ) ;
# endif
# endif
if ( buflen ) {
if ( commands_in_queue ) {
# ifdef SDSUPPORT
# ifdef SDSUPPORT
if ( card . saving ) {
if ( card . saving ) {
if ( strstr_P ( cmdbuffer [ bufindr ] , PSTR ( " M29 " ) ) = = NULL ) {
char * command = command_queue [ cmd_queue_index_r ] ;
card . write_command ( cmdbuffer [ bufindr ] ) ;
if ( strstr_P ( command , PSTR ( " M29 " ) ) ) {
// M29 closes the file
card . closefile ( ) ;
SERIAL_PROTOCOLLNPGM ( MSG_FILE_SAVED ) ;
}
else {
// Write the string from the read buffer to SD
card . write_command ( command ) ;
if ( card . logging )
if ( card . logging )
process_commands ( ) ;
process_commands ( ) ; // The card is saving because it's logging
else
else
SERIAL_PROTOCOLLNPGM ( MSG_OK ) ;
SERIAL_PROTOCOLLNPGM ( MSG_OK ) ;
}
}
else {
card . closefile ( ) ;
SERIAL_PROTOCOLLNPGM ( MSG_FILE_SAVED ) ;
}
}
}
else
else
process_commands ( ) ;
process_commands ( ) ;
# else
# else
process_commands ( ) ;
process_commands ( ) ;
# endif // SDSUPPORT
# endif // SDSUPPORT
buflen - - ;
bufindr = ( bufindr + 1 ) % BUFSIZE ;
commands_in_queue - - ;
cmd_queue_index_r = ( cmd_queue_index_r + 1 ) % BUFSIZE ;
}
}
// Check heater every n milliseconds
// Check heater every n milliseconds
manage_heater ( ) ;
manage_heater ( ) ;
@ -666,12 +714,20 @@ void loop() {
lcd_update ( ) ;
lcd_update ( ) ;
}
}
/**
* Add to the circular command queue the next command from :
* - The command - injection queue ( queued_commands_P )
* - The active serial input ( usually USB )
* - The SD card file being actively printed
*/
void get_command ( ) {
void get_command ( ) {
if ( drain_queued_commands_P ( ) ) return ; // priority is given to non-serial commands
if ( drain_queued_commands_P ( ) ) return ; // priority is given to non-serial commands
while ( MYSERIAL . available ( ) > 0 & & buflen < BUFSIZE ) {
while ( MYSERIAL . available ( ) > 0 & & commands_in_queue < BUFSIZE ) {
serial_char = MYSERIAL . read ( ) ;
serial_char = MYSERIAL . read ( ) ;
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' | |
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' | |
serial_count > = ( MAX_CMD_SIZE - 1 )
serial_count > = ( MAX_CMD_SIZE - 1 )
) {
) {
@ -680,16 +736,17 @@ void get_command() {
if ( ! serial_count ) return ; // shortcut for empty lines
if ( ! serial_count ) return ; // shortcut for empty lines
cmdbuffer [ bufindw ] [ serial_count ] = 0 ; // terminate string
char * command = command_queue [ cmd_queue_index_w ] ;
command [ serial_count ] = 0 ; // terminate string
# ifdef SDSUPPORT
# ifdef SDSUPPORT
fromsd [ bufind w] = false ;
fromsd [ cmd_queue_index_ w] = false ;
# endif
# endif
if ( strchr ( c mdbuffer[ bufindw ] , ' N ' ) ! = NULL ) {
if ( strchr ( c ommand , ' N ' ) ! = NULL ) {
strchr_pointer = strchr ( c mdbuffer[ bufindw ] , ' N ' ) ;
strchr_pointer = strchr ( c ommand , ' N ' ) ;
gcode_N = ( strtol ( strchr_pointer + 1 , NULL , 10 ) ) ;
gcode_N = ( strtol ( strchr_pointer + 1 , NULL , 10 ) ) ;
if ( gcode_N ! = gcode_LastN + 1 & & strstr_P ( c mdbuffer[ bufindw ] , PSTR ( " M110 " ) ) = = NULL ) {
if ( gcode_N ! = gcode_LastN + 1 & & strstr_P ( c ommand , PSTR ( " M110 " ) ) = = NULL ) {
SERIAL_ERROR_START ;
SERIAL_ERROR_START ;
SERIAL_ERRORPGM ( MSG_ERR_LINE_NO ) ;
SERIAL_ERRORPGM ( MSG_ERR_LINE_NO ) ;
SERIAL_ERRORLN ( gcode_LastN ) ;
SERIAL_ERRORLN ( gcode_LastN ) ;
@ -699,11 +756,11 @@ void get_command() {
return ;
return ;
}
}
if ( strchr ( c mdbuffer[ bufindw ] , ' * ' ) ! = NULL ) {
if ( strchr ( c ommand , ' * ' ) ! = NULL ) {
byte checksum = 0 ;
byte checksum = 0 ;
byte count = 0 ;
byte count = 0 ;
while ( c mdbuffer[ bufindw ] [ count ] ! = ' * ' ) checksum ^ = c mdbuffer[ bufindw ] [ count + + ] ;
while ( c ommand [ count ] ! = ' * ' ) checksum ^ = c ommand [ count + + ] ;
strchr_pointer = strchr ( c mdbuffer[ bufindw ] , ' * ' ) ;
strchr_pointer = strchr ( c ommand , ' * ' ) ;
if ( strtol ( strchr_pointer + 1 , NULL , 10 ) ! = checksum ) {
if ( strtol ( strchr_pointer + 1 , NULL , 10 ) ! = checksum ) {
SERIAL_ERROR_START ;
SERIAL_ERROR_START ;
@ -728,7 +785,7 @@ void get_command() {
//if no errors, continue parsing
//if no errors, continue parsing
}
}
else { // if we don't receive 'N' but still see '*'
else { // if we don't receive 'N' but still see '*'
if ( ( strchr ( c mdbuffer[ bufindw ] , ' * ' ) ! = NULL ) ) {
if ( ( strchr ( c ommand , ' * ' ) ! = NULL ) ) {
SERIAL_ERROR_START ;
SERIAL_ERROR_START ;
SERIAL_ERRORPGM ( MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM ) ;
SERIAL_ERRORPGM ( MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM ) ;
SERIAL_ERRORLN ( gcode_LastN ) ;
SERIAL_ERRORLN ( gcode_LastN ) ;
@ -737,8 +794,8 @@ void get_command() {
}
}
}
}
if ( strchr ( c mdbuffer[ bufindw ] , ' G ' ) ! = NULL ) {
if ( strchr ( c ommand , ' G ' ) ! = NULL ) {
strchr_pointer = strchr ( c mdbuffer[ bufindw ] , ' G ' ) ;
strchr_pointer = strchr ( c ommand , ' G ' ) ;
switch ( strtol ( strchr_pointer + 1 , NULL , 10 ) ) {
switch ( strtol ( strchr_pointer + 1 , NULL , 10 ) ) {
case 0 :
case 0 :
case 1 :
case 1 :
@ -755,24 +812,24 @@ void get_command() {
}
}
// If command was e-stop process now
// If command was e-stop process now
if ( strcmp ( c mdbuffer[ bufindw ] , " M112 " ) = = 0 ) kill ( ) ;
if ( strcmp ( c ommand , " M112 " ) = = 0 ) kill ( ) ;
bufindw = ( bufind w + 1 ) % BUFSIZE ;
cmd_queue_index_w = ( cmd_queue_index_ w + 1 ) % BUFSIZE ;
buflen + = 1 ;
commands_in_queue + = 1 ;
serial_count = 0 ; //clear buffer
serial_count = 0 ; //clear buffer
}
}
else if ( serial_char = = ' \\ ' ) { // Handle escapes
else if ( serial_char = = ' \\ ' ) { // Handle escapes
if ( MYSERIAL . available ( ) > 0 & & buflen < BUFSIZE ) {
if ( MYSERIAL . available ( ) > 0 & & commands_in_queue < BUFSIZE ) {
// if we have one more character, copy it over
// if we have one more character, copy it over
serial_char = MYSERIAL . read ( ) ;
serial_char = MYSERIAL . read ( ) ;
c mdbuffer[ bufind w] [ serial_count + + ] = serial_char ;
c ommand_queue[ cmd_queue_index_ w] [ serial_count + + ] = serial_char ;
}
}
// otherwise do nothing
// otherwise do nothing
}
}
else { // its not a newline, carriage return or escape char
else { // its not a newline, carriage return or escape char
if ( serial_char = = ' ; ' ) comment_mode = true ;
if ( serial_char = = ' ; ' ) comment_mode = true ;
if ( ! comment_mode ) c mdbuffer[ bufind w] [ serial_count + + ] = serial_char ;
if ( ! comment_mode ) c ommand_queue[ cmd_queue_index_ w] [ serial_count + + ] = serial_char ;
}
}
}
}
@ -785,9 +842,9 @@ void get_command() {
// this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
// this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
static bool stop_buffering = false ;
static bool stop_buffering = false ;
if ( buflen = = 0 ) stop_buffering = false ;
if ( commands_in_queue = = 0 ) stop_buffering = false ;
while ( ! card . eof ( ) & & buflen < BUFSIZE & & ! stop_buffering ) {
while ( ! card . eof ( ) & & commands_in_queue < BUFSIZE & & ! stop_buffering ) {
int16_t n = card . get ( ) ;
int16_t n = card . get ( ) ;
serial_char = ( char ) n ;
serial_char = ( char ) n ;
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' | |
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' | |
@ -796,9 +853,9 @@ void get_command() {
) {
) {
if ( card . eof ( ) ) {
if ( card . eof ( ) ) {
SERIAL_PROTOCOLLNPGM ( MSG_FILE_PRINTED ) ;
SERIAL_PROTOCOLLNPGM ( MSG_FILE_PRINTED ) ;
stoptime = millis ( ) ;
print_job_stop_ms = millis ( ) ;
char time [ 30 ] ;
char time [ 30 ] ;
millis_t t = ( stoptime - starttime ) / 1000 ;
millis_t t = ( print_job_stop_ms - print_job_start_ms ) / 1000 ;
int hours = t / 60 / 60 , minutes = ( t / 60 ) % 60 ;
int hours = t / 60 / 60 , minutes = ( t / 60 ) % 60 ;
sprintf_P ( time , PSTR ( " %i " MSG_END_HOUR " %i " MSG_END_MINUTE ) , hours , minutes ) ;
sprintf_P ( time , PSTR ( " %i " MSG_END_HOUR " %i " MSG_END_MINUTE ) , hours , minutes ) ;
SERIAL_ECHO_START ;
SERIAL_ECHO_START ;
@ -813,18 +870,18 @@ void get_command() {
comment_mode = false ; //for new command
comment_mode = false ; //for new command
return ; //if empty line
return ; //if empty line
}
}
c mdbuffer[ bufind w] [ serial_count ] = 0 ; //terminate string
c ommand_queue[ cmd_queue_index_ w] [ serial_count ] = 0 ; //terminate string
// if (!comment_mode) {
// if (!comment_mode) {
fromsd [ bufind w] = true ;
fromsd [ cmd_queue_index_ w] = true ;
buflen + = 1 ;
commands_in_queue + = 1 ;
bufindw = ( bufindw + 1 ) % BUFSIZE ;
cmd_queue_index_w = ( cmd_queue_index_w + 1 ) % BUFSIZE ;
// }
// }
comment_mode = false ; //for new command
comment_mode = false ; //for new command
serial_count = 0 ; //clear buffer
serial_count = 0 ; //clear buffer
}
}
else {
else {
if ( serial_char = = ' ; ' ) comment_mode = true ;
if ( serial_char = = ' ; ' ) comment_mode = true ;
if ( ! comment_mode ) c mdbuffer[ bufind w] [ serial_count + + ] = serial_char ;
if ( ! comment_mode ) c ommand_queue[ cmd_queue_index_ w] [ serial_count + + ] = serial_char ;
}
}
}
}
@ -854,7 +911,7 @@ long code_value_long() { return strtol(strchr_pointer + 1, NULL, 10); }
int16_t code_value_short ( ) { return ( int16_t ) strtol ( strchr_pointer + 1 , NULL , 10 ) ; }
int16_t code_value_short ( ) { return ( int16_t ) strtol ( strchr_pointer + 1 , NULL , 10 ) ; }
bool code_seen ( char code ) {
bool code_seen ( char code ) {
strchr_pointer = strchr ( c mdbuffer[ bufind r] , code ) ;
strchr_pointer = strchr ( c ommand_queue[ cmd_queue_index_ r] , code ) ;
return ( strchr_pointer ! = NULL ) ; //Return True if a character was found
return ( strchr_pointer ! = NULL ) ; //Return True if a character was found
}
}
@ -871,12 +928,12 @@ static const PROGMEM type array##_P[3] = \
static inline type array ( int axis ) \
static inline type array ( int axis ) \
{ return pgm_read_any ( & array # # _P [ axis ] ) ; }
{ return pgm_read_any ( & array # # _P [ axis ] ) ; }
XYZ_CONSTS_FROM_CONFIG ( float , base_min_pos , MIN_POS ) ;
XYZ_CONSTS_FROM_CONFIG ( float , base_min_pos , MIN_POS ) ;
XYZ_CONSTS_FROM_CONFIG ( float , base_max_pos , MAX_POS ) ;
XYZ_CONSTS_FROM_CONFIG ( float , base_max_pos , MAX_POS ) ;
XYZ_CONSTS_FROM_CONFIG ( float , base_home_pos , HOME_POS ) ;
XYZ_CONSTS_FROM_CONFIG ( float , base_home_pos , HOME_POS ) ;
XYZ_CONSTS_FROM_CONFIG ( float , max_length , MAX_LENGTH ) ;
XYZ_CONSTS_FROM_CONFIG ( float , max_length , MAX_LENGTH ) ;
XYZ_CONSTS_FROM_CONFIG ( float , home_bump_mm , HOME_BUMP_MM ) ;
XYZ_CONSTS_FROM_CONFIG ( float , home_bump_mm , HOME_BUMP_MM ) ;
XYZ_CONSTS_FROM_CONFIG ( signed char , home_dir , HOME_DIR ) ;
XYZ_CONSTS_FROM_CONFIG ( signed char , home_dir , HOME_DIR ) ;
# ifdef DUAL_X_CARRIAGE
# ifdef DUAL_X_CARRIAGE
@ -1023,7 +1080,7 @@ inline void set_destination_to_current() { memcpy(destination, current_position,
void prepare_move_raw ( ) {
void prepare_move_raw ( ) {
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
calculate_delta ( destination ) ;
calculate_delta ( destination ) ;
plan_buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , destination [ E_AXIS ] , ( feedrate / 60 ) * ( feed multiply / 100.0 ) , active_extruder ) ;
plan_buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , destination [ E_AXIS ] , ( feedrate / 60 ) * ( feed rate_multiplier / 100.0 ) , active_extruder ) ;
set_current_to_destination ( ) ;
set_current_to_destination ( ) ;
}
}
# endif
# endif
@ -1176,8 +1233,8 @@ inline void set_destination_to_current() { memcpy(destination, current_position,
static void setup_for_endstop_move ( ) {
static void setup_for_endstop_move ( ) {
saved_feedrate = feedrate ;
saved_feedrate = feedrate ;
saved_feed multiply = feedmultiply ;
saved_feed rate_multiplier = feedrate_multiplier ;
feed multiply = 100 ;
feed rate_multiplier = 100 ;
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
enable_endstops ( true ) ;
enable_endstops ( true ) ;
}
}
@ -1187,7 +1244,7 @@ inline void set_destination_to_current() { memcpy(destination, current_position,
enable_endstops ( false ) ;
enable_endstops ( false ) ;
# endif
# endif
feedrate = saved_feedrate ;
feedrate = saved_feedrate ;
feed multiply = saved_feedmultiply ;
feed rate_multiplier = saved_feedrate_multiplier ;
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
}
}
@ -1610,12 +1667,12 @@ static void homeaxis(AxisEnum axis) {
# define SLED_DOCKING_OFFSET 0
# define SLED_DOCKING_OFFSET 0
# endif
# endif
//
/**
// Method to dock/undock a sled designed by Charles Bell.
* Method to dock / undock a sled designed by Charles Bell .
//
*
// dock[in] If true, move to MAX_X and engage the electromagnet
* dock [ in ] If true , move to MAX_X and engage the electromagnet
// offset[in] The additional distance to move to adjust docking location
* offset [ in ] The additional distance to move to adjust docking location
//
*/
static void dock_sled ( bool dock , int offset = 0 ) {
static void dock_sled ( bool dock , int offset = 0 ) {
if ( ! axis_known_position [ X_AXIS ] | | ! axis_known_position [ Y_AXIS ] ) {
if ( ! axis_known_position [ X_AXIS ] | | ! axis_known_position [ Y_AXIS ] ) {
LCD_MESSAGEPGM ( MSG_POSITION_UNKNOWN ) ;
LCD_MESSAGEPGM ( MSG_POSITION_UNKNOWN ) ;
@ -1649,9 +1706,10 @@ static void homeaxis(AxisEnum axis) {
inline void gcode_G0_G1 ( ) {
inline void gcode_G0_G1 ( ) {
if ( IsRunning ( ) ) {
if ( IsRunning ( ) ) {
get_coordinates ( ) ; // For X Y Z E F
get_coordinates ( ) ; // For X Y Z E F
# ifdef FWRETRACT
# ifdef FWRETRACT
if ( autoretract_enabled )
if ( ! ( code_seen ( ' X ' ) | | code_seen ( ' Y ' ) | | code_seen ( ' Z ' ) ) & & code_seen ( ' E ' ) ) {
if ( autoretract_enabled & & ! ( code_seen ( ' X ' ) | | code_seen ( ' Y ' ) | | code_seen ( ' Z ' ) ) & & code_seen ( ' E ' ) ) {
float echange = destination [ E_AXIS ] - current_position [ E_AXIS ] ;
float echange = destination [ E_AXIS ] - current_position [ E_AXIS ] ;
// Is this move an attempt to retract or recover?
// Is this move an attempt to retract or recover?
if ( ( echange < - MIN_RETRACT & & ! retracted [ active_extruder ] ) | | ( echange > MIN_RETRACT & & retracted [ active_extruder ] ) ) {
if ( ( echange < - MIN_RETRACT & & ! retracted [ active_extruder ] ) | | ( echange > MIN_RETRACT & & retracted [ active_extruder ] ) ) {
@ -1661,7 +1719,9 @@ inline void gcode_G0_G1() {
return ;
return ;
}
}
}
}
# endif //FWRETRACT
# endif //FWRETRACT
prepare_move ( ) ;
prepare_move ( ) ;
//ClearToSend();
//ClearToSend();
}
}
@ -1758,8 +1818,8 @@ inline void gcode_G28() {
# endif
# endif
saved_feedrate = feedrate ;
saved_feedrate = feedrate ;
saved_feed multiply = feedmultiply ;
saved_feed rate_multiplier = feedrate_multiplier ;
feed multiply = 100 ;
feed rate_multiplier = 100 ;
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
enable_endstops ( true ) ;
enable_endstops ( true ) ;
@ -2013,7 +2073,7 @@ inline void gcode_G28() {
# endif
# endif
feedrate = saved_feedrate ;
feedrate = saved_feedrate ;
feed multiply = saved_feedmultiply ;
feed rate_multiplier = saved_feedrate_multiplier ;
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
endstops_hit_on_purpose ( ) ; // clear endstop hit flags
endstops_hit_on_purpose ( ) ; // clear endstop hit flags
}
}
@ -2659,7 +2719,7 @@ inline void gcode_M17() {
*/
*/
inline void gcode_M24 ( ) {
inline void gcode_M24 ( ) {
card . startFileprint ( ) ;
card . startFileprint ( ) ;
starttime = millis ( ) ;
print_job_start_ms = millis ( ) ;
}
}
/**
/**
@ -2691,7 +2751,7 @@ inline void gcode_M17() {
char * codepos = strchr_pointer + 4 ;
char * codepos = strchr_pointer + 4 ;
char * starpos = strchr ( codepos , ' * ' ) ;
char * starpos = strchr ( codepos , ' * ' ) ;
if ( starpos ) {
if ( starpos ) {
char * npos = strchr ( c mdbuffer[ bufind r] , ' N ' ) ;
char * npos = strchr ( c ommand_queue[ cmd_queue_index_ r] , ' N ' ) ;
strchr_pointer = strchr ( npos , ' ' ) + 1 ;
strchr_pointer = strchr ( npos , ' ' ) + 1 ;
* ( starpos ) = ' \0 ' ;
* ( starpos ) = ' \0 ' ;
}
}
@ -2714,7 +2774,7 @@ inline void gcode_M17() {
card . closefile ( ) ;
card . closefile ( ) ;
char * starpos = strchr ( strchr_pointer + 4 , ' * ' ) ;
char * starpos = strchr ( strchr_pointer + 4 , ' * ' ) ;
if ( starpos ) {
if ( starpos ) {
char * npos = strchr ( c mdbuffer[ bufind r] , ' N ' ) ;
char * npos = strchr ( c ommand_queue[ cmd_queue_index_ r] , ' N ' ) ;
strchr_pointer = strchr ( npos , ' ' ) + 1 ;
strchr_pointer = strchr ( npos , ' ' ) + 1 ;
* ( starpos ) = ' \0 ' ;
* ( starpos ) = ' \0 ' ;
}
}
@ -2728,8 +2788,8 @@ inline void gcode_M17() {
* M31 : Get the time since the start of SD Print ( or last M109 )
* M31 : Get the time since the start of SD Print ( or last M109 )
*/
*/
inline void gcode_M31 ( ) {
inline void gcode_M31 ( ) {
stoptime = millis ( ) ;
print_job_stop_ms = millis ( ) ;
millis_t t = ( stoptime - starttime ) / 1000 ;
millis_t t = ( print_job_stop_ms - print_job_start_ms ) / 1000 ;
int min = t / 60 , sec = t % 60 ;
int min = t / 60 , sec = t % 60 ;
char time [ 30 ] ;
char time [ 30 ] ;
sprintf_P ( time , PSTR ( " %i min, %i sec " ) , min , sec ) ;
sprintf_P ( time , PSTR ( " %i min, %i sec " ) , min , sec ) ;
@ -2769,7 +2829,7 @@ inline void gcode_M31() {
card . startFileprint ( ) ;
card . startFileprint ( ) ;
if ( ! call_procedure )
if ( ! call_procedure )
starttime = millis ( ) ; //procedure calls count as normal print time.
print_job_start_ms = millis ( ) ; //procedure calls count as normal print time.
}
}
}
}
@ -2779,7 +2839,7 @@ inline void gcode_M31() {
inline void gcode_M928 ( ) {
inline void gcode_M928 ( ) {
char * starpos = strchr ( strchr_pointer + 5 , ' * ' ) ;
char * starpos = strchr ( strchr_pointer + 5 , ' * ' ) ;
if ( starpos ) {
if ( starpos ) {
char * npos = strchr ( c mdbuffer[ bufind r] , ' N ' ) ;
char * npos = strchr ( c ommand_queue[ cmd_queue_index_ r] , ' N ' ) ;
strchr_pointer = strchr ( npos , ' ' ) + 1 ;
strchr_pointer = strchr ( npos , ' ' ) + 1 ;
* ( starpos ) = ' \0 ' ;
* ( starpos ) = ' \0 ' ;
}
}
@ -3185,8 +3245,8 @@ inline void gcode_M109() {
LCD_MESSAGEPGM ( MSG_HEATING ) ;
LCD_MESSAGEPGM ( MSG_HEATING ) ;
CooldownNoWait = code_seen ( ' S ' ) ;
no_wait_for_cooling = code_seen ( ' S ' ) ;
if ( CooldownNoWait | | code_seen ( ' R ' ) ) {
if ( no_wait_for_cooling | | code_seen ( ' R ' ) ) {
float temp = code_value ( ) ;
float temp = code_value ( ) ;
setTargetHotend ( temp , target_extruder ) ;
setTargetHotend ( temp , target_extruder ) ;
# ifdef DUAL_X_CARRIAGE
# ifdef DUAL_X_CARRIAGE
@ -3218,7 +3278,7 @@ inline void gcode_M109() {
while ( ( ! cancel_heatup ) & & ( ( residency_start_ms = = - 1 ) | |
while ( ( ! cancel_heatup ) & & ( ( residency_start_ms = = - 1 ) | |
( residency_start_ms > = 0 & & ( ( ( unsigned int ) ( millis ( ) - residency_start_ms ) ) < ( TEMP_RESIDENCY_TIME * 1000UL ) ) ) ) )
( residency_start_ms > = 0 & & ( ( ( unsigned int ) ( millis ( ) - residency_start_ms ) ) < ( TEMP_RESIDENCY_TIME * 1000UL ) ) ) ) )
# else
# else
while ( target_direction ? ( isHeatingHotend ( target_extruder ) ) : ( isCoolingHotend ( target_extruder ) & & ( CooldownNoWait = = false ) ) )
while ( target_direction ? ( isHeatingHotend ( target_extruder ) ) : ( isCoolingHotend ( target_extruder ) & & ( no_wait_for_cooling = = false ) ) )
# endif //TEMP_RESIDENCY_TIME
# endif //TEMP_RESIDENCY_TIME
{ // while loop
{ // while loop
@ -3258,7 +3318,7 @@ inline void gcode_M109() {
LCD_MESSAGEPGM ( MSG_HEATING_COMPLETE ) ;
LCD_MESSAGEPGM ( MSG_HEATING_COMPLETE ) ;
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
starttime = previous_cmd_ms ;
print_job_start_ms = previous_cmd_ms ;
}
}
# if HAS_TEMP_BED
# if HAS_TEMP_BED
@ -3269,8 +3329,8 @@ inline void gcode_M109() {
*/
*/
inline void gcode_M190 ( ) {
inline void gcode_M190 ( ) {
LCD_MESSAGEPGM ( MSG_BED_HEATING ) ;
LCD_MESSAGEPGM ( MSG_BED_HEATING ) ;
CooldownNoWait = code_seen ( ' S ' ) ;
no_wait_for_cooling = code_seen ( ' S ' ) ;
if ( CooldownNoWait | | code_seen ( ' R ' ) )
if ( no_wait_for_cooling | | code_seen ( ' R ' ) )
setTargetBed ( code_value ( ) ) ;
setTargetBed ( code_value ( ) ) ;
millis_t temp_ms = millis ( ) ;
millis_t temp_ms = millis ( ) ;
@ -3278,7 +3338,7 @@ inline void gcode_M109() {
cancel_heatup = false ;
cancel_heatup = false ;
target_direction = isHeatingBed ( ) ; // true if heating, false if cooling
target_direction = isHeatingBed ( ) ; // true if heating, false if cooling
while ( ( target_direction ) & & ( ! cancel_heatup ) ? ( isHeatingBed ( ) ) : ( isCoolingBed ( ) & & ( CooldownNoWait = = false ) ) ) {
while ( ( target_direction & & ! cancel_heatup ) ? isHeatingBed ( ) : isCoolingBed ( ) & & ! no_wait_for_cooling ) {
millis_t ms = millis ( ) ;
millis_t ms = millis ( ) ;
if ( ms > temp_ms + 1000UL ) { //Print Temp Reading every 1 second while heating up.
if ( ms > temp_ms + 1000UL ) { //Print Temp Reading every 1 second while heating up.
temp_ms = ms ;
temp_ms = ms ;
@ -3371,7 +3431,7 @@ inline void gcode_M140() {
* This code should ALWAYS be available for EMERGENCY SHUTDOWN !
* This code should ALWAYS be available for EMERGENCY SHUTDOWN !
*/
*/
inline void gcode_M81 ( ) {
inline void gcode_M81 ( ) {
disable_ heater( ) ;
disable_ all_ heaters ( ) ;
st_synchronize ( ) ;
st_synchronize ( ) ;
disable_e0 ( ) ;
disable_e0 ( ) ;
disable_e1 ( ) ;
disable_e1 ( ) ;
@ -3803,7 +3863,7 @@ inline void gcode_M206() {
default :
default :
SERIAL_ECHO_START ;
SERIAL_ECHO_START ;
SERIAL_ECHOPGM ( MSG_UNKNOWN_COMMAND ) ;
SERIAL_ECHOPGM ( MSG_UNKNOWN_COMMAND ) ;
SERIAL_ECHO ( c mdbuffer[ bufind r] ) ;
SERIAL_ECHO ( c ommand_queue[ cmd_queue_index_ r] ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
return ;
return ;
}
}
@ -3849,7 +3909,7 @@ inline void gcode_M206() {
* M220 : Set speed percentage factor , aka " Feed Rate " ( M220 S95 )
* M220 : Set speed percentage factor , aka " Feed Rate " ( M220 S95 )
*/
*/
inline void gcode_M220 ( ) {
inline void gcode_M220 ( ) {
if ( code_seen ( ' S ' ) ) feed multiply = code_value ( ) ;
if ( code_seen ( ' S ' ) ) feed rate_multiplier = code_value ( ) ;
}
}
/**
/**
@ -4485,7 +4545,7 @@ inline void gcode_M503() {
# endif
# endif
# ifdef FILAMENT_RUNOUT_SENSOR
# ifdef FILAMENT_RUNOUT_SENSOR
filrunoutEnque d = false ;
filrunoutEnque ue d = false ;
# endif
# endif
}
}
@ -4619,6 +4679,9 @@ inline void gcode_M999() {
FlushSerialRequestResend ( ) ;
FlushSerialRequestResend ( ) ;
}
}
/**
* T0 - T3 : Switch tool , usually switching extruders
*/
inline void gcode_T ( ) {
inline void gcode_T ( ) {
int tmp_extruder = code_value ( ) ;
int tmp_extruder = code_value ( ) ;
if ( tmp_extruder > = EXTRUDERS ) {
if ( tmp_extruder > = EXTRUDERS ) {
@ -5208,7 +5271,7 @@ void process_commands() {
else {
else {
SERIAL_ECHO_START ;
SERIAL_ECHO_START ;
SERIAL_ECHOPGM ( MSG_UNKNOWN_COMMAND ) ;
SERIAL_ECHOPGM ( MSG_UNKNOWN_COMMAND ) ;
SERIAL_ECHO ( c mdbuffer[ bufind r] ) ;
SERIAL_ECHO ( c ommand_queue[ cmd_queue_index_ r] ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
}
}
@ -5216,7 +5279,7 @@ void process_commands() {
}
}
void FlushSerialRequestResend ( ) {
void FlushSerialRequestResend ( ) {
//char c mdbuffer[bufind r][100]="Resend:";
//char c ommand_queue[cmd_queue_index_ r][100]="Resend:";
MYSERIAL . flush ( ) ;
MYSERIAL . flush ( ) ;
SERIAL_PROTOCOLPGM ( MSG_RESEND ) ;
SERIAL_PROTOCOLPGM ( MSG_RESEND ) ;
SERIAL_PROTOCOLLN ( gcode_LastN + 1 ) ;
SERIAL_PROTOCOLLN ( gcode_LastN + 1 ) ;
@ -5226,7 +5289,7 @@ void FlushSerialRequestResend() {
void ClearToSend ( ) {
void ClearToSend ( ) {
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
# ifdef SDSUPPORT
# ifdef SDSUPPORT
if ( fromsd [ bufind r] ) return ;
if ( fromsd [ cmd_queue_index_ r] ) return ;
# endif
# endif
SERIAL_PROTOCOLLNPGM ( MSG_OK ) ;
SERIAL_PROTOCOLLNPGM ( MSG_OK ) ;
}
}
@ -5470,7 +5533,7 @@ void prepare_move() {
float cartesian_mm = sqrt ( sq ( difference [ X_AXIS ] ) + sq ( difference [ Y_AXIS ] ) + sq ( difference [ Z_AXIS ] ) ) ;
float cartesian_mm = sqrt ( sq ( difference [ X_AXIS ] ) + sq ( difference [ Y_AXIS ] ) + sq ( difference [ Z_AXIS ] ) ) ;
if ( cartesian_mm < 0.000001 ) { cartesian_mm = abs ( difference [ E_AXIS ] ) ; }
if ( cartesian_mm < 0.000001 ) { cartesian_mm = abs ( difference [ E_AXIS ] ) ; }
if ( cartesian_mm < 0.000001 ) { return ; }
if ( cartesian_mm < 0.000001 ) { return ; }
float seconds = 6000 * cartesian_mm / feedrate / feed multiply ;
float seconds = 6000 * cartesian_mm / feedrate / feed rate_multiplier ;
int steps = max ( 1 , int ( scara_segments_per_second * seconds ) ) ;
int steps = max ( 1 , int ( scara_segments_per_second * seconds ) ) ;
//SERIAL_ECHOPGM("mm="); SERIAL_ECHO(cartesian_mm);
//SERIAL_ECHOPGM("mm="); SERIAL_ECHO(cartesian_mm);
@ -5489,7 +5552,7 @@ void prepare_move() {
//SERIAL_ECHOPGM("delta[Y_AXIS]="); SERIAL_ECHOLN(delta[Y_AXIS]);
//SERIAL_ECHOPGM("delta[Y_AXIS]="); SERIAL_ECHOLN(delta[Y_AXIS]);
//SERIAL_ECHOPGM("delta[Z_AXIS]="); SERIAL_ECHOLN(delta[Z_AXIS]);
//SERIAL_ECHOPGM("delta[Z_AXIS]="); SERIAL_ECHOLN(delta[Z_AXIS]);
plan_buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , destination [ E_AXIS ] , feedrate / 60 * feed multiply / 100.0 , active_extruder ) ;
plan_buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , destination [ E_AXIS ] , feedrate / 60 * feed rate_multiplier / 100.0 , active_extruder ) ;
}
}
# endif // SCARA
# endif // SCARA
@ -5502,7 +5565,7 @@ void prepare_move() {
float cartesian_mm = sqrt ( sq ( difference [ X_AXIS ] ) + sq ( difference [ Y_AXIS ] ) + sq ( difference [ Z_AXIS ] ) ) ;
float cartesian_mm = sqrt ( sq ( difference [ X_AXIS ] ) + sq ( difference [ Y_AXIS ] ) + sq ( difference [ Z_AXIS ] ) ) ;
if ( cartesian_mm < 0.000001 ) cartesian_mm = abs ( difference [ E_AXIS ] ) ;
if ( cartesian_mm < 0.000001 ) cartesian_mm = abs ( difference [ E_AXIS ] ) ;
if ( cartesian_mm < 0.000001 ) return ;
if ( cartesian_mm < 0.000001 ) return ;
float seconds = 6000 * cartesian_mm / feedrate / feed multiply ;
float seconds = 6000 * cartesian_mm / feedrate / feed rate_multiplier ;
int steps = max ( 1 , int ( delta_segments_per_second * seconds ) ) ;
int steps = max ( 1 , int ( delta_segments_per_second * seconds ) ) ;
// SERIAL_ECHOPGM("mm="); SERIAL_ECHO(cartesian_mm);
// SERIAL_ECHOPGM("mm="); SERIAL_ECHO(cartesian_mm);
@ -5516,7 +5579,7 @@ void prepare_move() {
# ifdef ENABLE_AUTO_BED_LEVELING
# ifdef ENABLE_AUTO_BED_LEVELING
adjust_delta ( destination ) ;
adjust_delta ( destination ) ;
# endif
# endif
plan_buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , destination [ E_AXIS ] , feedrate / 60 * feed multiply / 100.0 , active_extruder ) ;
plan_buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , destination [ E_AXIS ] , feedrate / 60 * feed rate_multiplier / 100.0 , active_extruder ) ;
}
}
# endif // DELTA
# endif // DELTA
@ -5556,16 +5619,16 @@ void prepare_move() {
# endif // DUAL_X_CARRIAGE
# endif // DUAL_X_CARRIAGE
# if !defined(DELTA) && !defined(SCARA)
# if !defined(DELTA) && !defined(SCARA)
// Do not use feed multiply for E or Z only moves
// Do not use feed rate_multiplier for E or Z only moves
if ( current_position [ X_AXIS ] = = destination [ X_AXIS ] & & current_position [ Y_AXIS ] = = destination [ Y_AXIS ] ) {
if ( current_position [ X_AXIS ] = = destination [ X_AXIS ] & & current_position [ Y_AXIS ] = = destination [ Y_AXIS ] ) {
line_to_destination ( ) ;
line_to_destination ( ) ;
}
}
else {
else {
# ifdef MESH_BED_LEVELING
# ifdef MESH_BED_LEVELING
mesh_plan_buffer_line ( destination [ X_AXIS ] , destination [ Y_AXIS ] , destination [ Z_AXIS ] , destination [ E_AXIS ] , ( feedrate / 60 ) * ( feed multiply / 100.0 ) , active_extruder ) ;
mesh_plan_buffer_line ( destination [ X_AXIS ] , destination [ Y_AXIS ] , destination [ Z_AXIS ] , destination [ E_AXIS ] , ( feedrate / 60 ) * ( feed rate_multiplier / 100.0 ) , active_extruder ) ;
return ;
return ;
# else
# else
line_to_destination ( feedrate * feed multiply / 100.0 ) ;
line_to_destination ( feedrate * feed rate_multiplier / 100.0 ) ;
# endif // MESH_BED_LEVELING
# endif // MESH_BED_LEVELING
}
}
# endif // !(DELTA || SCARA)
# endif // !(DELTA || SCARA)
@ -5577,7 +5640,7 @@ void prepare_arc_move(char isclockwise) {
float r = hypot ( offset [ X_AXIS ] , offset [ Y_AXIS ] ) ; // Compute arc radius for mc_arc
float r = hypot ( offset [ X_AXIS ] , offset [ Y_AXIS ] ) ; // Compute arc radius for mc_arc
// Trace the arc
// Trace the arc
mc_arc ( current_position , destination , offset , X_AXIS , Y_AXIS , Z_AXIS , feedrate * feed multiply / 60 / 100.0 , r , isclockwise , active_extruder ) ;
mc_arc ( current_position , destination , offset , X_AXIS , Y_AXIS , Z_AXIS , feedrate * feed rate_multiplier / 60 / 100.0 , r , isclockwise , active_extruder ) ;
// As far as the parser is concerned, the position is now == target. In reality the
// As far as the parser is concerned, the position is now == target. In reality the
// motion control system might still be processing the action and the real tool position
// motion control system might still be processing the action and the real tool position
@ -5762,7 +5825,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
filrunout ( ) ;
filrunout ( ) ;
# endif
# endif
if ( buflen < BUFSIZE - 1 ) get_command ( ) ;
if ( commands_in_queue < BUFSIZE - 1 ) get_command ( ) ;
millis_t ms = millis ( ) ;
millis_t ms = millis ( ) ;
@ -5898,7 +5961,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
void kill ( )
void kill ( )
{
{
cli ( ) ; // Stop interrupts
cli ( ) ; // Stop interrupts
disable_ heater( ) ;
disable_ all_ heaters ( ) ;
disable_all_steppers ( ) ;
disable_all_steppers ( ) ;
@ -5919,18 +5982,18 @@ void kill()
}
}
# ifdef FILAMENT_RUNOUT_SENSOR
# ifdef FILAMENT_RUNOUT_SENSOR
void filrunout ( )
{
void filrunout ( ) {
if ( filrunoutEnqued = = false ) {
if ( ! filrunoutEnqueued ) {
filrunoutEnqued = true ;
filrunoutEnqueued = true ;
enqueuecommand ( " M600 " ) ;
enqueuecommand ( " M600 " ) ;
}
}
}
}
# endif
# endif
void Stop ( )
void Stop ( ) {
{
disable_all_heaters ( ) ;
disable_heater ( ) ;
if ( IsRunning ( ) ) {
if ( IsRunning ( ) ) {
Running = false ;
Running = false ;
Stopped_gcode_LastN = gcode_LastN ; // Save last g_code for restart
Stopped_gcode_LastN = gcode_LastN ; // Save last g_code for restart