From c7db1c4546665174adad0664b73d6792a2a6dfb1 Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Mon, 23 Feb 2015 18:45:26 -0700 Subject: [PATCH] New configuration options. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New configuration option at compile-time: - Force alarm upon power-up or hard reset. When homing is enabled, this is already the default behavior. This simply forces this all of the time. - GUI reporting mode. Removes most human-readable strings that GUIs don’t need. This saves nearly 2KB in flash space that can be used for other features. - Hard limit force state check: In the hard limit pin change ISR, Grbl by default sets the hard limit alarm upon any pin change to guarantee the alarm is set. If this option is set, it’ll check the state within the ISR, but can’t guarantee the pin will be read correctly if the switch is bouncing. This option makes hard limit behavior a little less annoying if you have a good buffered switch circuit that removes bouncing and electronic noise. - Software debounce bug fix. It was reading the pin incorrectly for the setting. - Re-factored some of the ‘$’ settings code. --- grbl/config.h | 34 ++++++- grbl/grbl.h | 4 +- grbl/limits.c | 20 +++-- grbl/main.c | 5 ++ grbl/report.c | 239 +++++++++++++++++++++++++++++--------------------- grbl/system.c | 97 ++++++++++---------- 6 files changed, 240 insertions(+), 159 deletions(-) diff --git a/grbl/config.h b/grbl/config.h index e51b27c..297742e 100644 --- a/grbl/config.h +++ b/grbl/config.h @@ -106,8 +106,8 @@ // this feature. Since the two switches are sharing a single pin, there is no way for Grbl to tell // which one is enabled. This option only effects homing, where if a limit is engaged, Grbl will // alarm out and force the user to manually disengage the limit switch. Otherwise, if you have one -// limit switch for each axis, don't enable this option. By keeping it disabled, you can homing while -// on the limit switch and not have to move the machine off of it. +// limit switch for each axis, don't enable this option. By keeping it disabled, you can perform a +// homing cycle while on the limit switch and not have to move the machine off of it. // #define LIMITS_TWO_SWITCHES_ON_AXES // Allows GRBL to track and report gcode line numbers. Enabling this means that the planning buffer @@ -161,9 +161,22 @@ // with little to no benefit during normal operation. // #define REPORT_INPUT_PIN_STATES // Default disabled. Uncomment to enable. +// When Grbl powers-cycles or is hard reset with the Arduino reset button, Grbl boots up with no ALARM +// by default. This is to make it as simple as possible for new users to start using Grbl. When homing +// is enabled and a user has installed limit switches, Grbl will boot up in an ALARM state to indicate +// Grbl doesn't know its position and to force the user to home before proceeding. This option forces +// Grbl to always initialize into an ALARM state regardless of homing or not. This option is more for +// OEMs and LinuxCNC users that would like this power-cycle behavior. +// #define FORCE_INITIALIZATION_ALARM // Default disabled. Uncomment to enable. + // --------------------------------------------------------------------------------------- // ADVANCED CONFIGURATION OPTIONS: +// Enables minimal reporting feedback mode for GUIs, where human-readable strings are not as important. +// This saves nearly 2KB of flash space and may allow enough space to install other/future features. +// NOTE: This feature is new and experimental. Make sure the GUI you are using supports this mode. +#define REPORT_GUI_MODE // Default disabled. Uncomment to enable. + // The temporal resolution of the acceleration management subsystem. A higher number gives smoother // acceleration, particularly noticeable on machines that run at very high feedrates, but may negatively // impact performance. The correct value for this parameter is machine dependent, so it's advised to @@ -180,8 +193,10 @@ // step smoothing. See stepper.c for more details on the AMASS system works. #define ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING // Default enabled. Comment to disable. -// Sets the maximum step rate allowed to be written as a Grbl setting. This value is strictly limited -// by the CPU speed and will change if something other than an AVR running at 16MHz is used. +// Sets the maximum step rate allowed to be written as a Grbl setting. This option enables an error +// check in the settings module to prevent settings values that will exceed this limitation. The maximum +// step rate is strictly limited by the CPU speed and will change if something other than an AVR running +// at 16MHz is used. // NOTE: For now disabled, will enable if flash space permits. // #define MAX_STEP_RATE_HZ 30000 // Hz @@ -318,6 +333,17 @@ // work well and are cheap to find) and wire in a low-pass circuit into each limit pin. // #define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable. +// Force Grbl to check the state of the hard limit switches when the processor detects a pin +// change inside the hard limit ISR routine. By default, Grbl will trigger the hard limits +// alarm upon any pin change, since bouncing switches can cause a state check like this to +// misread the pin. When hard limits are triggers, this should be 100% reliable, which is the +// reason that this option is disabled by default. Only if your system/electronics can guarantee +// the pins don't bounce, we recommend enabling this option. If so, this will help prevent +// triggering a hard limit when the machine disengages from the switch. +// NOTE: This option has no effect if SOFTWARE_DEBOUNCE is enabled. +// #define HARD_LIMIT_FORCE_STATE_CHECK // Default disabled. Uncomment to enable. + + // --------------------------------------------------------------------------------------- // TODO: Install compile-time option to send numeric status codes rather than strings. diff --git a/grbl/grbl.h b/grbl/grbl.h index 08e7dd7..ff92269 100644 --- a/grbl/grbl.h +++ b/grbl/grbl.h @@ -22,8 +22,8 @@ #define grbl_h // Grbl versioning system -#define GRBL_VERSION "0.9h" -#define GRBL_VERSION_BUILD "20150215" +#define GRBL_VERSION "0.9i" +#define GRBL_VERSION_BUILD "20150223" // Define standard libraries used by Grbl. #include diff --git a/grbl/limits.c b/grbl/limits.c index 6f00b06..75b9f82 100644 --- a/grbl/limits.c +++ b/grbl/limits.c @@ -79,8 +79,18 @@ void limits_disable() // limit setting if their limits are constantly triggering after a reset and move their axes. if (sys.state != STATE_ALARM) { if (!(sys.rt_exec_alarm)) { - mc_reset(); // Initiate system kill. - bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event + #ifdef HARD_LIMIT_FORCE_STATE_CHECK + uint8_t bits = (LIMIT_PIN & LIMIT_MASK); + // Check limit pin state. + if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; } + if (bits) { + mc_reset(); // Initiate system kill. + bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event + } + #else + mc_reset(); // Initiate system kill. + bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event + #endif } } } @@ -92,10 +102,10 @@ void limits_disable() WDTCSR &= ~(1< 30kHz")); break; + #ifdef REPORT_GUI_MODE + print_uint8_base10(status_code); + #else + switch(status_code) { + case STATUS_EXPECTED_COMMAND_LETTER: + printPgmString(PSTR("Expected command letter")); break; + case STATUS_BAD_NUMBER_FORMAT: + printPgmString(PSTR("Bad number format")); break; + case STATUS_INVALID_STATEMENT: + printPgmString(PSTR("Invalid statement")); break; + case STATUS_NEGATIVE_VALUE: + printPgmString(PSTR("Value < 0")); break; + case STATUS_SETTING_DISABLED: + printPgmString(PSTR("Setting disabled")); break; + case STATUS_SETTING_STEP_PULSE_MIN: + printPgmString(PSTR("Value < 3 usec")); break; + case STATUS_SETTING_READ_FAIL: + printPgmString(PSTR("EEPROM read fail. Using defaults")); break; + case STATUS_IDLE_ERROR: + printPgmString(PSTR("Not idle")); break; + case STATUS_ALARM_LOCK: + printPgmString(PSTR("Alarm lock")); break; + case STATUS_SOFT_LIMIT_ERROR: + printPgmString(PSTR("Homing not enabled")); break; + case STATUS_OVERFLOW: + printPgmString(PSTR("Line overflow")); break; + // case STATUS_MAX_STEP_RATE_EXCEEDED: + // printPgmString(PSTR("Step rate > 30kHz")); break; - // Common g-code parser errors. - case STATUS_GCODE_MODAL_GROUP_VIOLATION: - printPgmString(PSTR("Modal group violation")); break; - case STATUS_GCODE_UNSUPPORTED_COMMAND: - printPgmString(PSTR("Unsupported command")); break; - case STATUS_GCODE_UNDEFINED_FEED_RATE: - printPgmString(PSTR("Undefined feed rate")); break; - default: - // Remaining g-code parser errors with error codes - printPgmString(PSTR("Invalid gcode ID:")); - print_uint8_base10(status_code); // Print error code for user reference - } + // Common g-code parser errors. + case STATUS_GCODE_MODAL_GROUP_VIOLATION: + printPgmString(PSTR("Modal group violation")); break; + case STATUS_GCODE_UNSUPPORTED_COMMAND: + printPgmString(PSTR("Unsupported command")); break; + case STATUS_GCODE_UNDEFINED_FEED_RATE: + printPgmString(PSTR("Undefined feed rate")); break; + default: + // Remaining g-code parser errors with error codes + printPgmString(PSTR("Invalid gcode ID:")); + print_uint8_base10(status_code); // Print error code for user reference + } + #endif printPgmString(PSTR("\r\n")); } } @@ -89,18 +93,22 @@ void report_status_message(uint8_t status_code) void report_alarm_message(int8_t alarm_code) { printPgmString(PSTR("ALARM: ")); - switch (alarm_code) { - case ALARM_HARD_LIMIT_ERROR: - printPgmString(PSTR("Hard limit")); break; - case ALARM_SOFT_LIMIT_ERROR: - printPgmString(PSTR("Soft limit")); break; - case ALARM_ABORT_CYCLE: - printPgmString(PSTR("Abort during cycle")); break; - case ALARM_PROBE_FAIL: - printPgmString(PSTR("Probe fail")); break; - case ALARM_HOMING_FAIL: - printPgmString(PSTR("Homing fail")); break; - } + #ifdef REPORT_GUI_MODE + print_uint8_base10(alarm_code); + #else + switch (alarm_code) { + case ALARM_HARD_LIMIT_ERROR: + printPgmString(PSTR("Hard limit")); break; + case ALARM_SOFT_LIMIT_ERROR: + printPgmString(PSTR("Soft limit")); break; + case ALARM_ABORT_CYCLE: + printPgmString(PSTR("Abort during cycle")); break; + case ALARM_PROBE_FAIL: + printPgmString(PSTR("Probe fail")); break; + case ALARM_HOMING_FAIL: + printPgmString(PSTR("Homing fail")); break; + } + #endif printPgmString(PSTR("\r\n")); delay_ms(500); // Force delay to ensure message clears serial write buffer. } @@ -140,20 +148,22 @@ void report_init_message() // Grbl help message void report_grbl_help() { - printPgmString(PSTR("$$ (view Grbl settings)\r\n" - "$# (view # parameters)\r\n" - "$G (view parser state)\r\n" - "$I (view build info)\r\n" - "$N (view startup blocks)\r\n" - "$x=value (save Grbl setting)\r\n" - "$Nx=line (save startup block)\r\n" - "$C (check gcode mode)\r\n" - "$X (kill alarm lock)\r\n" - "$H (run homing cycle)\r\n" - "~ (cycle start)\r\n" - "! (feed hold)\r\n" - "? (current status)\r\n" - "ctrl-x (reset Grbl)\r\n")); + #ifndef REPORT_GUI_MODE + printPgmString(PSTR("$$ (view Grbl settings)\r\n" + "$# (view # parameters)\r\n" + "$G (view parser state)\r\n" + "$I (view build info)\r\n" + "$N (view startup blocks)\r\n" + "$x=value (save Grbl setting)\r\n" + "$Nx=line (save startup block)\r\n" + "$C (check gcode mode)\r\n" + "$X (kill alarm lock)\r\n" + "$H (run homing cycle)\r\n" + "~ (cycle start)\r\n" + "! (feed hold)\r\n" + "? (current status)\r\n" + "ctrl-x (reset Grbl)\r\n")); + #endif } @@ -161,31 +171,54 @@ void report_grbl_help() { // NOTE: The numbering scheme here must correlate to storing in settings.c void report_grbl_settings() { // Print Grbl settings. - printPgmString(PSTR("$0=")); print_uint8_base10(settings.pulse_microseconds); - printPgmString(PSTR(" (step pulse, usec)\r\n$1=")); print_uint8_base10(settings.stepper_idle_lock_time); - printPgmString(PSTR(" (step idle delay, msec)\r\n$2=")); print_uint8_base10(settings.step_invert_mask); - printPgmString(PSTR(" (step port invert mask:")); print_uint8_base2(settings.step_invert_mask); - printPgmString(PSTR(")\r\n$3=")); print_uint8_base10(settings.dir_invert_mask); - printPgmString(PSTR(" (dir port invert mask:")); print_uint8_base2(settings.dir_invert_mask); - printPgmString(PSTR(")\r\n$4=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); - printPgmString(PSTR(" (step enable invert, bool)\r\n$5=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)); - printPgmString(PSTR(" (limit pins invert, bool)\r\n$6=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN)); - printPgmString(PSTR(" (probe pin invert, bool)\r\n$10=")); print_uint8_base10(settings.status_report_mask); - printPgmString(PSTR(" (status report mask:")); print_uint8_base2(settings.status_report_mask); - printPgmString(PSTR(")\r\n$11=")); printFloat_SettingValue(settings.junction_deviation); - printPgmString(PSTR(" (junction deviation, mm)\r\n$12=")); printFloat_SettingValue(settings.arc_tolerance); - printPgmString(PSTR(" (arc tolerance, mm)\r\n$13=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); - printPgmString(PSTR(" (report inches, bool)\r\n$20=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); - printPgmString(PSTR(" (soft limits, bool)\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); - printPgmString(PSTR(" (hard limits, bool)\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); - printPgmString(PSTR(" (homing cycle, bool)\r\n$23=")); print_uint8_base10(settings.homing_dir_mask); - printPgmString(PSTR(" (homing dir invert mask:")); print_uint8_base2(settings.homing_dir_mask); - printPgmString(PSTR(")\r\n$24=")); printFloat_SettingValue(settings.homing_feed_rate); - printPgmString(PSTR(" (homing feed, mm/min)\r\n$25=")); printFloat_SettingValue(settings.homing_seek_rate); - printPgmString(PSTR(" (homing seek, mm/min)\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay); - printPgmString(PSTR(" (homing debounce, msec)\r\n$27=")); printFloat_SettingValue(settings.homing_pulloff); - printPgmString(PSTR(" (homing pull-off, mm)\r\n")); - + #ifdef REPORT_GUI_MODE + printPgmString(PSTR("$0=")); print_uint8_base10(settings.pulse_microseconds); + printPgmString(PSTR("\r\n$1=")); print_uint8_base10(settings.stepper_idle_lock_time); + printPgmString(PSTR("\r\n$2=")); print_uint8_base10(settings.step_invert_mask); + printPgmString(PSTR("\r\n$3=")); print_uint8_base10(settings.dir_invert_mask); + printPgmString(PSTR("\r\n$4=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); + printPgmString(PSTR("\r\n$5=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)); + printPgmString(PSTR("\r\n$6=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN)); + printPgmString(PSTR("\r\n$10=")); print_uint8_base10(settings.status_report_mask); + printPgmString(PSTR("\r\n$11=")); printFloat_SettingValue(settings.junction_deviation); + printPgmString(PSTR("\r\n$12=")); printFloat_SettingValue(settings.arc_tolerance); + printPgmString(PSTR("\r\n$13=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); + printPgmString(PSTR("\r\n$20=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); + printPgmString(PSTR("\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); + printPgmString(PSTR("\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); + printPgmString(PSTR("\r\n$23=")); print_uint8_base10(settings.homing_dir_mask); + printPgmString(PSTR("\r\n$24=")); printFloat_SettingValue(settings.homing_feed_rate); + printPgmString(PSTR("\r\n$25=")); printFloat_SettingValue(settings.homing_seek_rate); + printPgmString(PSTR("\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay); + printPgmString(PSTR("\r\n$27=")); printFloat_SettingValue(settings.homing_pulloff); + printPgmString(PSTR("\r\n")); + #else + printPgmString(PSTR("$0=")); print_uint8_base10(settings.pulse_microseconds); + printPgmString(PSTR(" (step pulse, usec)\r\n$1=")); print_uint8_base10(settings.stepper_idle_lock_time); + printPgmString(PSTR(" (step idle delay, msec)\r\n$2=")); print_uint8_base10(settings.step_invert_mask); + printPgmString(PSTR(" (step port invert mask:")); print_uint8_base2(settings.step_invert_mask); + printPgmString(PSTR(")\r\n$3=")); print_uint8_base10(settings.dir_invert_mask); + printPgmString(PSTR(" (dir port invert mask:")); print_uint8_base2(settings.dir_invert_mask); + printPgmString(PSTR(")\r\n$4=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); + printPgmString(PSTR(" (step enable invert, bool)\r\n$5=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)); + printPgmString(PSTR(" (limit pins invert, bool)\r\n$6=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN)); + printPgmString(PSTR(" (probe pin invert, bool)\r\n$10=")); print_uint8_base10(settings.status_report_mask); + printPgmString(PSTR(" (status report mask:")); print_uint8_base2(settings.status_report_mask); + printPgmString(PSTR(")\r\n$11=")); printFloat_SettingValue(settings.junction_deviation); + printPgmString(PSTR(" (junction deviation, mm)\r\n$12=")); printFloat_SettingValue(settings.arc_tolerance); + printPgmString(PSTR(" (arc tolerance, mm)\r\n$13=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); + printPgmString(PSTR(" (report inches, bool)\r\n$20=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); + printPgmString(PSTR(" (soft limits, bool)\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); + printPgmString(PSTR(" (hard limits, bool)\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); + printPgmString(PSTR(" (homing cycle, bool)\r\n$23=")); print_uint8_base10(settings.homing_dir_mask); + printPgmString(PSTR(" (homing dir invert mask:")); print_uint8_base2(settings.homing_dir_mask); + printPgmString(PSTR(")\r\n$24=")); printFloat_SettingValue(settings.homing_feed_rate); + printPgmString(PSTR(" (homing feed, mm/min)\r\n$25=")); printFloat_SettingValue(settings.homing_seek_rate); + printPgmString(PSTR(" (homing seek, mm/min)\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay); + printPgmString(PSTR(" (homing debounce, msec)\r\n$27=")); printFloat_SettingValue(settings.homing_pulloff); + printPgmString(PSTR(" (homing pull-off, mm)\r\n")); + #endif + // Print axis settings uint8_t idx, set_idx; uint8_t val = AXIS_SETTINGS_START_VAL; @@ -200,19 +233,23 @@ void report_grbl_settings() { case 2: printFloat_SettingValue(settings.acceleration[idx]/(60*60)); break; case 3: printFloat_SettingValue(-settings.max_travel[idx]); break; } - printPgmString(PSTR(" (")); - switch (idx) { - case X_AXIS: printPgmString(PSTR("x")); break; - case Y_AXIS: printPgmString(PSTR("y")); break; - case Z_AXIS: printPgmString(PSTR("z")); break; - } - switch (set_idx) { - case 0: printPgmString(PSTR(", step/mm")); break; - case 1: printPgmString(PSTR(" max rate, mm/min")); break; - case 2: printPgmString(PSTR(" accel, mm/sec^2")); break; - case 3: printPgmString(PSTR(" max travel, mm")); break; - } - printPgmString(PSTR(")\r\n")); + #ifdef REPORT_GUI_MODE + printPgmString(PSTR("\r\n")); + #else + printPgmString(PSTR(" (")); + switch (idx) { + case X_AXIS: printPgmString(PSTR("x")); break; + case Y_AXIS: printPgmString(PSTR("y")); break; + case Z_AXIS: printPgmString(PSTR("z")); break; + } + switch (set_idx) { + case 0: printPgmString(PSTR(", step/mm")); break; + case 1: printPgmString(PSTR(" max rate, mm/min")); break; + case 2: printPgmString(PSTR(" accel, mm/sec^2")); break; + case 3: printPgmString(PSTR(" max travel, mm")); break; + } + printPgmString(PSTR(")\r\n")); + #endif } val += AXIS_SETTINGS_INCREMENT; } diff --git a/grbl/system.c b/grbl/system.c index 2f3d100..a31c5fe 100644 --- a/grbl/system.c +++ b/grbl/system.c @@ -109,54 +109,57 @@ uint8_t system_execute_line(char *line) float parameter, value; switch( line[char_counter] ) { case 0 : report_grbl_help(); break; - case '$' : // Prints Grbl settings - if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); } - if ( sys.state & (STATE_CYCLE | STATE_HOLD) ) { return(STATUS_IDLE_ERROR); } // Block during cycle. Takes too long to print. - else { report_grbl_settings(); } - break; - case 'G' : // Prints gcode parser state - // TODO: Move this to realtime commands for GUIs to request this data during suspend-state. - if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); } - else { report_gcode_modes(); } - break; - case 'C' : // Set check g-code mode [IDLE/CHECK] - if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); } - // Perform reset when toggling off. Check g-code mode should only work if Grbl - // is idle and ready, regardless of alarm locks. This is mainly to keep things - // simple and consistent. - if ( sys.state == STATE_CHECK_MODE ) { - mc_reset(); - report_feedback_message(MESSAGE_DISABLED); - } else { - if (sys.state) { return(STATUS_IDLE_ERROR); } // Requires no alarm mode. - sys.state = STATE_CHECK_MODE; - report_feedback_message(MESSAGE_ENABLED); + case '$': case 'G': case 'C': case 'X': + if ( line[(char_counter+1)] != 0 ) { return(STATUS_INVALID_STATEMENT); } + switch( line[char_counter] ) { + case '$' : // Prints Grbl settings + if ( sys.state & (STATE_CYCLE | STATE_HOLD) ) { return(STATUS_IDLE_ERROR); } // Block during cycle. Takes too long to print. + else { report_grbl_settings(); } + break; + case 'G' : // Prints gcode parser state + // TODO: Move this to realtime commands for GUIs to request this data during suspend-state. + report_gcode_modes(); + break; + case 'C' : // Set check g-code mode [IDLE/CHECK] + // Perform reset when toggling off. Check g-code mode should only work if Grbl + // is idle and ready, regardless of alarm locks. This is mainly to keep things + // simple and consistent. + if ( sys.state == STATE_CHECK_MODE ) { + mc_reset(); + report_feedback_message(MESSAGE_DISABLED); + } else { + if (sys.state) { return(STATUS_IDLE_ERROR); } // Requires no alarm mode. + sys.state = STATE_CHECK_MODE; + report_feedback_message(MESSAGE_ENABLED); + } + break; + case 'X' : // Disable alarm lock [ALARM] + if (sys.state == STATE_ALARM) { + report_feedback_message(MESSAGE_ALARM_UNLOCK); + sys.state = STATE_IDLE; + // Don't run startup script. Prevents stored moves in startup from causing accidents. + if (system_check_safety_door_ajar()) { // Check safety door switch before returning. + bit_true(sys.rt_exec_state, EXEC_SAFETY_DOOR); + protocol_execute_realtime(); // Enter safety door mode. + } + } // Otherwise, no effect. + break; + // case 'J' : break; // Jogging methods + // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be + // susceptible to other realtime commands except for e-stop. The jogging function is intended to + // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped + // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would + // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the + // motion by repeatedly toggling to slow the motion to the desired location. Location data would + // need to be updated real-time and supplied to the user through status queries. + // More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are + // handled by the planner. It would be possible for the jog subprogram to insert blocks into the + // block buffer without having the planner plan them. It would need to manage de/ac-celerations + // on its own carefully. This approach could be effective and possibly size/memory efficient. +// } +// break; } - break; - case 'X' : // Disable alarm lock [ALARM] - if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); } - if (sys.state == STATE_ALARM) { - report_feedback_message(MESSAGE_ALARM_UNLOCK); - sys.state = STATE_IDLE; - // Don't run startup script. Prevents stored moves in startup from causing accidents. - if (system_check_safety_door_ajar()) { // Check safety door switch before returning. - bit_true(sys.rt_exec_state, EXEC_SAFETY_DOOR); - protocol_execute_realtime(); // Enter safety door mode. - } - } // Otherwise, no effect. - break; -// case 'J' : break; // Jogging methods - // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be - // susceptible to other realtime commands except for e-stop. The jogging function is intended to - // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped - // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would - // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the - // motion by repeatedly toggling to slow the motion to the desired location. Location data would - // need to be updated real-time and supplied to the user through status queries. - // More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are - // handled by the planner. It would be possible for the jog subprogram to insert blocks into the - // block buffer without having the planner plan them. It would need to manage de/ac-celerations - // on its own carefully. This approach could be effective and possibly size/memory efficient. + break; default : // Block any system command that requires the state as IDLE/ALARM. (i.e. EEPROM, homing) if ( !(sys.state == STATE_IDLE || sys.state == STATE_ALARM) ) { return(STATUS_IDLE_ERROR); }