Sergey Pastor / grbl1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gcode.c Source File

gcode.c

00001 /*
00002   gcode.c - rs274/ngc parser.
00003   Part of Grbl
00004 
00005   Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
00006   Copyright (c) 2009-2011 Simen Svale Skogsrud
00007 
00008   Grbl is free software: you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation, either version 3 of the License, or
00011   (at your option) any later version.
00012 
00013   Grbl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017 
00018   You should have received a copy of the GNU General Public License
00019   along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
00020 */
00021 
00022 #include "grbl.h"
00023 
00024 // NOTE: Max line number is defined by the g-code standard to be 99999. It seems to be an
00025 // arbitrary value, and some GUIs may require more. So we increased it based on a max safe
00026 // value when converting a float (7.2 digit precision)s to an integer.
00027 #define MAX_LINE_NUMBER 10000000
00028 #define MAX_TOOL_NUMBER 255 // Limited by max unsigned 8-bit value
00029 
00030 #define AXIS_COMMAND_NONE 0
00031 #define AXIS_COMMAND_NON_MODAL 1
00032 #define AXIS_COMMAND_MOTION_MODE 2
00033 #define AXIS_COMMAND_TOOL_LENGTH_OFFSET 3 // *Undefined but required
00034 
00035 // Declare gc extern struct
00036 parser_state_t gc_state;
00037 parser_block_t gc_block;
00038 
00039 #define FAIL(status) return(status);
00040 
00041 
00042 void gc_init()
00043 {
00044   memset(&gc_state, 0, sizeof(parser_state_t));
00045 
00046   // Load default G54 coordinate system.
00047   if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) {
00048     report_status_message(STATUS_SETTING_READ_FAIL);
00049   }
00050 }
00051 
00052 
00053 // Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
00054 // limit pull-off routines.
00055 void gc_sync_position()
00056 {
00057   system_convert_array_steps_to_mpos(gc_state.position,sys_position);
00058 }
00059 
00060 
00061 // Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase
00062 // characters and signed floating point values (no whitespace). Comments and block delete
00063 // characters have been removed. In this function, all units and positions are converted and
00064 // exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine
00065 // coordinates, respectively.
00066 uint8_t gc_execute_line(char *line)
00067 {
00068   /* -------------------------------------------------------------------------------------
00069      STEP 1: Initialize parser block struct and copy current g-code state modes. The parser
00070      updates these modes and commands as the block line is parser and will only be used and
00071      executed after successful error-checking. The parser block struct also contains a block
00072      values struct, word tracking variables, and a non-modal commands tracker for the new
00073      block. This struct contains all of the necessary information to execute the block. */
00074 
00075   memset(&gc_block, 0, sizeof(parser_block_t)); // Initialize the parser block struct.
00076   memcpy(&gc_block.modal,&gc_state.modal,sizeof(gc_modal_t)); // Copy current modes
00077 
00078   uint8_t axis_command = AXIS_COMMAND_NONE;
00079   uint8_t axis_0, axis_1, axis_linear;
00080   uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution
00081 
00082   // Initialize bitflag tracking variables for axis indices compatible operations.
00083   uint8_t axis_words = 0; // XYZ tracking
00084   uint8_t ijk_words = 0; // IJK tracking
00085 
00086   // Initialize command and value words and parser flags variables.
00087   uint16_t command_words = 0; // Tracks G and M command words. Also used for modal group violations.
00088   uint16_t value_words = 0; // Tracks value words.
00089   uint8_t gc_parser_flags = GC_PARSER_NONE;
00090 
00091   // Determine if the line is a jogging motion or a normal g-code block.
00092   if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function.
00093                         // Set G1 and G94 enforced modes to ensure accurate error checks.
00094     gc_parser_flags |= GC_PARSER_JOG_MOTION;
00095     gc_block.modal.motion = MOTION_MODE_LINEAR;
00096     gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;
00097 #ifdef USE_LINE_NUMBERS
00098      gc_block.values.n = JOG_LINE_NUMBER; // Initialize default line number reported during jog.
00099 #endif
00100   }
00101 
00102   /* -------------------------------------------------------------------------------------
00103      STEP 2: Import all g-code words in the block line. A g-code word is a letter followed by
00104      a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also,
00105      perform initial error-checks for command word modal group violations, for any repeated
00106      words, and for negative values set for the value words F, N, P, T, and S. */
00107 
00108   uint8_t word_bit; // Bit-value for assigning tracking variables
00109   uint8_t char_counter;
00110   char letter;
00111   float value;
00112   uint8_t int_value = 0;
00113   uint16_t mantissa = 0;
00114   if (gc_parser_flags & GC_PARSER_JOG_MOTION) { char_counter = 3; } // Start parsing after `$J=`
00115   else { char_counter = 0; }
00116 
00117   while (line[char_counter] != 0) { // Loop until no more g-code words in line.
00118 
00119     // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out.
00120     letter = line[char_counter];
00121     if((letter < 'A') || (letter > 'Z')) { FAIL(STATUS_EXPECTED_COMMAND_LETTER); } // [Expected word letter]
00122     char_counter++;
00123     if (!read_float(line, &char_counter, &value)) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // [Expected word value]
00124 
00125     // Convert values to smaller uint8 significand and mantissa values for parsing this word.
00126     // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more
00127     // accurate than the NIST gcode requirement of x10 when used for commands, but not quite
00128     // accurate enough for value words that require integers to within 0.0001. This should be
00129     // a good enough comprimise and catch most all non-integer errors. To make it compliant,
00130     // we would simply need to change the mantissa to int16, but this add compiled flash space.
00131     // Maybe update this later.
00132     int_value = truncf(value);
00133     mantissa = (uint16_t)lroundf(100 * (value - int_value)); // Compute mantissa for Gxx.x commands.
00134     // NOTE: Rounding must be used to catch small floating point errors.
00135 
00136     // Check if the g-code word is supported or errors due to modal group violations or has
00137     // been repeated in the g-code block. If ok, update the command or record its value.
00138     switch(letter) {
00139 
00140       /* 'G' and 'M' Command Words: Parse commands and check for modal group violations.
00141          NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */
00142 
00143       case 'G':
00144         // Determine 'G' command and its modal group
00145         switch(int_value) {
00146           case 10: case 28: case 30: case 92:
00147             // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block.
00148             // * G43.1 is also an axis command but is not explicitly defined this way.
00149             if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1
00150               if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
00151               axis_command = AXIS_COMMAND_NON_MODAL;
00152             }
00153             // No break. Continues to next line.
00154           case 4: case 53:
00155             word_bit = MODAL_GROUP_G0;
00156             gc_block.non_modal_command = int_value;
00157             if ((int_value == 28) || (int_value == 30) || (int_value == 92)) {
00158               if (!((mantissa == 0) || (mantissa == 10))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); }
00159               gc_block.non_modal_command += mantissa;
00160               mantissa = 0; // Set to zero to indicate valid non-integer G command.
00161             }                
00162             break;
00163           case 0: case 1: case 2: case 3: case 38:
00164             // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.
00165             // * G43.1 is also an axis command but is not explicitly defined this way.
00166             if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
00167             axis_command = AXIS_COMMAND_MOTION_MODE;
00168             // No break. Continues to next line.
00169           case 80:
00170             word_bit = MODAL_GROUP_G1;
00171             gc_block.modal.motion = int_value;
00172             if (int_value == 38){
00173               if (!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) {
00174                 FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]
00175               }
00176               gc_block.modal.motion += (mantissa/10)+100;
00177               mantissa = 0; // Set to zero to indicate valid non-integer G command.
00178             }  
00179             break;
00180           case 17: case 18: case 19:
00181             word_bit = MODAL_GROUP_G2;
00182             gc_block.modal.plane_select = int_value - 17;
00183             break;
00184           case 90: case 91:
00185             if (mantissa == 0) {
00186               word_bit = MODAL_GROUP_G3;
00187               gc_block.modal.distance = int_value - 90;
00188             } else {
00189               word_bit = MODAL_GROUP_G4;
00190               if ((mantissa != 10) || (int_value == 90)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G90.1 not supported]
00191               mantissa = 0; // Set to zero to indicate valid non-integer G command.
00192               // Otherwise, arc IJK incremental mode is default. G91.1 does nothing.
00193             }
00194             break;
00195           case 93: case 94:
00196             word_bit = MODAL_GROUP_G5;
00197             gc_block.modal.feed_rate = 94 - int_value;
00198             break;
00199           case 20: case 21:
00200             word_bit = MODAL_GROUP_G6;
00201             gc_block.modal.units = 21 - int_value;
00202             break;
00203           case 40:
00204             word_bit = MODAL_GROUP_G7;
00205             // NOTE: Not required since cutter radius compensation is always disabled. Only here
00206             // to support G40 commands that often appear in g-code program headers to setup defaults.
00207             // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40
00208             break;
00209           case 43: case 49:
00210             word_bit = MODAL_GROUP_G8;
00211             // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed,
00212             // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49
00213             // all are explicit axis commands, regardless if they require axis words or not.
00214             if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] }
00215             axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET;
00216             if (int_value == 49) { // G49
00217               gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL;
00218             } else if (mantissa == 10) { // G43.1
00219               gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
00220             } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported G43.x command]
00221             mantissa = 0; // Set to zero to indicate valid non-integer G command.
00222             break;
00223           case 54: case 55: case 56: case 57: case 58: case 59:
00224             // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)
00225             word_bit = MODAL_GROUP_G12;
00226             gc_block.modal.coord_select = int_value - 54; // Shift to array indexing.
00227             break;
00228           case 61:
00229             word_bit = MODAL_GROUP_G13;
00230             if (mantissa != 0) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G61.1 not supported]
00231             // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61
00232             break;
00233           default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command]
00234         }
00235         if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [Unsupported or invalid Gxx.x command]
00236         // Check for more than one command per modal group violations in the current block
00237         // NOTE: Variable 'word_bit' is always assigned, if the command is valid.
00238         if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }
00239         command_words |= bit(word_bit);
00240         break;
00241 
00242       case 'M':
00243 
00244         // Determine 'M' command and its modal group
00245         if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [No Mxx.x commands]
00246         switch(int_value) {
00247           case 0: case 1: case 2: case 30:
00248             word_bit = MODAL_GROUP_M4;
00249             switch(int_value) {
00250               case 0: gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause
00251               case 1: break; // Optional stop not supported. Ignore.
00252               default: gc_block.modal.program_flow = int_value; // Program end and reset
00253             }
00254             break;
00255                     case 3: case 4: case 5:
00256             word_bit = MODAL_GROUP_M7;
00257             switch(int_value) {
00258               case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break;
00259               case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break;
00260               case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break;
00261             }
00262             break;
00263           #ifdef ENABLE_M7
00264             case 7: case 8: case 9:
00265           #else
00266             case 8: case 9:
00267           #endif
00268             word_bit = MODAL_GROUP_M8;
00269             switch(int_value) {
00270               #ifdef ENABLE_M7
00271                 case 7: gc_block.modal.coolant = COOLANT_MIST_ENABLE; break;
00272               #endif
00273               case 8: gc_block.modal.coolant = COOLANT_FLOOD_ENABLE; break;
00274               case 9: gc_block.modal.coolant = COOLANT_DISABLE; break;
00275             }
00276             break;
00277                     #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
00278                         case 56:
00279                             word_bit = MODAL_GROUP_M9;
00280                             gc_block.modal.override = OVERRIDE_PARKING_MOTION;
00281                             break;
00282                     #endif
00283           default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command]
00284         }
00285 
00286         // Check for more than one command per modal group violations in the current block
00287         // NOTE: Variable 'word_bit' is always assigned, if the command is valid.
00288         if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }
00289         command_words |= bit(word_bit);
00290         break;
00291 
00292       // NOTE: All remaining letters assign values.
00293       default:
00294 
00295         /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining
00296            legal g-code words and stores their value. Error-checking is performed later since some
00297            words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */
00298         switch(letter){
00299           // case 'A': // Not supported
00300           // case 'B': // Not supported
00301           // case 'C': // Not supported
00302           // case 'D': // Not supported
00303           case 'F': word_bit = WORD_F; gc_block.values.f = value; break;
00304           // case 'H': // Not supported
00305           case 'I': word_bit = WORD_I; gc_block.values.ijk[X_AXIS] = value; ijk_words |= (1<<X_AXIS); break;
00306           case 'J': word_bit = WORD_J; gc_block.values.ijk[Y_AXIS] = value; ijk_words |= (1<<Y_AXIS); break;
00307           case 'K': word_bit = WORD_K; gc_block.values.ijk[Z_AXIS] = value; ijk_words |= (1<<Z_AXIS); break;
00308           case 'L': word_bit = WORD_L; gc_block.values.l = int_value; break;
00309           case 'N': word_bit = WORD_N; gc_block.values.n = truncf(value); break;
00310           case 'P': word_bit = WORD_P; gc_block.values.p = value; break;
00311           // NOTE: For certain commands, P value must be an integer, but none of these commands are supported.
00312           // case 'Q': // Not supported
00313           case 'R': word_bit = WORD_R; gc_block.values.r = value; break;
00314           case 'S': word_bit = WORD_S; gc_block.values.s = value; break;
00315           case 'T': word_bit = WORD_T;
00316                 if (value > MAX_TOOL_NUMBER) { FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); }
00317                     gc_block.values.t = int_value;
00318                 break;
00319           case 'X': word_bit = WORD_X; gc_block.values.xyz[X_AXIS] = value; axis_words |= (1<<X_AXIS); break;
00320           case 'Y': word_bit = WORD_Y; gc_block.values.xyz[Y_AXIS] = value; axis_words |= (1<<Y_AXIS); break;
00321           case 'Z': word_bit = WORD_Z; gc_block.values.xyz[Z_AXIS] = value; axis_words |= (1<<Z_AXIS); break;
00322           default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND);
00323         }
00324 
00325         // NOTE: Variable 'word_bit' is always assigned, if the non-command letter is valid.
00326         if (bit_istrue(value_words,bit(word_bit))) { FAIL(STATUS_GCODE_WORD_REPEATED); } // [Word repeated]
00327         // Check for invalid negative values for words F, N, P, T, and S.
00328         // NOTE: Negative value check is done here simply for code-efficiency.
00329         if ( bit(word_bit) & (bit(WORD_F)|bit(WORD_N)|bit(WORD_P)|bit(WORD_T)|bit(WORD_S)) ) {
00330           if (value < 0.0) { FAIL(STATUS_NEGATIVE_VALUE); } // [Word value cannot be negative]
00331         }
00332         value_words |= bit(word_bit); // Flag to indicate parameter assigned.
00333 
00334     }
00335   }
00336   // Parsing complete!
00337 
00338 
00339   /* -------------------------------------------------------------------------------------
00340      STEP 3: Error-check all commands and values passed in this block. This step ensures all of
00341      the commands are valid for execution and follows the NIST standard as closely as possible.
00342      If an error is found, all commands and values in this block are dumped and will not update
00343      the active system g-code modes. If the block is ok, the active system g-code modes will be
00344      updated based on the commands of this block, and signal for it to be executed.
00345 
00346      Also, we have to pre-convert all of the values passed based on the modes set by the parsed
00347      block. There are a number of error-checks that require target information that can only be
00348      accurately calculated if we convert these values in conjunction with the error-checking.
00349      This relegates the next execution step as only updating the system g-code modes and
00350      performing the programmed actions in order. The execution step should not require any
00351      conversion calculations and would only require minimal checks necessary to execute.
00352   */
00353 
00354   /* NOTE: At this point, the g-code block has been parsed and the block line can be freed.
00355      NOTE: It's also possible, at some future point, to break up STEP 2, to allow piece-wise
00356      parsing of the block on a per-word basis, rather than the entire block. This could remove
00357      the need for maintaining a large string variable for the entire block and free up some memory.
00358      To do this, this would simply need to retain all of the data in STEP 1, such as the new block
00359      data struct, the modal group and value bitflag tracking variables, and axis array indices
00360      compatible variables. This data contains all of the information necessary to error-check the
00361      new g-code block when the EOL character is received. However, this would break Grbl's startup
00362      lines in how it currently works and would require some refactoring to make it compatible.
00363   */
00364 
00365   // [0. Non-specific/common error-checks and miscellaneous setup]:
00366 
00367   // Determine implicit axis command conditions. Axis words have been passed, but no explicit axis
00368   // command has been sent. If so, set axis command to current motion mode.
00369   if (axis_words) {
00370     if (!axis_command) { axis_command = AXIS_COMMAND_MOTION_MODE; } // Assign implicit motion-mode
00371   }
00372 
00373   // Check for valid line number N value.
00374   if (bit_istrue(value_words,bit(WORD_N))) {
00375     // Line number value cannot be less than zero (done) or greater than max line number.
00376     if (gc_block.values.n > MAX_LINE_NUMBER) { FAIL(STATUS_GCODE_INVALID_LINE_NUMBER); } // [Exceeds max line number]
00377   }
00378   // bit_false(value_words,bit(WORD_N)); // NOTE: Single-meaning value word. Set at end of error-checking.
00379 
00380   // Track for unused words at the end of error-checking.
00381   // NOTE: Single-meaning value words are removed all at once at the end of error-checking, because
00382   // they are always used when present. This was done to save a few bytes of flash. For clarity, the
00383   // single-meaning value words may be removed as they are used. Also, axis words are treated in the
00384   // same way. If there is an explicit/implicit axis command, XYZ words are always used and are
00385   // are removed at the end of error-checking.
00386 
00387   // [1. Comments ]: MSG's NOT SUPPORTED. Comment handling performed by protocol.
00388 
00389   // [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate
00390   //   is not defined after switching to G94 from G93.
00391   // NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word.
00392   if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
00393     if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); }
00394     if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
00395   } else {
00396     if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93
00397       // NOTE: G38 can also operate in inverse time, but is undefined as an error. Missing F word check added here.
00398       if (axis_command == AXIS_COMMAND_MOTION_MODE) {
00399         if ((gc_block.modal.motion != MOTION_MODE_NONE) && (gc_block.modal.motion != MOTION_MODE_SEEK)) {
00400           if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [F word missing]
00401         }
00402       }
00403       // NOTE: It seems redundant to check for an F word to be passed after switching from G94 to G93. We would
00404       // accomplish the exact same thing if the feed rate value is always reset to zero and undefined after each
00405       // inverse time block, since the commands that use this value already perform undefined checks. This would
00406       // also allow other commands, following this switch, to execute and not error out needlessly. This code is
00407       // combined with the above feed rate mode and the below set feed rate error-checking.
00408 
00409       // [3. Set feed rate ]: F is negative (done.)
00410       // - In inverse time mode: Always implicitly zero the feed rate value before and after block completion.
00411       // NOTE: If in G93 mode or switched into it from G94, just keep F value as initialized zero or passed F word
00412       // value in the block. If no F word is passed with a motion command that requires a feed rate, this will error
00413       // out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires
00414       // a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined.
00415     } else { // = G94
00416       // - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value.
00417       if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94
00418         if (bit_istrue(value_words,bit(WORD_F))) {
00419           if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
00420         } else {
00421           gc_block.values.f = gc_state.feed_rate; // Push last state feed rate
00422         }
00423       } // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value.
00424     }
00425   }
00426   // bit_false(value_words,bit(WORD_F)); // NOTE: Single-meaning value word. Set at end of error-checking.
00427 
00428   // [4. Set spindle speed ]: S is negative (done.)
00429   if (bit_isfalse(value_words,bit(WORD_S))) { gc_block.values.s = gc_state.spindle_speed; }
00430   // bit_false(value_words,bit(WORD_S)); // NOTE: Single-meaning value word. Set at end of error-checking.
00431 
00432   // [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value.
00433   // bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking.
00434 
00435   // [6. Change tool ]: N/A
00436   // [7. Spindle control ]: N/A
00437   // [8. Coolant control ]: N/A
00438     // [9. Override control ]: Not supported except for a Grbl-only parking motion override control.
00439 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
00440     if (bit_istrue(command_words, bit(MODAL_GROUP_M9))) { // Already set as enabled in parser.
00441         if (bit_istrue(value_words, bit(WORD_P))) {
00442             if (gc_block.values.p == 0.0f) { gc_block.modal.override = OVERRIDE_DISABLED; }
00443             bit_false(value_words, bit(WORD_P));
00444         }
00445     }
00446 #endif
00447     
00448   // [10. Dwell ]: P value missing. P is negative (done.) NOTE: See below.
00449   if (gc_block.non_modal_command == NON_MODAL_DWELL) {
00450     if (bit_isfalse(value_words,bit(WORD_P))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P word missing]
00451     bit_false(value_words,bit(WORD_P));
00452   }
00453 
00454   // [11. Set active plane ]: N/A
00455   switch (gc_block.modal.plane_select) {
00456     case PLANE_SELECT_XY:
00457       axis_0 = X_AXIS;
00458       axis_1 = Y_AXIS;
00459       axis_linear = Z_AXIS;
00460       break;
00461     case PLANE_SELECT_ZX:
00462       axis_0 = Z_AXIS;
00463       axis_1 = X_AXIS;
00464       axis_linear = Y_AXIS;
00465       break;
00466     default: // case PLANE_SELECT_YZ:
00467       axis_0 = Y_AXIS;
00468       axis_1 = Z_AXIS;
00469       axis_linear = X_AXIS;
00470   }
00471 
00472   // [12. Set length units ]: N/A
00473   // Pre-convert XYZ coordinate values to millimeters, if applicable.
00474   uint8_t idx;
00475   if (gc_block.modal.units == UNITS_MODE_INCHES) {
00476     for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.
00477       if (bit_istrue(axis_words,bit(idx)) ) {
00478         gc_block.values.xyz[idx] *= MM_PER_INCH;
00479       }
00480     }
00481   }
00482 
00483   // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED. Error, if enabled while G53 is active.
00484   // [G40 Errors]: G2/3 arc is programmed after a G40. The linear move after disabling is less than tool diameter.
00485   //   NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40
00486   //   only for the purpose to not error when G40 is sent with a g-code program header to setup the default modes.
00487 
00488   // [14. Cutter length compensation ]: G43 NOT SUPPORTED, but G43.1 and G49 are.
00489   // [G43.1 Errors]: Motion command in same line.
00490   //   NOTE: Although not explicitly stated so, G43.1 should be applied to only one valid
00491   //   axis that is configured (in config.h). There should be an error if the configured axis
00492   //   is absent or if any of the other axis words are present.
00493   if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates called in block.
00494     if (gc_block.modal.tool_length == TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC) {
00495       if (axis_words ^ (1<<TOOL_LENGTH_OFFSET_AXIS)) { FAIL(STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR); }
00496     }
00497   }
00498 
00499   // [15. Coordinate system selection ]: *N/A. Error, if cutter radius comp is active.
00500   // TODO: An EEPROM read of the coordinate data may require a buffer sync when the cycle
00501   // is active. The read pauses the processor temporarily and may cause a rare crash. For
00502   // future versions on processors with enough memory, all coordinate data should be stored
00503   // in memory and written to EEPROM only when there is not a cycle active.
00504   float block_coord_system[N_AXIS];
00505   memcpy(block_coord_system,gc_state.coord_system,sizeof(gc_state.coord_system));
00506   if ( bit_istrue(command_words,bit(MODAL_GROUP_G12)) ) { // Check if called in block
00507     if (gc_block.modal.coord_select > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]
00508     if (gc_state.modal.coord_select != gc_block.modal.coord_select) {
00509       if (!(settings_read_coord_data(gc_block.modal.coord_select,block_coord_system))) { FAIL(STATUS_SETTING_READ_FAIL); }
00510     }
00511   }
00512 
00513   // [16. Set path control mode ]: N/A. Only G61. G61.1 and G64 NOT SUPPORTED.
00514   // [17. Set distance mode ]: N/A. Only G91.1. G90.1 NOT SUPPORTED.
00515   // [18. Set retract mode ]: NOT SUPPORTED.
00516 
00517   // [19. Remaining non-modal actions ]: Check go to predefined position, set G10, or set axis offsets.
00518   // NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these
00519   // commands all treat axis words differently. G10 as absolute offsets or computes current position as
00520   // the axis value, G92 similarly to G10 L20, and G28/30 as an intermediate target position that observes
00521   // all the current coordinate system and G92 offsets.
00522   switch (gc_block.non_modal_command) {
00523     case NON_MODAL_SET_COORDINATE_DATA:
00524       // [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.)
00525       // [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing.
00526       // [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing.
00527       if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS) }; // [No axis words]
00528       if (bit_isfalse(value_words,((1<<WORD_P)|(1<<WORD_L)))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P/L word missing]
00529       coord_select = truncf(gc_block.values.p); // Convert p value to int.
00530       if (coord_select > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]
00531       if (gc_block.values.l != 20) {
00532         if (gc_block.values.l == 2) {
00533           if (bit_istrue(value_words,bit(WORD_R))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G10 L2 R not supported]
00534         } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported L]
00535       }
00536       bit_false(value_words,(bit(WORD_L)|bit(WORD_P)));
00537 
00538       // Determine coordinate system to change and try to load from EEPROM.
00539       if (coord_select > 0) { coord_select--; } // Adjust P1-P6 index to EEPROM coordinate data indexing.
00540       else { coord_select = gc_block.modal.coord_select; } // Index P0 as the active coordinate system
00541       
00542       // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
00543       if (!settings_read_coord_data(coord_select,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); } // [EEPROM read fail]
00544 
00545       // Pre-calculate the coordinate data changes.
00546       for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.
00547         // Update axes defined only in block. Always in machine coordinates. Can change non-active system.
00548         if (bit_istrue(axis_words,bit(idx)) ) {
00549           if (gc_block.values.l == 20) {
00550             // L20: Update coordinate system axis at current position (with modifiers) with programmed value
00551             // WPos = MPos - WCS - G92 - TLO  ->  WCS = MPos - G92 - TLO - WPos
00552             gc_block.values.ijk[idx] = gc_state.position[idx]-gc_state.coord_offset[idx]-gc_block.values.xyz[idx];
00553             if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.ijk[idx] -= gc_state.tool_length_offset; }
00554           } else {
00555             // L2: Update coordinate system axis to programmed value.
00556             gc_block.values.ijk[idx] = gc_block.values.xyz[idx];
00557           }
00558         } // Else, keep current stored value.
00559       }
00560       break;
00561     case NON_MODAL_SET_COORDINATE_OFFSET:
00562       // [G92 Errors]: No axis words.
00563       if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
00564 
00565       // Update axes defined only in block. Offsets current system to defined value. Does not update when
00566       // active coordinate system is selected, but is still active unless G92.1 disables it.
00567       for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.
00568         if (bit_istrue(axis_words,bit(idx)) ) {
00569           // WPos = MPos - WCS - G92 - TLO  ->  G92 = MPos - WCS - TLO - WPos
00570           gc_block.values.xyz[idx] = gc_state.position[idx]-block_coord_system[idx]-gc_block.values.xyz[idx];
00571           if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] -= gc_state.tool_length_offset; }
00572         } else {
00573           gc_block.values.xyz[idx] = gc_state.coord_offset[idx];
00574         }
00575       }
00576       break;
00577 
00578     default:
00579 
00580       // At this point, the rest of the explicit axis commands treat the axis values as the traditional
00581       // target position with the coordinate system offsets, G92 offsets, absolute override, and distance
00582       // modes applied. This includes the motion mode commands. We can now pre-compute the target position.
00583       // NOTE: Tool offsets may be appended to these conversions when/if this feature is added.
00584       if (axis_command != AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // TLO block any axis command.
00585         if (axis_words) {
00586           for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space.
00587             if ( bit_isfalse(axis_words,bit(idx)) ) {
00588               gc_block.values.xyz[idx] = gc_state.position[idx]; // No axis word in block. Keep same axis position.
00589             } else {
00590               // Update specified value according to distance mode or ignore if absolute override is active.
00591               // NOTE: G53 is never active with G28/30 since they are in the same modal group.
00592               if (gc_block.non_modal_command != NON_MODAL_ABSOLUTE_OVERRIDE) {
00593                 // Apply coordinate offsets based on distance mode.
00594                 if (gc_block.modal.distance == DISTANCE_MODE_ABSOLUTE) {
00595                   gc_block.values.xyz[idx] += block_coord_system[idx] + gc_state.coord_offset[idx];
00596                   if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] += gc_state.tool_length_offset; }
00597                 } else {  // Incremental mode
00598                   gc_block.values.xyz[idx] += gc_state.position[idx];
00599                 }
00600               }
00601             }
00602           }
00603         }
00604       }
00605 
00606       // Check remaining non-modal commands for errors.
00607       switch (gc_block.non_modal_command) {
00608         case NON_MODAL_GO_HOME_0: // G28
00609         case NON_MODAL_GO_HOME_1: // G30
00610           // [G28/30 Errors]: Cutter compensation is enabled.
00611           // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM
00612           // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
00613           if (gc_block.non_modal_command == NON_MODAL_GO_HOME_0) {
00614             if (!settings_read_coord_data(SETTING_INDEX_G28,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); }
00615           } else { // == NON_MODAL_GO_HOME_1
00616             if (!settings_read_coord_data(SETTING_INDEX_G30,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); }
00617           }
00618           if (axis_words) {
00619             // Move only the axes specified in secondary move.
00620             for (idx=0; idx<N_AXIS; idx++) {
00621               if (!(axis_words & (1<<idx))) { gc_block.values.ijk[idx] = gc_state.position[idx]; }
00622             }
00623           } else {
00624             axis_command = AXIS_COMMAND_NONE; // Set to none if no intermediate motion.
00625           }
00626           break;
00627         case NON_MODAL_SET_HOME_0: // G28.1
00628         case NON_MODAL_SET_HOME_1: // G30.1
00629           // [G28.1/30.1 Errors]: Cutter compensation is enabled.
00630           // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.
00631           break;
00632         case NON_MODAL_RESET_COORDINATE_OFFSET:
00633           // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.
00634           break;
00635         case NON_MODAL_ABSOLUTE_OVERRIDE:
00636           // [G53 Errors]: G0 and G1 are not active. Cutter compensation is enabled.
00637           // NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary.
00638           if (!(gc_block.modal.motion == MOTION_MODE_SEEK || gc_block.modal.motion == MOTION_MODE_LINEAR)) {
00639             FAIL(STATUS_GCODE_G53_INVALID_MOTION_MODE); // [G53 G0/1 not active]
00640           }
00641           break;
00642       }
00643   }
00644 
00645   // [20. Motion modes ]:
00646   if (gc_block.modal.motion == MOTION_MODE_NONE) {
00647     // [G80 Errors]: Axis word are programmed while G80 is active.
00648     // NOTE: Even non-modal commands or TLO that use axis words will throw this strict error.
00649     if (axis_words) { FAIL(STATUS_GCODE_AXIS_WORDS_EXIST); } // [No axis words allowed]
00650 
00651   // Check remaining motion modes, if axis word are implicit (exist and not used by G10/28/30/92), or
00652   // was explicitly commanded in the g-code block.
00653   } else if ( axis_command == AXIS_COMMAND_MOTION_MODE ) {
00654 
00655     if (gc_block.modal.motion == MOTION_MODE_SEEK) {
00656       // [G0 Errors]: Axis letter not configured or without real value (done.)
00657       // Axis words are optional. If missing, set axis command flag to ignore execution.
00658       if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
00659 
00660     // All remaining motion modes (all but G0 and G80), require a valid feed rate value. In units per mm mode,
00661     // the value must be positive. In inverse time mode, a positive value must be passed with each block.
00662     } else {
00663       // Check if feed rate is defined for the motion modes that require it.
00664       if (gc_block.values.f == 0.0f) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [Feed rate undefined]
00665 
00666       switch (gc_block.modal.motion) {
00667         case MOTION_MODE_LINEAR:
00668           // [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value.
00669           // Axis words are optional. If missing, set axis command flag to ignore execution.
00670           if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
00671 
00672           break;
00673         case MOTION_MODE_CW_ARC: 
00674           gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; // No break intentional.
00675         case MOTION_MODE_CCW_ARC:
00676           // [G2/3 Errors All-Modes]: Feed rate undefined.
00677           // [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current.
00678           // [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current
00679           //   point and the radius to the target point differs more than 0.002mm (EMC def. 0.5mm OR 0.005mm and 0.1% radius).
00680           // [G2/3 Full-Circle-Mode Errors]: NOT SUPPORTED. Axis words exist. No offsets programmed. P must be an integer.
00681           // NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking.
00682 
00683           if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
00684           if (!(axis_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE); } // [No axis words in plane]
00685 
00686           // Calculate the change in position along each selected axis
00687           float x,y;
00688           x = gc_block.values.xyz[axis_0]-gc_state.position[axis_0]; // Delta x between current position and target
00689           y = gc_block.values.xyz[axis_1]-gc_state.position[axis_1]; // Delta y between current position and target
00690 
00691           if (value_words & bit(WORD_R)) { // Arc Radius Mode
00692             bit_false(value_words,bit(WORD_R));
00693             if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
00694 
00695             // Convert radius value to proper units.
00696             if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.r *= MM_PER_INCH; }
00697             /*  We need to calculate the center of the circle that has the designated radius and passes
00698                 through both the current position and the target position. This method calculates the following
00699                 set of equations where [x,y] is the vector from current to target position, d == magnitude of
00700                 that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to
00701                 the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the
00702                 length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point
00703                 [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc.
00704 
00705                 d^2 == x^2 + y^2
00706                 h^2 == r^2 - (d/2)^2
00707                 i == x/2 - y/d*h
00708                 j == y/2 + x/d*h
00709 
00710                                                                      O <- [i,j]
00711                                                                   -  |
00712                                                         r      -     |
00713                                                             -        |
00714                                                          -           | h
00715                                                       -              |
00716                                         [0,0] ->  C -----------------+--------------- T  <- [x,y]
00717                                                   | <------ d/2 ---->|
00718 
00719                 C - Current position
00720                 T - Target position
00721                 O - center of circle that pass through both C and T
00722                 d - distance from C to T
00723                 r - designated radius
00724                 h - distance from center of CT to O
00725 
00726                 Expanding the equations:
00727 
00728                 d -> sqrt(x^2 + y^2)
00729                 h -> sqrt(4 * r^2 - x^2 - y^2)/2
00730                 i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
00731                 j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
00732 
00733                 Which can be written:
00734 
00735                 i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
00736                 j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
00737 
00738                 Which we for size and speed reasons optimize to:
00739 
00740                 h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2)
00741                 i = (x - (y * h_x2_div_d))/2
00742                 j = (y + (x * h_x2_div_d))/2
00743             */
00744 
00745             // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller
00746             // than d. If so, the sqrt of a negative number is complex and error out.
00747             float h_x2_div_d = 4.0f * gc_block.values.r*gc_block.values.r - x*x - y*y;
00748 
00749             if (h_x2_div_d < 0) { FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); } // [Arc radius error]
00750 
00751             // Finish computing h_x2_div_d.
00752             h_x2_div_d = -sqrtf(h_x2_div_d)/hypot_f(x,y); // == -(h * 2 / d)
00753             // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
00754             if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }
00755 
00756             /* The counter clockwise circle lies to the left of the target direction. When offset is positive,
00757                the left hand circle will be generated - when it is negative the right hand circle is generated.
00758 
00759                                                                    T  <-- Target position
00760 
00761                                                                    ^
00762                         Clockwise circles with this center         |          Clockwise circles with this center will have
00763                         will have > 180 deg of angular travel      |          < 180 deg of angular travel, which is a good thing!
00764                                                          \         |          /
00765             center of arc when h_x2_div_d is positive ->  x <----- | -----> x <- center of arc when h_x2_div_d is negative
00766                                                                    |
00767                                                                    |
00768 
00769                                                                    C  <-- Current position
00770             */
00771             // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!),
00772             // even though it is advised against ever generating such circles in a single line of g-code. By
00773             // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of
00774             // travel and thus we get the unadvisably long arcs as prescribed.
00775             if (gc_block.values.r < 0) {
00776                 h_x2_div_d = -h_x2_div_d;
00777                 gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc
00778             }
00779             // Complete the operation by calculating the actual center of the arc
00780             gc_block.values.ijk[axis_0] = 0.5f*(x-(y*h_x2_div_d));
00781             gc_block.values.ijk[axis_1] = 0.5f*(y+(x*h_x2_div_d));
00782 
00783           } else { // Arc Center Format Offset Mode
00784             if (!(ijk_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_OFFSETS_IN_PLANE); } // [No offsets in plane]
00785             bit_false(value_words,(bit(WORD_I)|bit(WORD_J)|bit(WORD_K)));
00786 
00787             // Convert IJK values to proper units.
00788             if (gc_block.modal.units == UNITS_MODE_INCHES) {
00789               for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space.
00790                 if (ijk_words & bit(idx)) { gc_block.values.ijk[idx] *= MM_PER_INCH; }
00791               }
00792             }
00793 
00794             // Arc radius from center to target
00795             x -= gc_block.values.ijk[axis_0]; // Delta x between circle center and target
00796             y -= gc_block.values.ijk[axis_1]; // Delta y between circle center and target
00797             float target_r = hypot_f(x,y);
00798 
00799             // Compute arc radius for mc_arc. Defined from current location to center.
00800             gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]);
00801 
00802             // Compute difference between current location and target radii for final error-checks.
00803             float delta_r = fabsf(target_r-gc_block.values.r);
00804             if (delta_r > 0.005f) {
00805               if (delta_r > 0.5f) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.5mm
00806               if (delta_r > (0.001f*gc_block.values.r)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.005mm AND 0.1% radius
00807             }
00808           }
00809           break;
00810         case MOTION_MODE_PROBE_TOWARD_NO_ERROR: case MOTION_MODE_PROBE_AWAY_NO_ERROR:
00811             gc_parser_flags |= GC_PARSER_PROBE_IS_NO_ERROR; // No break intentional.
00812         case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_AWAY:
00813             if ((gc_block.modal.motion == MOTION_MODE_PROBE_AWAY) ||
00814                 (gc_block.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) { gc_parser_flags |= GC_PARSER_PROBE_IS_AWAY; }
00815           // [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate
00816           //   is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning
00817           //   an error, it issues an alarm to prevent further motion to the probe. It's also done there to
00818           //   allow the planner buffer to empty and move off the probe trigger before another probing cycle.
00819           if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
00820           if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
00821           break;
00822       }
00823     }
00824   }
00825 
00826   // [21. Program flow ]: No error checks required.
00827 
00828   // [0. Non-specific error-checks]: Complete unused value words check, i.e. IJK used when in arc
00829   // radius mode, or axis words that aren't used in the block.
00830   if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
00831       // Jogging only uses the F feed rate and XYZ value words. N is valid, but S and T are invalid.
00832       bit_false(value_words, (bit(WORD_N) | bit(WORD_F)));
00833   } else {
00834       bit_false(value_words, (bit(WORD_N) | bit(WORD_F) | bit(WORD_S) | bit(WORD_T))); // Remove single-meaning value words.
00835   }
00836   if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words.
00837   if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words]
00838 
00839   /* -------------------------------------------------------------------------------------
00840      STEP 4: EXECUTE!!
00841      Assumes that all error-checking has been completed and no failure modes exist. We just
00842      need to update the state and execute the block according to the order-of-execution.
00843   */
00844 
00845   // Initialize planner data struct for motion blocks.
00846   plan_line_data_t plan_data;
00847   plan_line_data_t *pl_data = &plan_data;
00848   memset(pl_data,0,sizeof(plan_line_data_t)); // Zero pl_data struct
00849 
00850                                               // Intercept jog commands and complete error checking for valid jog commands and execute.
00851                                               // NOTE: G-code parser state is not updated, except the position to ensure sequential jog
00852                                               // targets are computed correctly. The final parser position after a jog is updated in
00853                                               // protocol_execute_realtime() when jogging completes or is canceled.
00854   if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
00855       // Only distance and unit modal commands and G53 absolute override command are allowed.
00856       // NOTE: Feed rate word and axis word checks have already been performed in STEP 3.
00857       if (command_words & ~(bit(MODAL_GROUP_G3) | bit(MODAL_GROUP_G6 | bit(MODAL_GROUP_G0)))) { FAIL(STATUS_INVALID_JOG_COMMAND) };
00858       if (!(gc_block.non_modal_command == NON_MODAL_ABSOLUTE_OVERRIDE || gc_block.non_modal_command == NON_MODAL_NO_ACTION)) { FAIL(STATUS_INVALID_JOG_COMMAND); }
00859 
00860       // Initialize planner data to current spindle and coolant modal state.
00861       pl_data->spindle_speed = gc_state.spindle_speed;
00862       plan_data.condition = (gc_state.modal.spindle | gc_state.modal.coolant);
00863 
00864       uint8_t status = jog_execute(&plan_data, &gc_block);
00865       if (status == STATUS_OK) { memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); }
00866       return(status);
00867   }
00868 
00869   // If in laser mode, setup laser power based on current and past parser conditions.
00870   if (bit_istrue(settings.flags, BITFLAG_LASER_MODE)) {
00871       if (!((gc_block.modal.motion == MOTION_MODE_LINEAR) || (gc_block.modal.motion == MOTION_MODE_CW_ARC)
00872           || (gc_block.modal.motion == MOTION_MODE_CCW_ARC))) {
00873           gc_parser_flags |= GC_PARSER_LASER_DISABLE;
00874       }
00875 
00876       // Any motion mode with axis words is allowed to be passed from a spindle speed update. 
00877       // NOTE: G1 and G0 without axis words sets axis_command to none. G28/30 are intentionally omitted.
00878       // TODO: Check sync conditions for M3 enabled motions that don't enter the planner. (zero length).
00879       if (axis_words && (axis_command == AXIS_COMMAND_MOTION_MODE)) {
00880         gc_parser_flags |= GC_PARSER_LASER_ISMOTION;
00881       }
00882       else {
00883         // M3 constant power laser requires planner syncs to update the laser when changing between
00884         // a G1/2/3 motion mode state and vice versa when there is no motion in the line.
00885         if (gc_state.modal.spindle == SPINDLE_ENABLE_CW) {
00886           if ((gc_state.modal.motion == MOTION_MODE_LINEAR) || (gc_state.modal.motion == MOTION_MODE_CW_ARC)
00887             || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
00888             if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) {
00889               gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode.
00890             }
00891           }
00892           else {
00893             // When changing to a G1 motion mode without axis words from a non-G1/2/3 motion mode.
00894             if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_DISABLE)) {
00895               gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC;
00896             }
00897           }
00898         }
00899       }
00900   }
00901 
00902   // [0. Non-specific/common error-checks and miscellaneous setup]:
00903   // NOTE: If no line number is present, the value is zero.
00904   gc_state.line_number = gc_block.values.n;
00905   #ifdef USE_LINE_NUMBERS
00906     pl_data->line_number = gc_state.line_number; // Record data for planner use.
00907   #endif
00908 
00909   // [1. Comments feedback ]:  NOT SUPPORTED
00910 
00911   // [2. Set feed rate mode ]:
00912   gc_state.modal.feed_rate = gc_block.modal.feed_rate;
00913   if (gc_state.modal.feed_rate) { pl_data->condition |= PL_COND_FLAG_INVERSE_TIME; } // Set condition flag for planner use.
00914 
00915   // [3. Set feed rate ]:
00916   gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking.
00917   pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use.
00918 
00919   // [4. Set spindle speed ]:
00920   if ((gc_state.spindle_speed != gc_block.values.s) || bit_istrue(gc_parser_flags, GC_PARSER_LASER_FORCE_SYNC)) {
00921       if (gc_state.modal.spindle != SPINDLE_DISABLE) {
00922 #ifdef VARIABLE_SPINDLE
00923         if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_ISMOTION)) {
00924           if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) {
00925             spindle_sync(gc_state.modal.spindle, 0.0);
00926           }
00927           else { spindle_sync(gc_state.modal.spindle, gc_block.values.s); }
00928         }
00929 #else
00930           spindle_sync(gc_state.modal.spindle, 0.0);
00931 #endif
00932       }
00933       gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state.
00934   }
00935   // NOTE: Pass zero spindle speed for all restricted laser motions.
00936   if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_DISABLE)) {
00937       pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use. 
00938   } // else { pl_data->spindle_speed = 0.0; } // Initialized as zero already.
00939 
00940   // [5. Select tool ]: NOT SUPPORTED. Only tracks tool value.
00941   gc_state.tool = gc_block.values.t;
00942 
00943   // [6. Change tool ]: NOT SUPPORTED
00944 
00945   // [7. Spindle control ]:
00946   if (gc_state.modal.spindle != gc_block.modal.spindle) {
00947     // Update spindle control and apply spindle speed when enabling it in this block.
00948     // NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data,
00949     // rather than gc_state, is used to manage laser state for non-laser motions.
00950     spindle_sync(gc_block.modal.spindle, pl_data->spindle_speed);
00951     gc_state.modal.spindle = gc_block.modal.spindle;
00952   }
00953   pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use.
00954 
00955   // [8. Coolant control ]:
00956   if (gc_state.modal.coolant != gc_block.modal.coolant) {
00957     // NOTE: Coolant M-codes are modal. Only one command per line is allowed. But, multiple states
00958     // can exist at the same time, while coolant disable clears all states.
00959     coolant_sync(gc_block.modal.coolant);
00960     if (gc_block.modal.coolant == COOLANT_DISABLE) { gc_state.modal.coolant = COOLANT_DISABLE; }
00961     else { gc_state.modal.coolant |= gc_block.modal.coolant; }
00962   }
00963   pl_data->condition |= gc_state.modal.coolant; // Set condition flag for planner use.
00964 
00965     // [9. Override control ]: NOT SUPPORTED. Always enabled. Except for a Grbl-only parking control.
00966 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
00967     if (gc_state.modal.override != gc_block.modal.override) {
00968         gc_state.modal.override = gc_block.modal.override;
00969         mc_override_ctrl_update(gc_state.modal.override);
00970     }
00971 #endif
00972 
00973   // [10. Dwell ]:
00974   if (gc_block.non_modal_command == NON_MODAL_DWELL) { mc_dwell(gc_block.values.p); }
00975 
00976   // [11. Set active plane ]:
00977   gc_state.modal.plane_select = gc_block.modal.plane_select;
00978 
00979   // [12. Set length units ]:
00980   gc_state.modal.units = gc_block.modal.units;
00981 
00982   // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED
00983   // gc_state.modal.cutter_comp = gc_block.modal.cutter_comp; // NOTE: Not needed since always disabled.
00984 
00985   // [14. Cutter length compensation ]: G43.1 and G49 supported. G43 NOT SUPPORTED.
00986   // NOTE: If G43 were supported, its operation wouldn't be any different from G43.1 in terms
00987   // of execution. The error-checking step would simply load the offset value into the correct
00988   // axis of the block XYZ value array.
00989   if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates a change.
00990     gc_state.modal.tool_length = gc_block.modal.tool_length;
00991     if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_CANCEL) { // G49
00992       gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] = 0.0f;
00993     } // else G43.1
00994     if ( gc_state.tool_length_offset != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] ) {
00995       gc_state.tool_length_offset = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS];
00996       system_flag_wco_change();
00997     }
00998   }
00999 
01000   // [15. Coordinate system selection ]:
01001   if (gc_state.modal.coord_select != gc_block.modal.coord_select) {
01002     gc_state.modal.coord_select = gc_block.modal.coord_select;
01003     memcpy(gc_state.coord_system,block_coord_system,N_AXIS*sizeof(float));
01004     system_flag_wco_change();
01005   }
01006 
01007   // [16. Set path control mode ]: G61.1/G64 NOT SUPPORTED
01008   // gc_state.modal.control = gc_block.modal.control; // NOTE: Always default.
01009 
01010   // [17. Set distance mode ]:
01011   gc_state.modal.distance = gc_block.modal.distance;
01012 
01013   // [18. Set retract mode ]: NOT SUPPORTED
01014 
01015   // [19. Go to predefined position, Set G10, or Set axis offsets ]:
01016   switch(gc_block.non_modal_command) {
01017     case NON_MODAL_SET_COORDINATE_DATA:
01018       settings_write_coord_data(coord_select,gc_block.values.ijk);
01019       // Update system coordinate system if currently active.
01020       if (gc_state.modal.coord_select == coord_select) {
01021         memcpy(gc_state.coord_system,gc_block.values.ijk,N_AXIS*sizeof(float));
01022         system_flag_wco_change();
01023       }
01024       break;
01025     case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1:
01026       // Move to intermediate position before going home. Obeys current coordinate system and offsets
01027       // and absolute and incremental modes.
01028       pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
01029       if (axis_command) { mc_line(gc_block.values.xyz, pl_data); }
01030       mc_line(gc_block.values.ijk, pl_data);
01031       memcpy(gc_state.position, gc_block.values.ijk, N_AXIS*sizeof(float));
01032       break;
01033     case NON_MODAL_SET_HOME_0:
01034       settings_write_coord_data(SETTING_INDEX_G28,gc_state.position);
01035       break;
01036     case NON_MODAL_SET_HOME_1:
01037       settings_write_coord_data(SETTING_INDEX_G30,gc_state.position);
01038       break;
01039     case NON_MODAL_SET_COORDINATE_OFFSET:
01040       memcpy(gc_state.coord_offset,gc_block.values.xyz,sizeof(gc_block.values.xyz));
01041       system_flag_wco_change();
01042       break;
01043     case NON_MODAL_RESET_COORDINATE_OFFSET:
01044       clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector.
01045       system_flag_wco_change();
01046       break;
01047   }
01048 
01049 
01050   // [20. Motion modes ]:
01051   // NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes.
01052   // Enter motion modes only if there are axis words or a motion mode command word in the block.
01053   gc_state.modal.motion = gc_block.modal.motion;
01054   if (gc_state.modal.motion != MOTION_MODE_NONE) {
01055     if (axis_command == AXIS_COMMAND_MOTION_MODE) {
01056       uint8_t gc_update_pos = GC_UPDATE_POS_TARGET;
01057       if (gc_state.modal.motion == MOTION_MODE_LINEAR) {
01058         mc_line(gc_block.values.xyz, pl_data);
01059       } else if (gc_state.modal.motion == MOTION_MODE_SEEK) {
01060         pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
01061         mc_line(gc_block.values.xyz, pl_data);
01062       } else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
01063           mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r,
01064               axis_0, axis_1, axis_linear, bit_istrue(gc_parser_flags, GC_PARSER_ARC_IS_CLOCKWISE));
01065       } else {
01066         // NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So
01067         // upon a successful probing cycle, the machine position and the returned value should be the same.
01068         #ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
01069           pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE;
01070         #endif
01071         gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags);
01072     }  
01073      
01074       // As far as the parser is concerned, the position is now == target. In reality the
01075       // motion control system might still be processing the action and the real tool position
01076       // in any intermediate location.
01077       if (gc_update_pos == GC_UPDATE_POS_TARGET) {
01078         memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[]
01079       } else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) {
01080         gc_sync_position(); // gc_state.position[] = sys_position
01081       } // == GC_UPDATE_POS_NONE
01082     }     
01083 
01084   }
01085 
01086   // [21. Program flow ]:
01087   // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
01088   // refill and can only be resumed by the cycle start run-time command.
01089   gc_state.modal.program_flow = gc_block.modal.program_flow;
01090   if (gc_state.modal.program_flow) {
01091     protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on.
01092     if (gc_state.modal.program_flow == PROGRAM_FLOW_PAUSED) {
01093       if (sys.state != STATE_CHECK_MODE) {
01094         system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause.
01095         protocol_execute_realtime(); // Execute suspend.
01096       }
01097     } else { // == PROGRAM_FLOW_COMPLETED
01098       // Upon program complete, only a subset of g-codes reset to certain defaults, according to
01099       // LinuxCNC's program end descriptions and testing. Only modal groups [G-code 1,2,3,5,7,12]
01100       // and [M-code 7,8,9] reset to [G1,G17,G90,G94,G40,G54,M5,M9,M48]. The remaining modal groups
01101       // [G-code 4,6,8,10,13,14,15] and [M-code 4,5,6] and the modal words [F,S,T,H] do not reset.
01102       gc_state.modal.motion = MOTION_MODE_LINEAR;
01103       gc_state.modal.plane_select = PLANE_SELECT_XY;
01104       gc_state.modal.distance = DISTANCE_MODE_ABSOLUTE;
01105       gc_state.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;
01106       // gc_state.modal.cutter_comp = CUTTER_COMP_DISABLE; // Not supported.
01107       gc_state.modal.coord_select = 0; // G54
01108       gc_state.modal.spindle = SPINDLE_DISABLE;
01109       gc_state.modal.coolant = COOLANT_DISABLE;
01110             #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
01111                 #ifdef DEACTIVATE_PARKING_UPON_INIT
01112                     gc_state.modal.override = OVERRIDE_DISABLED;
01113                 #else
01114                     gc_state.modal.override = OVERRIDE_PARKING_MOTION;
01115                 #endif
01116             #endif
01117 
01118       #ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END
01119         sys.f_override = DEFAULT_FEED_OVERRIDE;
01120         sys.r_override = DEFAULT_RAPID_OVERRIDE;
01121         sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE;
01122       #endif
01123 
01124       // Execute coordinate change and spindle/coolant stop.
01125       if (sys.state != STATE_CHECK_MODE) {
01126         if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) { FAIL(STATUS_SETTING_READ_FAIL); }
01127         system_flag_wco_change(); // Set to refresh immediately just in case something altered.
01128         spindle_set_state(SPINDLE_DISABLE,0.0f);
01129         coolant_set_state(COOLANT_DISABLE);
01130       }
01131       report_feedback_message(MESSAGE_PROGRAM_END);
01132     }
01133     gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow.
01134   }
01135 
01136   // TODO: % to denote start of program.
01137 
01138   return(STATUS_OK);
01139 }
01140 
01141 
01142 /*
01143   Not supported:
01144 
01145   - Canned cycles
01146   - Tool radius compensation
01147   - A,B,C-axes
01148   - Evaluation of expressions
01149   - Variables
01150   - Override control (TBD)
01151   - Tool changes
01152   - Switches
01153 
01154    (*) Indicates optional parameter, enabled through config.h and re-compile
01155    group 0 = {G92.2, G92.3} (Non modal: Cancel and re-enable G92 offsets)
01156    group 1 = {G81 - G89} (Motion modes: Canned cycles)
01157    group 4 = {M1} (Optional stop, ignored)
01158    group 6 = {M6} (Tool change)
01159    group 7 = {G41, G42} cutter radius compensation (G40 is supported)
01160    group 8 = {G43} tool length offset (G43.1/G49 are supported)
01161    group 8 = {M7*} enable mist coolant (* Compile-option)
01162      group 9 = {M48, M49, M56*} enable/disable override switches (* Compile-option)
01163      group 10 = {G98, G99} return mode canned cycles
01164    group 13 = {G61.1, G64} path control mode (G61 is supported)
01165 */