blob: 57e31e590447e6f8d79cfaca28f7ecb96e7d6417 [file] [log] [blame]
Luigi Santivetti69972f92019-11-12 22:55:40 +00001/*
2 gcode.c - rs274/ngc parser.
3 Part of Grbl
4
5 Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
6 Copyright (c) 2009-2011 Simen Svale Skogsrud
7
8 Grbl is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Grbl is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Grbl. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "grbl.h"
23
24// NOTE: Max line number is defined by the g-code standard to be 99999. It seems to be an
25// arbitrary value, and some GUIs may require more. So we increased it based on a max safe
26// value when converting a float (7.2 digit precision)s to an integer.
27#define MAX_LINE_NUMBER 10000000
28#define MAX_TOOL_NUMBER 255 // Limited by max unsigned 8-bit value
29
30#define AXIS_COMMAND_NONE 0
31#define AXIS_COMMAND_NON_MODAL 1
32#define AXIS_COMMAND_MOTION_MODE 2
33#define AXIS_COMMAND_TOOL_LENGTH_OFFSET 3 // *Undefined but required
34
35// Declare gc extern struct
36parser_state_t gc_state;
37parser_block_t gc_block;
38
39#define FAIL(status) return(status);
40
41
42void gc_init()
43{
44 memset(&gc_state, 0, sizeof(parser_state_t));
45
46 // Load default G54 coordinate system.
47 if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) {
48 report_status_message(STATUS_SETTING_READ_FAIL);
49 }
50}
51
52
53// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
54// limit pull-off routines.
55void gc_sync_position()
56{
57 system_convert_array_steps_to_mpos(gc_state.position,sys_position);
58}
59
60
61// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase
62// characters and signed floating point values (no whitespace). Comments and block delete
63// characters have been removed. In this function, all units and positions are converted and
64// exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine
65// coordinates, respectively.
66uint8_t gc_execute_line(char *line)
67{
68 /* -------------------------------------------------------------------------------------
69 STEP 1: Initialize parser block struct and copy current g-code state modes. The parser
70 updates these modes and commands as the block line is parser and will only be used and
71 executed after successful error-checking. The parser block struct also contains a block
72 values struct, word tracking variables, and a non-modal commands tracker for the new
73 block. This struct contains all of the necessary information to execute the block. */
74
75 memset(&gc_block, 0, sizeof(parser_block_t)); // Initialize the parser block struct.
76 memcpy(&gc_block.modal,&gc_state.modal,sizeof(gc_modal_t)); // Copy current modes
77
78 uint8_t axis_command = AXIS_COMMAND_NONE;
79 uint8_t axis_0, axis_1, axis_linear;
80 uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution
81
82 // Initialize bitflag tracking variables for axis indices compatible operations.
83 uint8_t axis_words = 0; // XYZ tracking
84 uint8_t ijk_words = 0; // IJK tracking
85
86 // Initialize command and value words and parser flags variables.
87 uint16_t command_words = 0; // Tracks G and M command words. Also used for modal group violations.
88 uint16_t value_words = 0; // Tracks value words.
89 uint8_t gc_parser_flags = GC_PARSER_NONE;
90
91 // Determine if the line is a jogging motion or a normal g-code block.
92 if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function.
93 // Set G1 and G94 enforced modes to ensure accurate error checks.
94 gc_parser_flags |= GC_PARSER_JOG_MOTION;
95 gc_block.modal.motion = MOTION_MODE_LINEAR;
96 gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;
97 #ifdef USE_LINE_NUMBERS
98 gc_block.values.n = JOG_LINE_NUMBER; // Initialize default line number reported during jog.
99 #endif
100 }
101
102 /* -------------------------------------------------------------------------------------
103 STEP 2: Import all g-code words in the block line. A g-code word is a letter followed by
104 a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also,
105 perform initial error-checks for command word modal group violations, for any repeated
106 words, and for negative values set for the value words F, N, P, T, and S. */
107
108 uint8_t word_bit; // Bit-value for assigning tracking variables
109 uint8_t char_counter;
110 char letter;
111 float value;
112 uint8_t int_value = 0;
113 uint16_t mantissa = 0;
114 if (gc_parser_flags & GC_PARSER_JOG_MOTION) { char_counter = 3; } // Start parsing after `$J=`
115 else { char_counter = 0; }
116
117 while (line[char_counter] != 0) { // Loop until no more g-code words in line.
118
119 // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out.
120 letter = line[char_counter];
121 if((letter < 'A') || (letter > 'Z')) { FAIL(STATUS_EXPECTED_COMMAND_LETTER); } // [Expected word letter]
122 char_counter++;
123 if (!read_float(line, &char_counter, &value)) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // [Expected word value]
124
125 // Convert values to smaller uint8 significand and mantissa values for parsing this word.
126 // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more
127 // accurate than the NIST gcode requirement of x10 when used for commands, but not quite
128 // accurate enough for value words that require integers to within 0.0001. This should be
129 // a good enough comprimise and catch most all non-integer errors. To make it compliant,
130 // we would simply need to change the mantissa to int16, but this add compiled flash space.
131 // Maybe update this later.
132 int_value = trunc(value);
133 mantissa = round(100*(value - int_value)); // Compute mantissa for Gxx.x commands.
134 // NOTE: Rounding must be used to catch small floating point errors.
135
136 // Check if the g-code word is supported or errors due to modal group violations or has
137 // been repeated in the g-code block. If ok, update the command or record its value.
138 switch(letter) {
139
140 /* 'G' and 'M' Command Words: Parse commands and check for modal group violations.
141 NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */
142
143 case 'G':
144 // Determine 'G' command and its modal group
145 switch(int_value) {
146 case 10: case 28: case 30: case 92:
147 // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block.
148 // * G43.1 is also an axis command but is not explicitly defined this way.
149 if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1
150 if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
151 axis_command = AXIS_COMMAND_NON_MODAL;
152 }
153 // No break. Continues to next line.
154 case 4: case 53:
155 word_bit = MODAL_GROUP_G0;
156 gc_block.non_modal_command = int_value;
157 if ((int_value == 28) || (int_value == 30) || (int_value == 92)) {
158 if (!((mantissa == 0) || (mantissa == 10))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); }
159 gc_block.non_modal_command += mantissa;
160 mantissa = 0; // Set to zero to indicate valid non-integer G command.
161 }
162 break;
163 case 0: case 1: case 2: case 3: case 38:
164 // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.
165 // * G43.1 is also an axis command but is not explicitly defined this way.
166 if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
167 axis_command = AXIS_COMMAND_MOTION_MODE;
168 // No break. Continues to next line.
169 case 80:
170 word_bit = MODAL_GROUP_G1;
171 gc_block.modal.motion = int_value;
172 if (int_value == 38){
173 if (!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) {
174 FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]
175 }
176 gc_block.modal.motion += (mantissa/10)+100;
177 mantissa = 0; // Set to zero to indicate valid non-integer G command.
178 }
179 break;
180 case 17: case 18: case 19:
181 word_bit = MODAL_GROUP_G2;
182 gc_block.modal.plane_select = int_value - 17;
183 break;
184 case 90: case 91:
185 if (mantissa == 0) {
186 word_bit = MODAL_GROUP_G3;
187 gc_block.modal.distance = int_value - 90;
188 } else {
189 word_bit = MODAL_GROUP_G4;
190 if ((mantissa != 10) || (int_value == 90)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G90.1 not supported]
191 mantissa = 0; // Set to zero to indicate valid non-integer G command.
192 // Otherwise, arc IJK incremental mode is default. G91.1 does nothing.
193 }
194 break;
195 case 93: case 94:
196 word_bit = MODAL_GROUP_G5;
197 gc_block.modal.feed_rate = 94 - int_value;
198 break;
199 case 20: case 21:
200 word_bit = MODAL_GROUP_G6;
201 gc_block.modal.units = 21 - int_value;
202 break;
203 case 40:
204 word_bit = MODAL_GROUP_G7;
205 // NOTE: Not required since cutter radius compensation is always disabled. Only here
206 // to support G40 commands that often appear in g-code program headers to setup defaults.
207 // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40
208 break;
209 case 43: case 49:
210 word_bit = MODAL_GROUP_G8;
211 // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed,
212 // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49
213 // all are explicit axis commands, regardless if they require axis words or not.
214 if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] }
215 axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET;
216 if (int_value == 49) { // G49
217 gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL;
218 } else if (mantissa == 10) { // G43.1
219 gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
220 } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported G43.x command]
221 mantissa = 0; // Set to zero to indicate valid non-integer G command.
222 break;
223 case 54: case 55: case 56: case 57: case 58: case 59:
224 // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)
225 word_bit = MODAL_GROUP_G12;
226 gc_block.modal.coord_select = int_value - 54; // Shift to array indexing.
227 break;
228 case 61:
229 word_bit = MODAL_GROUP_G13;
230 if (mantissa != 0) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G61.1 not supported]
231 // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61
232 break;
233 default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command]
234 }
235 if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [Unsupported or invalid Gxx.x command]
236 // Check for more than one command per modal group violations in the current block
237 // NOTE: Variable 'word_bit' is always assigned, if the command is valid.
238 if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }
239 command_words |= bit(word_bit);
240 break;
241
242 case 'M':
243
244 // Determine 'M' command and its modal group
245 if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [No Mxx.x commands]
246 switch(int_value) {
247 case 0: case 1: case 2: case 30:
248 word_bit = MODAL_GROUP_M4;
249 switch(int_value) {
250 case 0: gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause
251 case 1: break; // Optional stop not supported. Ignore.
252 default: gc_block.modal.program_flow = int_value; // Program end and reset
253 }
254 break;
255 case 3: case 4: case 5:
256 word_bit = MODAL_GROUP_M7;
257 switch(int_value) {
258 case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break;
259 case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break;
260 case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break;
261 }
262 break;
263 #ifdef ENABLE_M7
264 case 7: case 8: case 9:
265 #else
266 case 8: case 9:
267 #endif
268 word_bit = MODAL_GROUP_M8;
269 switch(int_value) {
270 #ifdef ENABLE_M7
271 case 7: gc_block.modal.coolant |= COOLANT_MIST_ENABLE; break;
272 #endif
273 case 8: gc_block.modal.coolant |= COOLANT_FLOOD_ENABLE; break;
274 case 9: gc_block.modal.coolant = COOLANT_DISABLE; break; // M9 disables both M7 and M8.
275 }
276 break;
277 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
278 case 56:
279 word_bit = MODAL_GROUP_M9;
280 gc_block.modal.override = OVERRIDE_PARKING_MOTION;
281 break;
282 #endif
283 default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command]
284 }
285
286 // Check for more than one command per modal group violations in the current block
287 // NOTE: Variable 'word_bit' is always assigned, if the command is valid.
288 if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }
289 command_words |= bit(word_bit);
290 break;
291
292 // NOTE: All remaining letters assign values.
293 default:
294
295 /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining
296 legal g-code words and stores their value. Error-checking is performed later since some
297 words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */
298 switch(letter){
299 // case 'A': // Not supported
300 // case 'B': // Not supported
301 // case 'C': // Not supported
302 // case 'D': // Not supported
303 case 'F': word_bit = WORD_F; gc_block.values.f = value; break;
304 // case 'H': // Not supported
305 case 'I': word_bit = WORD_I; gc_block.values.ijk[X_AXIS] = value; ijk_words |= (1<<X_AXIS); break;
306 case 'J': word_bit = WORD_J; gc_block.values.ijk[Y_AXIS] = value; ijk_words |= (1<<Y_AXIS); break;
307 case 'K': word_bit = WORD_K; gc_block.values.ijk[Z_AXIS] = value; ijk_words |= (1<<Z_AXIS); break;
308 case 'L': word_bit = WORD_L; gc_block.values.l = int_value; break;
309 case 'N': word_bit = WORD_N; gc_block.values.n = trunc(value); break;
310 case 'P': word_bit = WORD_P; gc_block.values.p = value; break;
311 // NOTE: For certain commands, P value must be an integer, but none of these commands are supported.
312 // case 'Q': // Not supported
313 case 'R': word_bit = WORD_R; gc_block.values.r = value; break;
314 case 'S': word_bit = WORD_S; gc_block.values.s = value; break;
315 case 'T': word_bit = WORD_T;
316 if (value > MAX_TOOL_NUMBER) { FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); }
317 gc_block.values.t = int_value;
318 break;
319 case 'X': word_bit = WORD_X; gc_block.values.xyz[X_AXIS] = value; axis_words |= (1<<X_AXIS); break;
320 case 'Y': word_bit = WORD_Y; gc_block.values.xyz[Y_AXIS] = value; axis_words |= (1<<Y_AXIS); break;
321 case 'Z': word_bit = WORD_Z; gc_block.values.xyz[Z_AXIS] = value; axis_words |= (1<<Z_AXIS); break;
322 default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND);
323 }
324
325 // NOTE: Variable 'word_bit' is always assigned, if the non-command letter is valid.
326 if (bit_istrue(value_words,bit(word_bit))) { FAIL(STATUS_GCODE_WORD_REPEATED); } // [Word repeated]
327 // Check for invalid negative values for words F, N, P, T, and S.
328 // NOTE: Negative value check is done here simply for code-efficiency.
329 if ( bit(word_bit) & (bit(WORD_F)|bit(WORD_N)|bit(WORD_P)|bit(WORD_T)|bit(WORD_S)) ) {
330 if (value < 0.0) { FAIL(STATUS_NEGATIVE_VALUE); } // [Word value cannot be negative]
331 }
332 value_words |= bit(word_bit); // Flag to indicate parameter assigned.
333
334 }
335 }
336 // Parsing complete!
337
338
339 /* -------------------------------------------------------------------------------------
340 STEP 3: Error-check all commands and values passed in this block. This step ensures all of
341 the commands are valid for execution and follows the NIST standard as closely as possible.
342 If an error is found, all commands and values in this block are dumped and will not update
343 the active system g-code modes. If the block is ok, the active system g-code modes will be
344 updated based on the commands of this block, and signal for it to be executed.
345
346 Also, we have to pre-convert all of the values passed based on the modes set by the parsed
347 block. There are a number of error-checks that require target information that can only be
348 accurately calculated if we convert these values in conjunction with the error-checking.
349 This relegates the next execution step as only updating the system g-code modes and
350 performing the programmed actions in order. The execution step should not require any
351 conversion calculations and would only require minimal checks necessary to execute.
352 */
353
354 /* NOTE: At this point, the g-code block has been parsed and the block line can be freed.
355 NOTE: It's also possible, at some future point, to break up STEP 2, to allow piece-wise
356 parsing of the block on a per-word basis, rather than the entire block. This could remove
357 the need for maintaining a large string variable for the entire block and free up some memory.
358 To do this, this would simply need to retain all of the data in STEP 1, such as the new block
359 data struct, the modal group and value bitflag tracking variables, and axis array indices
360 compatible variables. This data contains all of the information necessary to error-check the
361 new g-code block when the EOL character is received. However, this would break Grbl's startup
362 lines in how it currently works and would require some refactoring to make it compatible.
363 */
364
365 // [0. Non-specific/common error-checks and miscellaneous setup]:
366
367 // Determine implicit axis command conditions. Axis words have been passed, but no explicit axis
368 // command has been sent. If so, set axis command to current motion mode.
369 if (axis_words) {
370 if (!axis_command) { axis_command = AXIS_COMMAND_MOTION_MODE; } // Assign implicit motion-mode
371 }
372
373 // Check for valid line number N value.
374 if (bit_istrue(value_words,bit(WORD_N))) {
375 // Line number value cannot be less than zero (done) or greater than max line number.
376 if (gc_block.values.n > MAX_LINE_NUMBER) { FAIL(STATUS_GCODE_INVALID_LINE_NUMBER); } // [Exceeds max line number]
377 }
378 // bit_false(value_words,bit(WORD_N)); // NOTE: Single-meaning value word. Set at end of error-checking.
379
380 // Track for unused words at the end of error-checking.
381 // NOTE: Single-meaning value words are removed all at once at the end of error-checking, because
382 // they are always used when present. This was done to save a few bytes of flash. For clarity, the
383 // single-meaning value words may be removed as they are used. Also, axis words are treated in the
384 // same way. If there is an explicit/implicit axis command, XYZ words are always used and are
385 // are removed at the end of error-checking.
386
387 // [1. Comments ]: MSG's NOT SUPPORTED. Comment handling performed by protocol.
388
389 // [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate
390 // is not defined after switching to G94 from G93.
391 // NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word.
392 if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
393 if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); }
394 if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
395 } else {
396 if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93
397 // NOTE: G38 can also operate in inverse time, but is undefined as an error. Missing F word check added here.
398 if (axis_command == AXIS_COMMAND_MOTION_MODE) {
399 if ((gc_block.modal.motion != MOTION_MODE_NONE) && (gc_block.modal.motion != MOTION_MODE_SEEK)) {
400 if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [F word missing]
401 }
402 }
403 // NOTE: It seems redundant to check for an F word to be passed after switching from G94 to G93. We would
404 // accomplish the exact same thing if the feed rate value is always reset to zero and undefined after each
405 // inverse time block, since the commands that use this value already perform undefined checks. This would
406 // also allow other commands, following this switch, to execute and not error out needlessly. This code is
407 // combined with the above feed rate mode and the below set feed rate error-checking.
408
409 // [3. Set feed rate ]: F is negative (done.)
410 // - In inverse time mode: Always implicitly zero the feed rate value before and after block completion.
411 // NOTE: If in G93 mode or switched into it from G94, just keep F value as initialized zero or passed F word
412 // value in the block. If no F word is passed with a motion command that requires a feed rate, this will error
413 // out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires
414 // a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined.
415 } else { // = G94
416 // - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value.
417 if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94
418 if (bit_istrue(value_words,bit(WORD_F))) {
419 if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
420 } else {
421 gc_block.values.f = gc_state.feed_rate; // Push last state feed rate
422 }
423 } // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value.
424 }
425 }
426 // bit_false(value_words,bit(WORD_F)); // NOTE: Single-meaning value word. Set at end of error-checking.
427
428 // [4. Set spindle speed ]: S is negative (done.)
429 if (bit_isfalse(value_words,bit(WORD_S))) { gc_block.values.s = gc_state.spindle_speed; }
430 // bit_false(value_words,bit(WORD_S)); // NOTE: Single-meaning value word. Set at end of error-checking.
431
432 // [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value.
433 // bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking.
434
435 // [6. Change tool ]: N/A
436 // [7. Spindle control ]: N/A
437 // [8. Coolant control ]: N/A
438 // [9. Override control ]: Not supported except for a Grbl-only parking motion override control.
439 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
440 if (bit_istrue(command_words,bit(MODAL_GROUP_M9))) { // Already set as enabled in parser.
441 if (bit_istrue(value_words,bit(WORD_P))) {
442 if (gc_block.values.p == 0.0) { gc_block.modal.override = OVERRIDE_DISABLED; }
443 bit_false(value_words,bit(WORD_P));
444 }
445 }
446 #endif
447
448 // [10. Dwell ]: P value missing. P is negative (done.) NOTE: See below.
449 if (gc_block.non_modal_command == NON_MODAL_DWELL) {
450 if (bit_isfalse(value_words,bit(WORD_P))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P word missing]
451 bit_false(value_words,bit(WORD_P));
452 }
453
454 // [11. Set active plane ]: N/A
455 switch (gc_block.modal.plane_select) {
456 case PLANE_SELECT_XY:
457 axis_0 = X_AXIS;
458 axis_1 = Y_AXIS;
459 axis_linear = Z_AXIS;
460 break;
461 case PLANE_SELECT_ZX:
462 axis_0 = Z_AXIS;
463 axis_1 = X_AXIS;
464 axis_linear = Y_AXIS;
465 break;
466 default: // case PLANE_SELECT_YZ:
467 axis_0 = Y_AXIS;
468 axis_1 = Z_AXIS;
469 axis_linear = X_AXIS;
470 }
471
472 // [12. Set length units ]: N/A
473 // Pre-convert XYZ coordinate values to millimeters, if applicable.
474 uint8_t idx;
475 if (gc_block.modal.units == UNITS_MODE_INCHES) {
476 for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.
477 if (bit_istrue(axis_words,bit(idx)) ) {
478 gc_block.values.xyz[idx] *= MM_PER_INCH;
479 }
480 }
481 }
482
483 // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED. Error, if enabled while G53 is active.
484 // [G40 Errors]: G2/3 arc is programmed after a G40. The linear move after disabling is less than tool diameter.
485 // NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40
486 // only for the purpose to not error when G40 is sent with a g-code program header to setup the default modes.
487
488 // [14. Cutter length compensation ]: G43 NOT SUPPORTED, but G43.1 and G49 are.
489 // [G43.1 Errors]: Motion command in same line.
490 // NOTE: Although not explicitly stated so, G43.1 should be applied to only one valid
491 // axis that is configured (in config.h). There should be an error if the configured axis
492 // is absent or if any of the other axis words are present.
493 if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates called in block.
494 if (gc_block.modal.tool_length == TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC) {
495 if (axis_words ^ (1<<TOOL_LENGTH_OFFSET_AXIS)) { FAIL(STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR); }
496 }
497 }
498
499 // [15. Coordinate system selection ]: *N/A. Error, if cutter radius comp is active.
500 // TODO: An EEPROM read of the coordinate data may require a buffer sync when the cycle
501 // is active. The read pauses the processor temporarily and may cause a rare crash. For
502 // future versions on processors with enough memory, all coordinate data should be stored
503 // in memory and written to EEPROM only when there is not a cycle active.
504 float block_coord_system[N_AXIS];
505 memcpy(block_coord_system,gc_state.coord_system,sizeof(gc_state.coord_system));
506 if ( bit_istrue(command_words,bit(MODAL_GROUP_G12)) ) { // Check if called in block
507 if (gc_block.modal.coord_select > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]
508 if (gc_state.modal.coord_select != gc_block.modal.coord_select) {
509 if (!(settings_read_coord_data(gc_block.modal.coord_select,block_coord_system))) { FAIL(STATUS_SETTING_READ_FAIL); }
510 }
511 }
512
513 // [16. Set path control mode ]: N/A. Only G61. G61.1 and G64 NOT SUPPORTED.
514 // [17. Set distance mode ]: N/A. Only G91.1. G90.1 NOT SUPPORTED.
515 // [18. Set retract mode ]: NOT SUPPORTED.
516
517 // [19. Remaining non-modal actions ]: Check go to predefined position, set G10, or set axis offsets.
518 // NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these
519 // commands all treat axis words differently. G10 as absolute offsets or computes current position as
520 // the axis value, G92 similarly to G10 L20, and G28/30 as an intermediate target position that observes
521 // all the current coordinate system and G92 offsets.
522 switch (gc_block.non_modal_command) {
523 case NON_MODAL_SET_COORDINATE_DATA:
524 // [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.)
525 // [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing.
526 // [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing.
527 if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS) }; // [No axis words]
528 if (bit_isfalse(value_words,((1<<WORD_P)|(1<<WORD_L)))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P/L word missing]
529 coord_select = trunc(gc_block.values.p); // Convert p value to int.
530 if (coord_select > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]
531 if (gc_block.values.l != 20) {
532 if (gc_block.values.l == 2) {
533 if (bit_istrue(value_words,bit(WORD_R))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G10 L2 R not supported]
534 } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported L]
535 }
536 bit_false(value_words,(bit(WORD_L)|bit(WORD_P)));
537
538 // Determine coordinate system to change and try to load from EEPROM.
539 if (coord_select > 0) { coord_select--; } // Adjust P1-P6 index to EEPROM coordinate data indexing.
540 else { coord_select = gc_block.modal.coord_select; } // Index P0 as the active coordinate system
541
542 // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
543 if (!settings_read_coord_data(coord_select,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); } // [EEPROM read fail]
544
545 // Pre-calculate the coordinate data changes.
546 for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.
547 // Update axes defined only in block. Always in machine coordinates. Can change non-active system.
548 if (bit_istrue(axis_words,bit(idx)) ) {
549 if (gc_block.values.l == 20) {
550 // L20: Update coordinate system axis at current position (with modifiers) with programmed value
551 // WPos = MPos - WCS - G92 - TLO -> WCS = MPos - G92 - TLO - WPos
552 gc_block.values.ijk[idx] = gc_state.position[idx]-gc_state.coord_offset[idx]-gc_block.values.xyz[idx];
553 if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.ijk[idx] -= gc_state.tool_length_offset; }
554 } else {
555 // L2: Update coordinate system axis to programmed value.
556 gc_block.values.ijk[idx] = gc_block.values.xyz[idx];
557 }
558 } // Else, keep current stored value.
559 }
560 break;
561 case NON_MODAL_SET_COORDINATE_OFFSET:
562 // [G92 Errors]: No axis words.
563 if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
564
565 // Update axes defined only in block. Offsets current system to defined value. Does not update when
566 // active coordinate system is selected, but is still active unless G92.1 disables it.
567 for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.
568 if (bit_istrue(axis_words,bit(idx)) ) {
569 // WPos = MPos - WCS - G92 - TLO -> G92 = MPos - WCS - TLO - WPos
570 gc_block.values.xyz[idx] = gc_state.position[idx]-block_coord_system[idx]-gc_block.values.xyz[idx];
571 if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] -= gc_state.tool_length_offset; }
572 } else {
573 gc_block.values.xyz[idx] = gc_state.coord_offset[idx];
574 }
575 }
576 break;
577
578 default:
579
580 // At this point, the rest of the explicit axis commands treat the axis values as the traditional
581 // target position with the coordinate system offsets, G92 offsets, absolute override, and distance
582 // modes applied. This includes the motion mode commands. We can now pre-compute the target position.
583 // NOTE: Tool offsets may be appended to these conversions when/if this feature is added.
584 if (axis_command != AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // TLO block any axis command.
585 if (axis_words) {
586 for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space.
587 if ( bit_isfalse(axis_words,bit(idx)) ) {
588 gc_block.values.xyz[idx] = gc_state.position[idx]; // No axis word in block. Keep same axis position.
589 } else {
590 // Update specified value according to distance mode or ignore if absolute override is active.
591 // NOTE: G53 is never active with G28/30 since they are in the same modal group.
592 if (gc_block.non_modal_command != NON_MODAL_ABSOLUTE_OVERRIDE) {
593 // Apply coordinate offsets based on distance mode.
594 if (gc_block.modal.distance == DISTANCE_MODE_ABSOLUTE) {
595 gc_block.values.xyz[idx] += block_coord_system[idx] + gc_state.coord_offset[idx];
596 if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] += gc_state.tool_length_offset; }
597 } else { // Incremental mode
598 gc_block.values.xyz[idx] += gc_state.position[idx];
599 }
600 }
601 }
602 }
603 }
604 }
605
606 // Check remaining non-modal commands for errors.
607 switch (gc_block.non_modal_command) {
608 case NON_MODAL_GO_HOME_0: // G28
609 case NON_MODAL_GO_HOME_1: // G30
610 // [G28/30 Errors]: Cutter compensation is enabled.
611 // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM
612 // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
613 if (gc_block.non_modal_command == NON_MODAL_GO_HOME_0) {
614 if (!settings_read_coord_data(SETTING_INDEX_G28,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); }
615 } else { // == NON_MODAL_GO_HOME_1
616 if (!settings_read_coord_data(SETTING_INDEX_G30,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); }
617 }
618 if (axis_words) {
619 // Move only the axes specified in secondary move.
620 for (idx=0; idx<N_AXIS; idx++) {
621 if (!(axis_words & (1<<idx))) { gc_block.values.ijk[idx] = gc_state.position[idx]; }
622 }
623 } else {
624 axis_command = AXIS_COMMAND_NONE; // Set to none if no intermediate motion.
625 }
626 break;
627 case NON_MODAL_SET_HOME_0: // G28.1
628 case NON_MODAL_SET_HOME_1: // G30.1
629 // [G28.1/30.1 Errors]: Cutter compensation is enabled.
630 // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.
631 break;
632 case NON_MODAL_RESET_COORDINATE_OFFSET:
633 // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.
634 break;
635 case NON_MODAL_ABSOLUTE_OVERRIDE:
636 // [G53 Errors]: G0 and G1 are not active. Cutter compensation is enabled.
637 // NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary.
638 if (!(gc_block.modal.motion == MOTION_MODE_SEEK || gc_block.modal.motion == MOTION_MODE_LINEAR)) {
639 FAIL(STATUS_GCODE_G53_INVALID_MOTION_MODE); // [G53 G0/1 not active]
640 }
641 break;
642 }
643 }
644
645 // [20. Motion modes ]:
646 if (gc_block.modal.motion == MOTION_MODE_NONE) {
647 // [G80 Errors]: Axis word are programmed while G80 is active.
648 // NOTE: Even non-modal commands or TLO that use axis words will throw this strict error.
649 if (axis_words) { FAIL(STATUS_GCODE_AXIS_WORDS_EXIST); } // [No axis words allowed]
650
651 // Check remaining motion modes, if axis word are implicit (exist and not used by G10/28/30/92), or
652 // was explicitly commanded in the g-code block.
653 } else if ( axis_command == AXIS_COMMAND_MOTION_MODE ) {
654
655 if (gc_block.modal.motion == MOTION_MODE_SEEK) {
656 // [G0 Errors]: Axis letter not configured or without real value (done.)
657 // Axis words are optional. If missing, set axis command flag to ignore execution.
658 if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
659
660 // All remaining motion modes (all but G0 and G80), require a valid feed rate value. In units per mm mode,
661 // the value must be positive. In inverse time mode, a positive value must be passed with each block.
662 } else {
663 // Check if feed rate is defined for the motion modes that require it.
664 if (gc_block.values.f == 0.0) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [Feed rate undefined]
665
666 switch (gc_block.modal.motion) {
667 case MOTION_MODE_LINEAR:
668 // [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value.
669 // Axis words are optional. If missing, set axis command flag to ignore execution.
670 if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
671 break;
672 case MOTION_MODE_CW_ARC:
673 gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; // No break intentional.
674 case MOTION_MODE_CCW_ARC:
675 // [G2/3 Errors All-Modes]: Feed rate undefined.
676 // [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current.
677 // [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current
678 // point and the radius to the target point differs more than 0.002mm (EMC def. 0.5mm OR 0.005mm and 0.1% radius).
679 // [G2/3 Full-Circle-Mode Errors]: NOT SUPPORTED. Axis words exist. No offsets programmed. P must be an integer.
680 // NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking.
681
682 if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
683 if (!(axis_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE); } // [No axis words in plane]
684
685 // Calculate the change in position along each selected axis
686 float x,y;
687 x = gc_block.values.xyz[axis_0]-gc_state.position[axis_0]; // Delta x between current position and target
688 y = gc_block.values.xyz[axis_1]-gc_state.position[axis_1]; // Delta y between current position and target
689
690 if (value_words & bit(WORD_R)) { // Arc Radius Mode
691 bit_false(value_words,bit(WORD_R));
692 if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
693
694 // Convert radius value to proper units.
695 if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.r *= MM_PER_INCH; }
696 /* We need to calculate the center of the circle that has the designated radius and passes
697 through both the current position and the target position. This method calculates the following
698 set of equations where [x,y] is the vector from current to target position, d == magnitude of
699 that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to
700 the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the
701 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
702 [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc.
703
704 d^2 == x^2 + y^2
705 h^2 == r^2 - (d/2)^2
706 i == x/2 - y/d*h
707 j == y/2 + x/d*h
708
709 O <- [i,j]
710 - |
711 r - |
712 - |
713 - | h
714 - |
715 [0,0] -> C -----------------+--------------- T <- [x,y]
716 | <------ d/2 ---->|
717
718 C - Current position
719 T - Target position
720 O - center of circle that pass through both C and T
721 d - distance from C to T
722 r - designated radius
723 h - distance from center of CT to O
724
725 Expanding the equations:
726
727 d -> sqrt(x^2 + y^2)
728 h -> sqrt(4 * r^2 - x^2 - y^2)/2
729 i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
730 j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
731
732 Which can be written:
733
734 i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
735 j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
736
737 Which we for size and speed reasons optimize to:
738
739 h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2)
740 i = (x - (y * h_x2_div_d))/2
741 j = (y + (x * h_x2_div_d))/2
742 */
743
744 // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller
745 // than d. If so, the sqrt of a negative number is complex and error out.
746 float h_x2_div_d = 4.0 * gc_block.values.r*gc_block.values.r - x*x - y*y;
747
748 if (h_x2_div_d < 0) { FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); } // [Arc radius error]
749
750 // Finish computing h_x2_div_d.
751 h_x2_div_d = -sqrt(h_x2_div_d)/hypot_f(x,y); // == -(h * 2 / d)
752 // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
753 if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }
754
755 /* The counter clockwise circle lies to the left of the target direction. When offset is positive,
756 the left hand circle will be generated - when it is negative the right hand circle is generated.
757
758 T <-- Target position
759
760 ^
761 Clockwise circles with this center | Clockwise circles with this center will have
762 will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing!
763 \ | /
764 center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative
765 |
766 |
767
768 C <-- Current position
769 */
770 // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!),
771 // even though it is advised against ever generating such circles in a single line of g-code. By
772 // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of
773 // travel and thus we get the unadvisably long arcs as prescribed.
774 if (gc_block.values.r < 0) {
775 h_x2_div_d = -h_x2_div_d;
776 gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc
777 }
778 // Complete the operation by calculating the actual center of the arc
779 gc_block.values.ijk[axis_0] = 0.5*(x-(y*h_x2_div_d));
780 gc_block.values.ijk[axis_1] = 0.5*(y+(x*h_x2_div_d));
781
782 } else { // Arc Center Format Offset Mode
783 if (!(ijk_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_OFFSETS_IN_PLANE); } // [No offsets in plane]
784 bit_false(value_words,(bit(WORD_I)|bit(WORD_J)|bit(WORD_K)));
785
786 // Convert IJK values to proper units.
787 if (gc_block.modal.units == UNITS_MODE_INCHES) {
788 for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space.
789 if (ijk_words & bit(idx)) { gc_block.values.ijk[idx] *= MM_PER_INCH; }
790 }
791 }
792
793 // Arc radius from center to target
794 x -= gc_block.values.ijk[axis_0]; // Delta x between circle center and target
795 y -= gc_block.values.ijk[axis_1]; // Delta y between circle center and target
796 float target_r = hypot_f(x,y);
797
798 // Compute arc radius for mc_arc. Defined from current location to center.
799 gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]);
800
801 // Compute difference between current location and target radii for final error-checks.
802 float delta_r = fabs(target_r-gc_block.values.r);
803 if (delta_r > 0.005) {
804 if (delta_r > 0.5) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.5mm
805 if (delta_r > (0.001*gc_block.values.r)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.005mm AND 0.1% radius
806 }
807 }
808 break;
809 case MOTION_MODE_PROBE_TOWARD_NO_ERROR: case MOTION_MODE_PROBE_AWAY_NO_ERROR:
810 gc_parser_flags |= GC_PARSER_PROBE_IS_NO_ERROR; // No break intentional.
811 case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_AWAY:
812 if ((gc_block.modal.motion == MOTION_MODE_PROBE_AWAY) ||
813 (gc_block.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) { gc_parser_flags |= GC_PARSER_PROBE_IS_AWAY; }
814 // [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate
815 // is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning
816 // an error, it issues an alarm to prevent further motion to the probe. It's also done there to
817 // allow the planner buffer to empty and move off the probe trigger before another probing cycle.
818 if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
819 if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
820 break;
821 }
822 }
823 }
824
825 // [21. Program flow ]: No error checks required.
826
827 // [0. Non-specific error-checks]: Complete unused value words check, i.e. IJK used when in arc
828 // radius mode, or axis words that aren't used in the block.
829 if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
830 // Jogging only uses the F feed rate and XYZ value words. N is valid, but S and T are invalid.
831 bit_false(value_words,(bit(WORD_N)|bit(WORD_F)));
832 } else {
833 bit_false(value_words,(bit(WORD_N)|bit(WORD_F)|bit(WORD_S)|bit(WORD_T))); // Remove single-meaning value words.
834 }
835 if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words.
836 if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words]
837
838 /* -------------------------------------------------------------------------------------
839 STEP 4: EXECUTE!!
840 Assumes that all error-checking has been completed and no failure modes exist. We just
841 need to update the state and execute the block according to the order-of-execution.
842 */
843
844 // Initialize planner data struct for motion blocks.
845 plan_line_data_t plan_data;
846 plan_line_data_t *pl_data = &plan_data;
847 memset(pl_data,0,sizeof(plan_line_data_t)); // Zero pl_data struct
848
849 // Intercept jog commands and complete error checking for valid jog commands and execute.
850 // NOTE: G-code parser state is not updated, except the position to ensure sequential jog
851 // targets are computed correctly. The final parser position after a jog is updated in
852 // protocol_execute_realtime() when jogging completes or is canceled.
853 if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
854 // Only distance and unit modal commands and G53 absolute override command are allowed.
855 // NOTE: Feed rate word and axis word checks have already been performed in STEP 3.
856 if (command_words & ~(bit(MODAL_GROUP_G3) | bit(MODAL_GROUP_G6) | bit(MODAL_GROUP_G0)) ) { FAIL(STATUS_INVALID_JOG_COMMAND) };
857 if (!(gc_block.non_modal_command == NON_MODAL_ABSOLUTE_OVERRIDE || gc_block.non_modal_command == NON_MODAL_NO_ACTION)) { FAIL(STATUS_INVALID_JOG_COMMAND); }
858
859 // Initialize planner data to current spindle and coolant modal state.
860 pl_data->spindle_speed = gc_state.spindle_speed;
861 plan_data.condition = (gc_state.modal.spindle | gc_state.modal.coolant);
862
863 uint8_t status = jog_execute(&plan_data, &gc_block);
864 if (status == STATUS_OK) { memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); }
865 return(status);
866 }
867
868 // If in laser mode, setup laser power based on current and past parser conditions.
869 if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) {
870 if ( !((gc_block.modal.motion == MOTION_MODE_LINEAR) || (gc_block.modal.motion == MOTION_MODE_CW_ARC)
871 || (gc_block.modal.motion == MOTION_MODE_CCW_ARC)) ) {
872 gc_parser_flags |= GC_PARSER_LASER_DISABLE;
873 }
874
875 // Any motion mode with axis words is allowed to be passed from a spindle speed update.
876 // NOTE: G1 and G0 without axis words sets axis_command to none. G28/30 are intentionally omitted.
877 // TODO: Check sync conditions for M3 enabled motions that don't enter the planner. (zero length).
878 if (axis_words && (axis_command == AXIS_COMMAND_MOTION_MODE)) {
879 gc_parser_flags |= GC_PARSER_LASER_ISMOTION;
880 } else {
881 // M3 constant power laser requires planner syncs to update the laser when changing between
882 // a G1/2/3 motion mode state and vice versa when there is no motion in the line.
883 if (gc_state.modal.spindle == SPINDLE_ENABLE_CW) {
884 if ((gc_state.modal.motion == MOTION_MODE_LINEAR) || (gc_state.modal.motion == MOTION_MODE_CW_ARC)
885 || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
886 if (bit_istrue(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
887 gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode.
888 }
889 } else {
890 // When changing to a G1 motion mode without axis words from a non-G1/2/3 motion mode.
891 if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
892 gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC;
893 }
894 }
895 }
896 }
897 }
898
899 // [0. Non-specific/common error-checks and miscellaneous setup]:
900 // NOTE: If no line number is present, the value is zero.
901 gc_state.line_number = gc_block.values.n;
902 #ifdef USE_LINE_NUMBERS
903 pl_data->line_number = gc_state.line_number; // Record data for planner use.
904 #endif
905
906 // [1. Comments feedback ]: NOT SUPPORTED
907
908 // [2. Set feed rate mode ]:
909 gc_state.modal.feed_rate = gc_block.modal.feed_rate;
910 if (gc_state.modal.feed_rate) { pl_data->condition |= PL_COND_FLAG_INVERSE_TIME; } // Set condition flag for planner use.
911
912 // [3. Set feed rate ]:
913 gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking.
914 pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use.
915
916 // [4. Set spindle speed ]:
917 if ((gc_state.spindle_speed != gc_block.values.s) || bit_istrue(gc_parser_flags,GC_PARSER_LASER_FORCE_SYNC)) {
918 if (gc_state.modal.spindle != SPINDLE_DISABLE) {
919 #ifdef VARIABLE_SPINDLE
920 if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_ISMOTION)) {
921 if (bit_istrue(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
922 spindle_sync(gc_state.modal.spindle, 0.0);
923 } else { spindle_sync(gc_state.modal.spindle, gc_block.values.s); }
924 }
925 #else
926 spindle_sync(gc_state.modal.spindle, 0.0);
927 #endif
928 }
929 gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state.
930 }
931 // NOTE: Pass zero spindle speed for all restricted laser motions.
932 if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
933 pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use.
934 } // else { pl_data->spindle_speed = 0.0; } // Initialized as zero already.
935
936 // [5. Select tool ]: NOT SUPPORTED. Only tracks tool value.
937 gc_state.tool = gc_block.values.t;
938
939 // [6. Change tool ]: NOT SUPPORTED
940
941 // [7. Spindle control ]:
942 if (gc_state.modal.spindle != gc_block.modal.spindle) {
943 // Update spindle control and apply spindle speed when enabling it in this block.
944 // NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data,
945 // rather than gc_state, is used to manage laser state for non-laser motions.
946 spindle_sync(gc_block.modal.spindle, pl_data->spindle_speed);
947 gc_state.modal.spindle = gc_block.modal.spindle;
948 }
949 pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use.
950
951 // [8. Coolant control ]:
952 if (gc_state.modal.coolant != gc_block.modal.coolant) {
953 // NOTE: Coolant M-codes are modal. Only one command per line is allowed. But, multiple states
954 // can exist at the same time, while coolant disable clears all states.
955 coolant_sync(gc_block.modal.coolant);
956 gc_state.modal.coolant = gc_block.modal.coolant;
957 }
958 pl_data->condition |= gc_state.modal.coolant; // Set condition flag for planner use.
959
960 // [9. Override control ]: NOT SUPPORTED. Always enabled. Except for a Grbl-only parking control.
961 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
962 if (gc_state.modal.override != gc_block.modal.override) {
963 gc_state.modal.override = gc_block.modal.override;
964 mc_override_ctrl_update(gc_state.modal.override);
965 }
966 #endif
967
968 // [10. Dwell ]:
969 if (gc_block.non_modal_command == NON_MODAL_DWELL) { mc_dwell(gc_block.values.p); }
970
971 // [11. Set active plane ]:
972 gc_state.modal.plane_select = gc_block.modal.plane_select;
973
974 // [12. Set length units ]:
975 gc_state.modal.units = gc_block.modal.units;
976
977 // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED
978 // gc_state.modal.cutter_comp = gc_block.modal.cutter_comp; // NOTE: Not needed since always disabled.
979
980 // [14. Cutter length compensation ]: G43.1 and G49 supported. G43 NOT SUPPORTED.
981 // NOTE: If G43 were supported, its operation wouldn't be any different from G43.1 in terms
982 // of execution. The error-checking step would simply load the offset value into the correct
983 // axis of the block XYZ value array.
984 if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates a change.
985 gc_state.modal.tool_length = gc_block.modal.tool_length;
986 if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_CANCEL) { // G49
987 gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] = 0.0;
988 } // else G43.1
989 if ( gc_state.tool_length_offset != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] ) {
990 gc_state.tool_length_offset = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS];
991 system_flag_wco_change();
992 }
993 }
994
995 // [15. Coordinate system selection ]:
996 if (gc_state.modal.coord_select != gc_block.modal.coord_select) {
997 gc_state.modal.coord_select = gc_block.modal.coord_select;
998 memcpy(gc_state.coord_system,block_coord_system,N_AXIS*sizeof(float));
999 system_flag_wco_change();
1000 }
1001
1002 // [16. Set path control mode ]: G61.1/G64 NOT SUPPORTED
1003 // gc_state.modal.control = gc_block.modal.control; // NOTE: Always default.
1004
1005 // [17. Set distance mode ]:
1006 gc_state.modal.distance = gc_block.modal.distance;
1007
1008 // [18. Set retract mode ]: NOT SUPPORTED
1009
1010 // [19. Go to predefined position, Set G10, or Set axis offsets ]:
1011 switch(gc_block.non_modal_command) {
1012 case NON_MODAL_SET_COORDINATE_DATA:
1013 settings_write_coord_data(coord_select,gc_block.values.ijk);
1014 // Update system coordinate system if currently active.
1015 if (gc_state.modal.coord_select == coord_select) {
1016 memcpy(gc_state.coord_system,gc_block.values.ijk,N_AXIS*sizeof(float));
1017 system_flag_wco_change();
1018 }
1019 break;
1020 case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1:
1021 // Move to intermediate position before going home. Obeys current coordinate system and offsets
1022 // and absolute and incremental modes.
1023 pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
1024 if (axis_command) { mc_line(gc_block.values.xyz, pl_data); }
1025 mc_line(gc_block.values.ijk, pl_data);
1026 memcpy(gc_state.position, gc_block.values.ijk, N_AXIS*sizeof(float));
1027 break;
1028 case NON_MODAL_SET_HOME_0:
1029 settings_write_coord_data(SETTING_INDEX_G28,gc_state.position);
1030 break;
1031 case NON_MODAL_SET_HOME_1:
1032 settings_write_coord_data(SETTING_INDEX_G30,gc_state.position);
1033 break;
1034 case NON_MODAL_SET_COORDINATE_OFFSET:
1035 memcpy(gc_state.coord_offset,gc_block.values.xyz,sizeof(gc_block.values.xyz));
1036 system_flag_wco_change();
1037 break;
1038 case NON_MODAL_RESET_COORDINATE_OFFSET:
1039 clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector.
1040 system_flag_wco_change();
1041 break;
1042 }
1043
1044
1045 // [20. Motion modes ]:
1046 // NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes.
1047 // Enter motion modes only if there are axis words or a motion mode command word in the block.
1048 gc_state.modal.motion = gc_block.modal.motion;
1049 if (gc_state.modal.motion != MOTION_MODE_NONE) {
1050 if (axis_command == AXIS_COMMAND_MOTION_MODE) {
1051 uint8_t gc_update_pos = GC_UPDATE_POS_TARGET;
1052 if (gc_state.modal.motion == MOTION_MODE_LINEAR) {
1053 mc_line(gc_block.values.xyz, pl_data);
1054 } else if (gc_state.modal.motion == MOTION_MODE_SEEK) {
1055 pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
1056 mc_line(gc_block.values.xyz, pl_data);
1057 } else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
1058 mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r,
1059 axis_0, axis_1, axis_linear, bit_istrue(gc_parser_flags,GC_PARSER_ARC_IS_CLOCKWISE));
1060 } else {
1061 // NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So
1062 // upon a successful probing cycle, the machine position and the returned value should be the same.
1063 #ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
1064 pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE;
1065 #endif
1066 gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags);
1067 }
1068
1069 // As far as the parser is concerned, the position is now == target. In reality the
1070 // motion control system might still be processing the action and the real tool position
1071 // in any intermediate location.
1072 if (gc_update_pos == GC_UPDATE_POS_TARGET) {
1073 memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[]
1074 } else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) {
1075 gc_sync_position(); // gc_state.position[] = sys_position
1076 } // == GC_UPDATE_POS_NONE
1077 }
1078 }
1079
1080 // [21. Program flow ]:
1081 // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
1082 // refill and can only be resumed by the cycle start run-time command.
1083 gc_state.modal.program_flow = gc_block.modal.program_flow;
1084 if (gc_state.modal.program_flow) {
1085 protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on.
1086 if (gc_state.modal.program_flow == PROGRAM_FLOW_PAUSED) {
1087 if (sys.state != STATE_CHECK_MODE) {
1088 system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause.
1089 protocol_execute_realtime(); // Execute suspend.
1090 }
1091 } else { // == PROGRAM_FLOW_COMPLETED
1092 // Upon program complete, only a subset of g-codes reset to certain defaults, according to
1093 // LinuxCNC's program end descriptions and testing. Only modal groups [G-code 1,2,3,5,7,12]
1094 // and [M-code 7,8,9] reset to [G1,G17,G90,G94,G40,G54,M5,M9,M48]. The remaining modal groups
1095 // [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.
1096 gc_state.modal.motion = MOTION_MODE_LINEAR;
1097 gc_state.modal.plane_select = PLANE_SELECT_XY;
1098 gc_state.modal.distance = DISTANCE_MODE_ABSOLUTE;
1099 gc_state.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;
1100 // gc_state.modal.cutter_comp = CUTTER_COMP_DISABLE; // Not supported.
1101 gc_state.modal.coord_select = 0; // G54
1102 gc_state.modal.spindle = SPINDLE_DISABLE;
1103 gc_state.modal.coolant = COOLANT_DISABLE;
1104 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
1105 #ifdef DEACTIVATE_PARKING_UPON_INIT
1106 gc_state.modal.override = OVERRIDE_DISABLED;
1107 #else
1108 gc_state.modal.override = OVERRIDE_PARKING_MOTION;
1109 #endif
1110 #endif
1111
1112 #ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END
1113 sys.f_override = DEFAULT_FEED_OVERRIDE;
1114 sys.r_override = DEFAULT_RAPID_OVERRIDE;
1115 sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE;
1116 #endif
1117
1118 // Execute coordinate change and spindle/coolant stop.
1119 if (sys.state != STATE_CHECK_MODE) {
1120 if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) { FAIL(STATUS_SETTING_READ_FAIL); }
1121 system_flag_wco_change(); // Set to refresh immediately just in case something altered.
1122 spindle_set_state(SPINDLE_DISABLE,0.0);
1123 coolant_set_state(COOLANT_DISABLE);
1124 }
1125 report_feedback_message(MESSAGE_PROGRAM_END);
1126 }
1127 gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow.
1128 }
1129
1130 // TODO: % to denote start of program.
1131
1132 return(STATUS_OK);
1133}
1134
1135
1136/*
1137 Not supported:
1138
1139 - Canned cycles
1140 - Tool radius compensation
1141 - A,B,C-axes
1142 - Evaluation of expressions
1143 - Variables
1144 - Override control (TBD)
1145 - Tool changes
1146 - Switches
1147
1148 (*) Indicates optional parameter, enabled through config.h and re-compile
1149 group 0 = {G92.2, G92.3} (Non modal: Cancel and re-enable G92 offsets)
1150 group 1 = {G81 - G89} (Motion modes: Canned cycles)
1151 group 4 = {M1} (Optional stop, ignored)
1152 group 6 = {M6} (Tool change)
1153 group 7 = {G41, G42} cutter radius compensation (G40 is supported)
1154 group 8 = {G43} tool length offset (G43.1/G49 are supported)
1155 group 8 = {M7*} enable mist coolant (* Compile-option)
1156 group 9 = {M48, M49, M56*} enable/disable override switches (* Compile-option)
1157 group 10 = {G98, G99} return mode canned cycles
1158 group 13 = {G61.1, G64} path control mode (G61 is supported)
1159*/