@ -276,9 +276,7 @@ const char echomagic[] PROGMEM = "echo:";
const char axis_codes [ NUM_AXIS ] = { ' X ' , ' Y ' , ' Z ' , ' E ' } ;
const char axis_codes [ NUM_AXIS ] = { ' X ' , ' Y ' , ' Z ' , ' E ' } ;
static bool relative_mode = false ; //Determines Absolute or Relative Coordinates
static bool relative_mode = false ; //Determines Absolute or Relative Coordinates
static char serial_char ;
static int serial_count = 0 ;
static int serial_count = 0 ;
static boolean comment_mode = false ;
static char * seen_pointer ; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
static char * seen_pointer ; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
const char * queued_commands_P = NULL ; /* pointer to the current line in the active sequence of commands, or NULL when none */
const char * queued_commands_P = NULL ; /* pointer to the current line in the active sequence of commands, or NULL when none */
const int sensitive_pins [ ] = SENSITIVE_PINS ; ///< Sensitive pin list for M42
const int sensitive_pins [ ] = SENSITIVE_PINS ; ///< Sensitive pin list for M42
@ -409,9 +407,7 @@ static uint8_t target_extruder;
static bool filrunoutEnqueued = false ;
static bool filrunoutEnqueued = false ;
# endif
# endif
# if ENABLED(SDSUPPORT)
static bool send_ok [ BUFSIZE ] ;
static bool fromsd [ BUFSIZE ] ;
# endif
# if HAS_SERVOS
# if HAS_SERVOS
Servo servo [ NUM_SERVOS ] ;
Servo servo [ NUM_SERVOS ] ;
@ -483,7 +479,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 ( enqueue command( cmd ) ) { // buffer was not full (else we will retry later)
if ( enqueue _and_echo_ command( 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
@ -497,32 +493,45 @@ static bool drain_queued_commands_P() {
* Aborts the current queue , if any .
* Aborts the current queue , if any .
* Note : drain_queued_commands_P ( ) must be called repeatedly to drain the commands afterwards
* Note : drain_queued_commands_P ( ) must be called repeatedly to drain the commands afterwards
*/
*/
void enqueue commands_P( const char * pgcode ) {
void enqueue _and_echo_ commands_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)
}
}
/**
/**
* Copy a command directly into the main command buffer , from RAM .
* Once a new command is in the ring buffer , call this to commit it
*
* This is done in a non - safe way and needs a rework someday .
* Returns false if it doesn ' t add any command
*/
*/
bool enqueuecommand ( const char * cmd ) {
inline void _commit_command ( bool say_ok ) {
if ( * cmd = = ' ; ' | | commands_in_queue > = BUFSIZE ) return false ;
send_ok [ cmd_queue_index_w ] = say_ok ;
// This is dangerous if a mixing of serial and this happens
char * command = command_queue [ cmd_queue_index_w ] ;
strcpy ( command , cmd ) ;
SERIAL_ECHO_START ;
SERIAL_ECHOPGM ( MSG_Enqueueing ) ;
SERIAL_ECHO ( command ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
cmd_queue_index_w = ( cmd_queue_index_w + 1 ) % BUFSIZE ;
cmd_queue_index_w = ( cmd_queue_index_w + 1 ) % BUFSIZE ;
commands_in_queue + + ;
commands_in_queue + + ;
}
/**
* Copy a command directly into the main command buffer , from RAM .
* Returns true if successfully adds the command
*/
inline bool _enqueuecommand ( const char * cmd , bool say_ok = false ) {
if ( * cmd = = ' ; ' | | commands_in_queue > = BUFSIZE ) return false ;
strcpy ( command_queue [ cmd_queue_index_w ] , cmd ) ;
_commit_command ( say_ok ) ;
return true ;
return true ;
}
}
/**
* Enqueue with Serial Echo
*/
bool enqueue_and_echo_command ( const char * cmd , bool say_ok /*=false*/ ) {
if ( _enqueuecommand ( cmd , say_ok ) ) {
SERIAL_ECHO_START ;
SERIAL_ECHOPGM ( MSG_Enqueueing ) ;
SERIAL_ECHO ( cmd ) ;
SERIAL_ECHOLNPGM ( " \" " ) ;
return true ;
}
return false ;
}
void setup_killpin ( ) {
void setup_killpin ( ) {
# if HAS_KILL
# if HAS_KILL
SET_INPUT ( KILL_PIN ) ;
SET_INPUT ( KILL_PIN ) ;
@ -679,9 +688,8 @@ void setup() {
SERIAL_ECHOPGM ( MSG_PLANNER_BUFFER_BYTES ) ;
SERIAL_ECHOPGM ( MSG_PLANNER_BUFFER_BYTES ) ;
SERIAL_ECHOLN ( ( int ) sizeof ( block_t ) * BLOCK_BUFFER_SIZE ) ;
SERIAL_ECHOLN ( ( int ) sizeof ( block_t ) * BLOCK_BUFFER_SIZE ) ;
# if ENABLED(SDSUPPORT)
// Send "ok" after commands by default
for ( int8_t i = 0 ; i < BUFSIZE ; i + + ) fromsd [ i ] = false ;
for ( int8_t i = 0 ; i < BUFSIZE ; i + + ) send_ok [ i ] = true ;
# 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 ( ) ;
@ -740,7 +748,7 @@ void setup() {
* - Call LCD update
* - Call LCD update
*/
*/
void loop ( ) {
void loop ( ) {
if ( commands_in_queue < BUFSIZE - 1 ) get_command ( ) ;
if ( commands_in_queue < BUFSIZE ) get_command ( ) ;
# if ENABLED(SDSUPPORT)
# if ENABLED(SDSUPPORT)
card . checkautostart ( false ) ;
card . checkautostart ( false ) ;
@ -800,9 +808,12 @@ void gcode_line_error(const char* err, bool doFlush = true) {
*/
*/
void get_command ( ) {
void get_command ( ) {
static char serial_line_buffer [ MAX_CMD_SIZE ] ;
static boolean serial_comment_mode = false ;
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
# if ENABLED(NO_TIMEOUTS)
# if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
static millis_t last_command_time = 0 ;
static millis_t last_command_time = 0 ;
millis_t ms = millis ( ) ;
millis_t ms = millis ( ) ;
@ -817,29 +828,21 @@ void get_command() {
//
//
while ( commands_in_queue < BUFSIZE & & MYSERIAL . available ( ) > 0 ) {
while ( commands_in_queue < BUFSIZE & & MYSERIAL . available ( ) > 0 ) {
# if ENABLED(NO_TIMEOUTS)
char serial_char = MYSERIAL . read ( ) ;
last_command_time = ms ;
# endif
serial_char = MYSERIAL . read ( ) ;
//
//
// If the character ends the line , or the line is full...
// If the character ends the line
//
//
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' | | serial_count > = MAX_CMD_SIZE - 1 ) {
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' ) {
// end of line == end of comment
serial_comment_mode = false ; // end of line == end of comment
comment_mode = false ;
if ( ! serial_count ) return ; // empty lines just exit
if ( ! serial_count ) return ; // empty lines just exit
char * command = command_queue [ cmd_queue_index_w ] ;
serial_line_buffer [ serial_count ] = 0 ; // terminate string
command[ serial_count] = 0 ; // te rminat e string
serial_count = 0 ; // rese t buffe r
// this item in the queue is not from sd
char * command = serial_line_buffer ;
# if ENABLED(SDSUPPORT)
fromsd [ cmd_queue_index_w ] = false ;
# endif
while ( * command = = ' ' ) command + + ; // skip any leading spaces
while ( * command = = ' ' ) command + + ; // skip any leading spaces
char * npos = ( * command = = ' N ' ) ? command : NULL ; // Require the N parameter to start the line
char * npos = ( * command = = ' N ' ) ? command : NULL ; // Require the N parameter to start the line
@ -904,44 +907,56 @@ void get_command() {
// If command was e-stop process now
// If command was e-stop process now
if ( strcmp ( command , " M112 " ) = = 0 ) kill ( PSTR ( MSG_KILLED ) ) ;
if ( strcmp ( command , " M112 " ) = = 0 ) kill ( PSTR ( MSG_KILLED ) ) ;
cmd_queue_index_w = ( cmd_queue_index_w + 1 ) % BUFSIZE ;
# if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
commands_in_queue + = 1 ;
last_command_time = ms ;
# endif
serial_count = 0 ; //clear buffer
// Add the command to the queue
_enqueuecommand ( serial_line_buffer , true ) ;
}
else if ( serial_count > = MAX_CMD_SIZE - 1 ) {
// Keep fetching, but ignore normal characters beyond the max length
// The command will be injected when EOL is reached
}
}
else if ( serial_char = = ' \\ ' ) { // Handle escapes
else if ( serial_char = = ' \\ ' ) { // Handle escapes
if ( MYSERIAL . available ( ) > 0 & & commands_in_queue < BUFSIZE ) {
if ( MYSERIAL . available ( ) > 0 ) {
// 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 ( ) ;
command_queue[ cmd_queue_index_w ] [ serial_count + + ] = serial_char ;
serial_line_buffer [ serial_count + + ] = serial_char ;
}
}
// otherwise do nothing
// otherwise do nothing
}
}
else { // it s not a newline, carriage return or escape char
else { // it ' s not a newline, carriage return or escape char
if ( serial_char = = ' ; ' ) comment_mode = true ;
if ( serial_char = = ' ; ' ) serial_ comment_mode = true ;
if ( ! comment_mode) command_queue [ cmd_queue_index_w ] [ serial_count + + ] = serial_char ;
if ( ! serial_comment_mode) serial_line_buffer [ serial_count + + ] = serial_char ;
}
}
}
} // queue has space, serial has data
# if ENABLED(SDSUPPORT)
# if ENABLED(SDSUPPORT)
if ( ! card . sdprinting | | serial_count ) return ;
static bool stop_buffering = false ,
sd_comment_mode = false ;
if ( ! card . sdprinting ) return ;
// '#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
// '#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
// if it occurs, stop_buffering is triggered and the buffer is ran dry.
// if it occurs, stop_buffering is triggered and the buffer is r u n dry.
// 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 ;
if ( commands_in_queue = = 0 ) stop_buffering = false ;
if ( commands_in_queue = = 0 ) stop_buffering = false ;
while ( ! card . eof ( ) & & commands_in_queue < BUFSIZE & & ! stop_buffering ) {
uint16_t sd_count = 0 ;
bool card_eof = card . eof ( ) ;
while ( commands_in_queue < BUFSIZE & & ! card_eof & & ! stop_buffering ) {
int16_t n = card . get ( ) ;
int16_t n = card . get ( ) ;
serial_char = ( char ) n ;
char sd_char = ( char ) n ;
if ( serial_char = = ' \n ' | | serial_char = = ' \r ' | |
card_eof = card . eof ( ) ;
( ( serial_char = = ' # ' | | serial_char = = ' : ' ) & & ! comment_mode ) | |
if ( card_eof | | n = = - 1
serial_count > = ( MAX_CMD_SIZE - 1 ) | | n = = - 1
| | sd_char = = ' \n ' | | sd_char = = ' \r '
| | ( ( sd_char = = ' # ' | | sd_char = = ' : ' ) & & ! sd_comment_mode )
) {
) {
if ( card . eof ( ) ) {
if ( card _eof ) {
SERIAL_PROTOCOLLNPGM ( MSG_FILE_PRINTED ) ;
SERIAL_PROTOCOLLNPGM ( MSG_FILE_PRINTED ) ;
print_job_stop_ms = millis ( ) ;
print_job_stop_ms = millis ( ) ;
char time [ 30 ] ;
char time [ 30 ] ;
@ -954,24 +969,24 @@ void get_command() {
card . printingHasFinished ( ) ;
card . printingHasFinished ( ) ;
card . checkautostart ( true ) ;
card . checkautostart ( true ) ;
}
}
if ( s erial _char = = ' # ' ) stop_buffering = true ;
if ( s d _char = = ' # ' ) stop_buffering = true ;
if ( ! serial_count ) {
sd_comment_mode = false ; //for new command
comment_mode = false ; //for new command
return ; //if empty line
if ( ! sd_count ) continue ; //skip empty lines
}
command_queue [ cmd_queue_index_w ] [ s erial_count] = 0 ; //terminate string
command_queue [ cmd_queue_index_w ] [ s d_count] = ' \0 ' ; //terminate string
// if (!comment_mode) {
sd_count = 0 ; //clear buffer
fromsd [ cmd_queue_index_w ] = true ;
commands_in_queue + = 1 ;
_commit_command( false ) ;
cmd_queue_index_w = ( cmd_queue_index_w + 1 ) % BUFSIZE ;
}
// }
else if ( sd_count > = MAX_CMD_SIZE - 1 ) {
comment_mode = false ; //for new command
// Keep fetching, but ignore normal characters beyond the max length
serial_count = 0 ; //clear buffer
// The command will be injected when EOL is reached
}
}
else {
else {
if ( s erial _char = = ' ; ' ) comment_mode = true ;
if ( s d _char = = ' ; ' ) sd_ comment_mode = true ;
if ( ! comment_mode) command_queue [ cmd_queue_index_w ] [ s erial_count+ + ] = serial _char;
if ( ! sd_ comment_mode) command_queue [ cmd_queue_index_w ] [ s d_count+ + ] = sd _char;
}
}
}
}
@ -2654,7 +2669,7 @@ inline void gcode_G28() {
case MeshStart :
case MeshStart :
mbl . reset ( ) ;
mbl . reset ( ) ;
probe_point = 0 ;
probe_point = 0 ;
enqueue commands_P( PSTR ( " G28 \n G29 S2 " ) ) ;
enqueue _and_echo_ commands_P( PSTR ( " G28 \n G29 S2 " ) ) ;
break ;
break ;
case MeshNext :
case MeshNext :
@ -2693,7 +2708,7 @@ inline void gcode_G28() {
SERIAL_PROTOCOLLNPGM ( " Mesh probing done. " ) ;
SERIAL_PROTOCOLLNPGM ( " Mesh probing done. " ) ;
probe_point = - 1 ;
probe_point = - 1 ;
mbl . active = 1 ;
mbl . active = 1 ;
enqueue commands_P( PSTR ( " G28 " ) ) ;
enqueue _and_echo_ commands_P( PSTR ( " G28 " ) ) ;
}
}
break ;
break ;
@ -3215,7 +3230,7 @@ inline void gcode_G28() {
SERIAL_ECHOLNPGM ( Z_PROBE_END_SCRIPT ) ;
SERIAL_ECHOLNPGM ( Z_PROBE_END_SCRIPT ) ;
}
}
# endif
# endif
enqueue commands_P( PSTR ( Z_PROBE_END_SCRIPT ) ) ;
enqueue _and_echo_ commands_P( PSTR ( Z_PROBE_END_SCRIPT ) ) ;
st_synchronize ( ) ;
st_synchronize ( ) ;
# endif
# endif
@ -3374,7 +3389,7 @@ inline void gcode_M17() {
}
}
/**
/**
* M23 : Select a file
* M23 : Open a file
*/
*/
inline void gcode_M23 ( ) {
inline void gcode_M23 ( ) {
card . openFile ( current_command_args , true ) ;
card . openFile ( current_command_args , true ) ;
@ -5244,7 +5259,7 @@ inline void gcode_M428() {
SERIAL_ERRORLNPGM ( MSG_ERR_M428_TOO_FAR ) ;
SERIAL_ERRORLNPGM ( MSG_ERR_M428_TOO_FAR ) ;
LCD_ALERTMESSAGEPGM ( " Err: Too far! " ) ;
LCD_ALERTMESSAGEPGM ( " Err: Too far! " ) ;
# if HAS_BUZZER
# if HAS_BUZZER
enqueue commands_P( PSTR ( " M300 S40 P200 " ) ) ;
enqueue _and_echo_ commands_P( PSTR ( " M300 S40 P200 " ) ) ;
# endif
# endif
err = true ;
err = true ;
break ;
break ;
@ -5258,7 +5273,7 @@ inline void gcode_M428() {
sync_plan_position ( ) ;
sync_plan_position ( ) ;
LCD_ALERTMESSAGEPGM ( " Offset applied. " ) ;
LCD_ALERTMESSAGEPGM ( " Offset applied. " ) ;
# if HAS_BUZZER
# if HAS_BUZZER
enqueue commands_P( PSTR ( " M300 S659 P200 \n M300 S698 P200 " ) ) ;
enqueue _and_echo_ commands_P( PSTR ( " M300 S659 P200 \n M300 S698 P200 " ) ) ;
# endif
# endif
}
}
}
}
@ -6304,9 +6319,7 @@ void FlushSerialRequestResend() {
void ok_to_send ( ) {
void ok_to_send ( ) {
refresh_cmd_timeout ( ) ;
refresh_cmd_timeout ( ) ;
# if ENABLED(SDSUPPORT)
if ( ! send_ok [ cmd_queue_index_r ] ) return ;
if ( fromsd [ cmd_queue_index_r ] ) return ;
# endif
SERIAL_PROTOCOLPGM ( MSG_OK ) ;
SERIAL_PROTOCOLPGM ( MSG_OK ) ;
# if ENABLED(ADVANCED_OK)
# if ENABLED(ADVANCED_OK)
char * p = command_queue [ cmd_queue_index_r ] ;
char * p = command_queue [ cmd_queue_index_r ] ;
@ -6997,7 +7010,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
filrunout ( ) ;
filrunout ( ) ;
# endif
# endif
if ( commands_in_queue < BUFSIZE - 1 ) get_command ( ) ;
if ( commands_in_queue < BUFSIZE ) get_command ( ) ;
millis_t ms = millis ( ) ;
millis_t ms = millis ( ) ;
@ -7054,7 +7067,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
const int HOME_DEBOUNCE_DELAY = 2500 ;
const int HOME_DEBOUNCE_DELAY = 2500 ;
if ( ! READ ( HOME_PIN ) ) {
if ( ! READ ( HOME_PIN ) ) {
if ( ! homeDebounceCount ) {
if ( ! homeDebounceCount ) {
enqueue commands_P( PSTR ( " G28 " ) ) ;
enqueue _and_echo_ commands_P( PSTR ( " G28 " ) ) ;
LCD_MESSAGEPGM ( MSG_AUTO_HOME ) ;
LCD_MESSAGEPGM ( MSG_AUTO_HOME ) ;
}
}
if ( homeDebounceCount < HOME_DEBOUNCE_DELAY )
if ( homeDebounceCount < HOME_DEBOUNCE_DELAY )
@ -7180,7 +7193,7 @@ void kill(const char* lcd_msg) {
void filrunout ( ) {
void filrunout ( ) {
if ( ! filrunoutEnqueued ) {
if ( ! filrunoutEnqueued ) {
filrunoutEnqueued = true ;
filrunoutEnqueued = true ;
enqueue commands_P( PSTR ( FILAMENT_RUNOUT_SCRIPT ) ) ;
enqueue _and_echo_ commands_P( PSTR ( FILAMENT_RUNOUT_SCRIPT ) ) ;
st_synchronize ( ) ;
st_synchronize ( ) ;
}
}
}
}