From 6b7e3585bfaff240a7b60d8a5a080e1608b4c2a2 Mon Sep 17 00:00:00 2001 From: "alden.hart" Date: Sun, 28 Apr 2013 22:12:15 -0400 Subject: [PATCH] 008.02 refactored gcode normalizer to include octal stripping --- TinyG2/TinyG2.cppproj | 2 +- TinyG2/canonical_machine.cpp | 3 + TinyG2/canonical_machine.h | 10 ++- TinyG2/controller.cpp | 1 + TinyG2/gcode_parser.cpp | 110 +++++++++++++---------------- TinyG2/report.cpp | 3 +- TinyG2/settings/settings_default.h | 8 +-- TinyG2/tinyg2.h | 2 +- 8 files changed, 68 insertions(+), 71 deletions(-) diff --git a/TinyG2/TinyG2.cppproj b/TinyG2/TinyG2.cppproj index 36776c87..ce980051 100755 --- a/TinyG2/TinyG2.cppproj +++ b/TinyG2/TinyG2.cppproj @@ -30,7 +30,7 @@ 000028011884 127.0.0.1 - 4114 + 4123 False diff --git a/TinyG2/canonical_machine.cpp b/TinyG2/canonical_machine.cpp index 20c9ef55..8df1a7d0 100755 --- a/TinyG2/canonical_machine.cpp +++ b/TinyG2/canonical_machine.cpp @@ -168,6 +168,7 @@ uint8_t cm_get_distance_mode() { return gm.distance_mode;} uint8_t cm_get_inverse_feed_rate_mode() { return gm.inverse_feed_rate_mode;} uint8_t cm_get_spindle_mode() { return gm.spindle_mode;} uint32_t cm_get_model_linenum() { return gm.linenum;} +uint8_t cm_get_block_delete_switch() { return gm.block_delete_switch;} uint8_t cm_isbusy() { return (mp_isbusy());} // set parameters in gm struct @@ -560,6 +561,8 @@ void canonical_machine_init() cm_set_path_control(cfg.path_control); cm_set_distance_mode(cfg.distance_mode); + gm.block_delete_switch = true; + // never start a machine in a motion mode gm.motion_mode = MOTION_MODE_CANCEL_MOTION_MODE; diff --git a/TinyG2/canonical_machine.h b/TinyG2/canonical_machine.h index 78d9e49a..5968a824 100755 --- a/TinyG2/canonical_machine.h +++ b/TinyG2/canonical_machine.h @@ -94,11 +94,11 @@ typedef struct GCodeModel { // Gcode dynamic model float g28_position[AXES]; // XYZABC stored machine position for G28 float g30_position[AXES]; // XYZABC stored machine position for G30 - float min_time; // minimum time possible for the move given axis constraints + float min_time; // minimum time possible for the move given axis constraints float feed_rate; // F - normalized to millimeters/minute float inverse_feed_rate; // ignored if inverse_feed_rate not active float feed_rate_override_factor; // 1.0000 x F feed rate. Go up or down from there - float traverse_override_factor; // 1.0000 x traverse rate. Go down from there + float traverse_override_factor; // 1.0000 x traverse rate. Go down from there uint8_t inverse_feed_rate_mode; // G93 TRUE = inverse, FALSE = normal (G94) uint8_t feed_rate_override_enable; // TRUE = overrides enabled (M48), F=(M49) uint8_t traverse_override_enable; // TRUE = traverse override enabled @@ -124,9 +124,11 @@ typedef struct GCodeModel { // Gcode dynamic model uint8_t spindle_mode; // 0=OFF (M5), 1=CW (M3), 2=CCW (M4) float spindle_speed; // in RPM - float spindle_override_factor; // 1.0000 x S spindle speed. Go up or down from there + float spindle_override_factor; // 1.0000 x S spindle speed. Go up or down from there uint8_t spindle_override_enable; // TRUE = override enabled + uint8_t block_delete_switch; // set true to enable block deletes (true is default) + // unimplemented gcode parameters // float cutter_radius; // D - cutter radius compensation (0 is off) // float cutter_length; // H - cutter length compensation (0 is off) @@ -443,6 +445,8 @@ uint8_t cm_get_distance_mode(void); uint8_t cm_get_inverse_feed_rate_mode(void); uint8_t cm_get_spindle_mode(void); uint32_t cm_get_model_linenum(void); +uint8_t cm_get_block_delete_switch(void); + uint8_t cm_isbusy(void); void cm_set_motion_mode(uint8_t motion_mode); diff --git a/TinyG2/controller.cpp b/TinyG2/controller.cpp index 9f6b6b87..41fd4960 100755 --- a/TinyG2/controller.cpp +++ b/TinyG2/controller.cpp @@ -196,6 +196,7 @@ static stat_t _command_dispatch() } else if (cs.state == CONTROLLER_STARTUP) { // strcpy(cs.in_buf, "$x"); // strcpy(cs.in_buf, "g1f400x100"); + strcpy(cs.in_buf, "?"); cs.state = CONTROLLER_READY; } else { return (STAT_OK); diff --git a/TinyG2/gcode_parser.cpp b/TinyG2/gcode_parser.cpp index 7c6a6366..1d73be78 100755 --- a/TinyG2/gcode_parser.cpp +++ b/TinyG2/gcode_parser.cpp @@ -78,82 +78,72 @@ stat_t gc_gcode_parser(char_t *block) * chars < 0x20 (control characters) * ! $ % , ; ; ? @ ^ _ ~ " ' * - * Valid characters in a Gcode block are (see RS274NGC_3 Appendix E) - * digits all digits are passed to interpreter - * lower case alpha all alpha is passed - * upper case alpha all alpha is passed - * + - . / * < = > chars passed to interpreter - * | % # ( ) [ ] { } chars passed to interpreter - * chars are legal but are not passed - * / if first, block delete char - omits the block + * Valid characters in a Gcode block are a sub-set of those in RS274NGC_3 Appendix E: + * - alphanumeric plus '-' and '.' + * + * Block delete: Blocks starting with '/' are ignored if block delete switch is on, + * otherwise they are processed as usual. + * + * Octal stripping: Leading zeros in number fields are stripped unless followed by a period * * Comment handling: - * * - Comments are not normalized - they are left alone * - Comments always terminate the block (i.e. embedded comments are not supported) * - Messages in comments are sent to console * - The 'MSG' specifier in comment can have mixed case but cannot cannot have embedded white spaces * - Normalization returns true if there was a message to display, false otherwise - * - Processing splits string into command and comment portions - cases: - * supported: COMMAND - * supported: comment - * supported: COMMAND comment - * - * unsupported: COMMAND COMMAND - * unsupported: comment COMMAND - * unsupported: COMMAND comment COMMAND - * - * ++++ todo: Support leading and trailing spaces around the MSG specifier - * ++++ todo: Refactor to reject Octal numbers (leading 0's) + * - Processing splits string into command and comment portions - supported cases are: + * COMMAND + * (comment) + * COMMAND (comment) */ - -static uint8_t _normalize_gcode_block(char_t *block) +static uint8_t _normalize_gcode_block(char_t *str) { - char_t c; - char_t *comment=0; // comment pointer - first char past opening paren - uint8_t i=0; // index for incoming characters - uint8_t j=0; // index for normalized characters + char_t *rd = str; // read pointer + char_t *wr = str; // pointer to write normalized characters + char_t *cp = NUL; // comment pointer - first char past opening paren - if (block[0] == '/') { // discard deleted blocks - block[0] = NUL; - return (false); - } - if (block[0] == '?') { // trap and return ? command - return (false); + if (*rd == '?') { return (false); } // trap and return ? command + if (*rd == '/') { // handle block deletes + rd++; + if (cm_get_block_delete_switch() == true) { + *wr = NUL; + return (false); + } } // normalize the command block & mark the comment(if any) - while ((c = toupper(block[i++])) != NUL) { - if ((isupper(c)) || (isdigit(c))) { // capture common chars - block[j++] = c; + do { + if (*rd == NUL) { *wr = NUL; } + else if (*rd == '(') { *wr = NUL; cp = rd+1; } + else if ((isalnum((char)*rd)) || (strchr("-.", *rd))) { // all valid characters + *(wr++) = (char_t)toupper((char)*(rd)); + } + rd++; + } while (*wr != NUL); + + // Perform Octal stripping - remove invalid leading zeros in number strings + rd = str; + while (*rd != NUL) { + if ((!isdigit(*rd)) && (*(rd+1) == '0') && (isdigit(*(rd+2)))) { + wr = rd+1; + while (*wr != NUL) { *wr = *(wr+1); wr++;} +// while (*wr != NUL) { *(wr++) = *(wr+1); } continue; } - if (c == '(') { // detect & handle comments - block[j] = NUL; - comment = &block[i]; - break; - } - if (c <= ' ') continue; // toss controls & whitespace - if (c == DEL) continue; // toss DELETE (0x7F) - if (strchr("!$%,;:?@^_~`\'\"", c)) // toss invalid punctuation - continue; - block[j++] = c; + rd++; } - block[j] = NUL; // terminate the command - if (comment != 0) { - if ((toupper(comment[0]) == 'M') && - (toupper(comment[1]) == 'S') && - (toupper(comment[2]) == 'G')) { - i=0; - comment +=3; // skip past the leading chars - while ((c = comment[i++]) != NUL) {// remove trailing parenthesis - if (c == ')') { - comment[--i] = NUL; - break; - } - } - (void)cm_message(comment); + + // process a comment with a message, otherwise ignore it + rd = cp; + if (cp != NUL) { + if ((tolower(*(rd++)) == 'm') && (toupper(*(rd++)) == 's') && (toupper(*(rd++)) == 'g')) { + do { + if (*rd == ')') *rd = NUL; // remove trailing parenthesis, if any + rd++; + } while (*rd != NUL); + (void)cm_message(cp); return (true); - } + } } return (false); } diff --git a/TinyG2/report.cpp b/TinyG2/report.cpp index b37b6185..07a4b4cc 100755 --- a/TinyG2/report.cpp +++ b/TinyG2/report.cpp @@ -236,7 +236,7 @@ void rpt_print_system_ready_message(void) /* * rpt_init_status_report() * - * Call this function to completely re-initialze the status report + * Call this function to completely re-initialize the status report * Sets SR list to hard-coded defaults and re-initializes sr values in NVM */ @@ -248,7 +248,6 @@ void rpt_init_status_report() cmdObj_t *cmd = cmd_reset_list(); // used for status report persistence locations cs.status_report_counter = (cfg.status_report_interval / RTC_PERIOD); // RTC fires every 10 ms -// cmd->index = cmd_get_index((const char_t *)"",(const char_t *)"se00"); // set first SR persistence index cmd->index = cmd_get_index(nul, se00); // set first SR persistence index for (uint8_t i=0; i < CMD_STATUS_REPORT_LEN ; i++) { if (sr_defaults[i][0] == NUL) break; // quit on first blank array entry diff --git a/TinyG2/settings/settings_default.h b/TinyG2/settings/settings_default.h index fd1095a4..2043d9ce 100755 --- a/TinyG2/settings/settings_default.h +++ b/TinyG2/settings/settings_default.h @@ -49,7 +49,7 @@ // *** motor settings *** -#define M1_MOTOR_MAP AXIS_X // 1ma +#define M1_MOTOR_MAP AXIS_X // 1ma #define M1_STEP_ANGLE 1.8 // 1sa #define M1_TRAVEL_PER_REV 1.25 // 1tr #define M1_MICROSTEPS 8 // 1mi 1,2,4,8 @@ -94,7 +94,7 @@ // *** axis settings *** #define X_AXIS_MODE AXIS_STANDARD // xam see canonical_machine.h cmAxisMode for valid values -#define X_VELOCITY_MAX 1200 // xvm G0 max velocity in mm/min +#define X_VELOCITY_MAX 800 // xvm G0 max velocity in mm/min #define X_FEEDRATE_MAX X_VELOCITY_MAX // xfr G1 max feed rate in mm/min #define X_TRAVEL_MAX 150 // xtm travel between switches or crashes #define X_JERK_MAX JERK_MAX // xjm @@ -108,7 +108,7 @@ #define X_JERK_HOMING X_JERK_MAX // xjh #define Y_AXIS_MODE AXIS_STANDARD -#define Y_VELOCITY_MAX 1200 +#define Y_VELOCITY_MAX 800 #define Y_FEEDRATE_MAX Y_VELOCITY_MAX #define Y_TRAVEL_MAX 150 #define Y_JERK_MAX JERK_MAX @@ -122,7 +122,7 @@ #define Y_JERK_HOMING Y_JERK_MAX #define Z_AXIS_MODE AXIS_STANDARD -#define Z_VELOCITY_MAX 1200 +#define Z_VELOCITY_MAX 800 #define Z_FEEDRATE_MAX Z_VELOCITY_MAX #define Z_TRAVEL_MAX 75 #define Z_JERK_MAX JERK_MAX diff --git a/TinyG2/tinyg2.h b/TinyG2/tinyg2.h index 3f8c375d..ca9dbc5c 100755 --- a/TinyG2/tinyg2.h +++ b/TinyG2/tinyg2.h @@ -40,7 +40,7 @@ extern "C"{ #endif -#define TINYG2_FIRMWARE_BUILD 008.01 // refining a functioning unit! +#define TINYG2_FIRMWARE_BUILD 008.02 // refining a functioning unit! #define TINYG2_FIRMWARE_VERSION 0.01 // firmware major version #define TINYG2_HARDWARE_PLATFORM 1.00 // hardware platform indicator (Native Arduino Due) #define TINYG2_HARDWARE_VERSION 1.00 // hardware platform revision number