gnea\grbl-Mega  1.0f
Source Code Documentation ( Internal Workings )
gcode.c File Reference
#include "grbl.h"

Go to the source code of this file.

Macros

#define MAX_LINE_NUMBER   10000000
 NOTE: Max line number is defined by the g-code standard to be 99999. More...
 
#define MAX_TOOL_NUMBER   255
 Limited by max unsigned 8-bit value. More...
 
#define AXIS_COMMAND_NONE   0
 
#define AXIS_COMMAND_NON_MODAL   1
 
#define AXIS_COMMAND_MOTION_MODE   2
 
#define AXIS_COMMAND_TOOL_LENGTH_OFFSET   3
 *Undefined but required More...
 
#define FAIL(status)   return(status);
 

Functions

void gc_init ()
 Initialize the parser. More...
 
void gc_sync_position ()
 Sets g-code parser position in mm. Input in steps. Called by the system abort and hard. More...
 
uint8_t gc_execute_line (char *line)
 Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase. More...
 
 if (axis_words)
 

STEP 3: Error-check all commands and values passed in this block. This step ensures all of the commands are valid for execution and follows the NIST standard as closely as possible. If an error is found, all commands and values in this block are dumped and will not update the active system g-code modes. If the block is ok, the active system g-code modes will be updated based on the commands of this block, and signal for it to be executed. More...

 
 if (bit_istrue(value_words, bit(WORD_N)))
 
 if (gc_parser_flags &GC_PARSER_JOG_MOTION)
 NOTE: Single-meaning value word. Set at end of error-checking. More...
 
 if (gc_block.modal.units==UNITS_MODE_INCHES)
 
 if (axis_command==AXIS_COMMAND_TOOL_LENGTH_OFFSET)
 NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40. More...
 
 memcpy (block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system))
 
 if (bit_istrue(command_words, bit(MODAL_GROUP_G12)))
 
 switch (gc_block.non_modal_command)
 NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these. More...
 
 if (value_words)
 [Unused words] More...
 
 memset (pl_data, 0, sizeof(plan_line_data_t))
 Zero pl_data struct. More...
 
 if (bit_istrue(settings.flags, BITFLAG_LASER_MODE))
 
 if (gc_state.modal.feed_rate)
 Set condition flag for planner use. More...
 
 if ((gc_state.spindle_speed!=gc_block.values.s)||bit_istrue(gc_parser_flags, GC_PARSER_LASER_FORCE_SYNC))
 
 if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_DISABLE))
 NOTE: Pass zero spindle speed for all restricted laser motions. More...
 
 if (gc_state.modal.spindle!=gc_block.modal.spindle)
 
 if (gc_state.modal.coolant!=gc_block.modal.coolant)
 
 if (gc_block.non_modal_command==NON_MODAL_DWELL)
 
 if (gc_state.modal.coord_select!=gc_block.modal.coord_select)
 
 if (gc_state.modal.motion!=MOTION_MODE_NONE)
 
 return (STATUS_OK)
 

Variables

parser_state_t gc_state
 Declare gc extern struct. More...
 
parser_block_t gc_block
 
 else
 Remove single-meaning value words. More...
 
float block_coord_system [N_AXIS]
 
plan_line_data_t plan_data
 

STEP 4: EXECUTE!! Assumes that all error-checking has been completed and no failure modes exist. We just need to update the state and execute the block according to the order-of-execution. More...

 
plan_line_data_tpl_data = &plan_data
 
gc_state line_number = gc_block.values.n
 NOTE: If no line number is present, the value is zero. More...
 
gc_state modal feed_rate = gc_block.modal.feed_rate
 Always copy this value. See feed rate error-checking. More...
 
gc_state tool = gc_block.values.t
 
pl_data condition = gc_state.modal.spindle
 Set condition flag for planner use. More...
 
gc_state modal plane_select = gc_block.modal.plane_select
 
gc_state modal units = gc_block.modal.units
 
gc_state modal distance = gc_block.modal.distance
 NOTE: Always default. More...
 
gc_state modal motion = gc_block.modal.motion
 NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes. More...
 
gc_state modal program_flow = gc_block.modal.program_flow
 

Macro Definition Documentation

#define AXIS_COMMAND_MOTION_MODE   2

Definition at line 32 of file gcode.c.

#define AXIS_COMMAND_NON_MODAL   1

Definition at line 31 of file gcode.c.

#define AXIS_COMMAND_NONE   0

Definition at line 30 of file gcode.c.

#define AXIS_COMMAND_TOOL_LENGTH_OFFSET   3

*Undefined but required

Definition at line 33 of file gcode.c.

#define FAIL (   status)    return(status);

Definition at line 38 of file gcode.c.

#define MAX_LINE_NUMBER   10000000

NOTE: Max line number is defined by the g-code standard to be 99999.

It seems to be an

Definition at line 27 of file gcode.c.

#define MAX_TOOL_NUMBER   255

Limited by max unsigned 8-bit value.

Definition at line 28 of file gcode.c.

Function Documentation

uint8_t gc_execute_line ( char *  line)

Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase.

Execute one block of rs275/ngc/g-code.


STEP 1: Initialize parser block struct and copy current g-code state modes. The parser updates these modes and commands as the block line is parser and will only be used and executed after successful error-checking. The parser block struct also contains a block values struct, word tracking variables, and a non-modal commands tracker for the new block. This struct contains all of the necessary information to execute the block.

< Initialize the parser block struct.

< Copy current modes

< Tracks G10 P coordinate selection for execution

< XYZ tracking

< IJK tracking

< Tracks G and M command words. Also used for modal group violations.

< Tracks value words.

<

NOTE: $J= already parsed when passed to this function.

< Initialize default line number reported during jog.


STEP 2: Import all g-code words in the block line. A g-code word is a letter followed by a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also, perform initial error-checks for command word modal group violations, for any repeated words, and for negative values set for the value words F, N, P, T, and S.

< Bit-value for assigning tracking variables

< Loop until no more g-code words in line.

NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more

< Compute mantissa for Gxx.x commands.

NOTE: Rounding must be used to catch small floating point errors.

'G' and 'M' Command Words: Parse commands and check for modal group violations.

/ NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20

< Ignore G28.1, G30.1, and G92.1

< Set to zero to indicate valid non-integer G command.

< [Unsupported G38.x command]

< Set to zero to indicate valid non-integer G command.

< Set to zero to indicate valid non-integer G command.

NOTE: Not required since cutter radius compensation is always disabled. Only here

NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed,

< G49

< G43.1

< Set to zero to indicate valid non-integer G command.

NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)

< Shift to array indexing.

< [Unsupported G command]

NOTE: Variable 'word_bit' is always assigned, if the command is valid.

< Program pause

< Optional stop not supported. Ignore.

< Program end and reset

< [Unsupported M command]

NOTE: Variable 'word_bit' is always assigned, if the command is valid.

NOTE: All remaining letters assign values.

Non-Command Words: This initial parsing phase only checks for repeats of the remaining legal g-code words and stores their value. Error-checking is performed later since some words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands.

NOTE: For certain commands, P value must be an integer, but none of these commands are supported.

NOTE: Variable 'word_bit' is always assigned, if the non-command letter is valid.

NOTE: Negative value check is done here simply for code-efficiency.

< Flag to indicate parameter assigned.

Definition at line 63 of file gcode.c.

void gc_init ( )

Initialize the parser.

Definition at line 41 of file gcode.c.

void gc_sync_position ( )

Sets g-code parser position in mm. Input in steps. Called by the system abort and hard.

Set g-code parser position. Input in steps.

Definition at line 53 of file gcode.c.

if ( axis_words  )


STEP 3: Error-check all commands and values passed in this block. This step ensures all of the commands are valid for execution and follows the NIST standard as closely as possible. If an error is found, all commands and values in this block are dumped and will not update the active system g-code modes. If the block is ok, the active system g-code modes will be updated based on the commands of this block, and signal for it to be executed.

Also, we have to pre-convert all of the values passed based on the modes set by the parsed block. There are a number of error-checks that require target information that can only be accurately calculated if we convert these values in conjunction with the error-checking. This relegates the next execution step as only updating the system g-code modes and performing the programmed actions in order. The execution step should not require any conversion calculations and would only require minimal checks necessary to execute.

/ NOTE: At this point, the g-code block has been parsed and the block line can be freed.

/ NOTE: It's also possible, at some future point, to break up STEP 2, to allow piece-wise parsing of the block on a per-word basis, rather than the entire block. This could remove the need for maintaining a large string variable for the entire block and free up some memory. To do this, this would simply need to retain all of the data in STEP 1, such as the new block data struct, the modal group and value bitflag tracking variables, and axis array indices compatible variables. This data contains all of the information necessary to error-check the new g-code block when the EOL character is received. However, this would break Grbl's startup lines in how it currently works and would require some refactoring to make it compatible.

Definition at line 367 of file gcode.c.

if ( bit_istrue(value_words, bit(WORD_N))  )

Definition at line 372 of file gcode.c.

if ( gc_parser_flags &  GC_PARSER_JOG_MOTION)

NOTE: Single-meaning value word. Set at end of error-checking.

NOTE: G-code parser state is not updated, except the position to ensure sequential jog.

NOTE: Single-meaning value words are removed all at once at the end of error-checking, because NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word.

NOTE: Feed rate word and axis word checks have already been performed in STEP 3.

Definition at line 393 of file gcode.c.

if ( gc_block.modal.  units = UNITS_MODE_INCHES)

< Axes indices are consistent, so loop may be used.

NOTE: Even non-modal commands or TLO that use axis words will throw this strict error.

Definition at line 475 of file gcode.c.

if ( axis_command  = AXIS_COMMAND_TOOL_LENGTH_OFFSET)

NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40.

NOTE: Not needed since always disabled.

Remove axis words.

NOTE: Although not explicitly stated so, G43.1 should be applied to only one valid

NOTE: If G43 were supported, its operation wouldn't be any different from G43.1 in terms

< Indicates called in block.

< No break intentional.

NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking.

< Delta x between current position and target

< Delta y between current position and target

< Arc Radius Mode

We need to calculate the center of the circle that has the designated radius and passes through both the current position and the target position. This method calculates the following set of equations where [x,y] is the vector from current to target position, d == magnitude of that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the 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 [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc.

d^2 == x^2 + y^2 h^2 == r^2 - (d/2)^2 i == x/2 - y/d*h j == y/2 + x/d*h

                                                 O <- [i,j]
                                              -  |
                                    r      -     |
                                        -        |
                                     -           | h
                                  -              |
                    [0,0] ->  C -----------------+--------------- T  <- [x,y]
                              | <------ d/2 ---->|

C - Current position T - Target position O - center of circle that pass through both C and T d - distance from C to T r - designated radius h - distance from center of CT to O

Expanding the equations:

d -> sqrt(x^2 + y^2) h -> sqrt(4 * r^2 - x^2 - y^2)/2 i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2

Which can be written:

i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2

Which we for size and speed reasons optimize to:

h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) i = (x - (y * h_x2_div_d))/2 j = (y + (x * h_x2_div_d))/2

< == -(h * 2 / d)

The counter clockwise circle lies to the left of the target direction. When offset is positive, the left hand circle will be generated - when it is negative the right hand circle is generated.

                                                T  <-- Target position

                                                ^
     Clockwise circles with this center         |          Clockwise circles with this center will have
     will have > 180 deg of angular travel      |          < 180 deg of angular travel, which is a good thing!
                                      \         |          /

center of arc when h_x2_div_d is positive -> x <–— | –—> x <- center of arc when h_x2_div_d is negative | |

C <– Current position

< Finished with r. Set to positive for mc_arc

< Arc Center Format Offset Mode

< Axes indices are consistent, so loop may be used to save flash space.

< Delta x between circle center and target

< Delta y between circle center and target

< No break intentional.

NOTE: Probe check moved to probe cycle. Instead of returning

< Indicates a change.

< G49

Definition at line 495 of file gcode.c.

if ( bit_istrue(command_words, bit(MODAL_GROUP_G12))  )

< Check if called in block

Definition at line 508 of file gcode.c.

if ( value_words  )

[Unused words]

Definition at line 849 of file gcode.c.

if ( bit_istrue(settings.flags, BITFLAG_LASER_MODE )

NOTE: G1 and G0 without axis words sets axis_command to none. G28/30 are intentionally omitted.

Todo:
Check sync conditions for M3 enabled motions that don't enter the planner. (zero length).

< Change from G1/2/3 motion mode.

Definition at line 884 of file gcode.c.

if ( gc_state.modal.  feed_rate)

Set condition flag for planner use.

< Sync and finish all remaining buffered motions before moving on.

< Use feed hold for program pause.

< Execute suspend.

< == PROGRAM_FLOW_COMPLETED

< G54

< Set to refresh immediately just in case something altered.

< Reset program flow.

Definition at line 925 of file gcode.c.

if ( (gc_state.spindle_speed!=gc_block.values.s)||bit_istrue(gc_parser_flags, GC_PARSER_LASER_FORCE_SYNC )

< Update spindle speed state.

Definition at line 932 of file gcode.c.

if ( bit_isfalse(gc_parser_flags, GC_PARSER_LASER_DISABLE )

NOTE: Pass zero spindle speed for all restricted laser motions.

else { pl_data->spindle_speed = 0.0; } //!< Initialized as zero already.

< Record data for planner use.

Definition at line 944 of file gcode.c.

if ( gc_state.modal.spindle!  = gc_block.modal.spindle)

NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data,

Definition at line 954 of file gcode.c.

if ( gc_state.modal.coolant!  = gc_block.modal.coolant)

NOTE: Coolant M-codes are modal. Only one command per line is allowed. But, multiple states

Definition at line 965 of file gcode.c.

if ( gc_block.  non_modal_command = NON_MODAL_DWELL)

Definition at line 978 of file gcode.c.

if ( gc_state.modal.coord_select!  = gc_block.modal.coord_select)

Definition at line 1007 of file gcode.c.

if ( gc_state.modal.motion!  = MOTION_MODE_NONE)

< Set rapid motion condition flag.

NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So

< gc_state.position[] = gc_block.values.xyz[]

< gc_state.position[] = sys_position

Definition at line 1062 of file gcode.c.

memcpy ( block_coord_system  ,
gc_state.  coord_system,
sizeof(gc_state.coord_system)   
)
memset ( pl_data  ,
,
sizeof(plan_line_data_t  
)

Zero pl_data struct.

return ( STATUS_OK  )
Todo:
% to denote start of program.
switch ( gc_block.  non_modal_command)

NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these.

< [No axis words]

< Convert p value to int.

NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.

< Axes indices are consistent, so loop may be used.

< Axes indices are consistent, so loop may be used.

NOTE: Tool offsets may be appended to these conversions when/if this feature is added.

< TLO block any axis command.

< Axes indices are consistent, so loop may be used to save flash space.

< No axis word in block. Keep same axis position.

NOTE: G53 is never active with G28/30 since they are in the same modal group.

< Incremental mode

< G28

< G30

NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.

< == NON_MODAL_GO_HOME_1

< Set to none if no intermediate motion.

< G28.1

< G30.1

NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.

NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.

NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary.

< [G53 G0/1 not active]

< Set rapid motion condition flag.

< Disable G92 offsets by zeroing offset vector.

Definition at line 525 of file gcode.c.

Variable Documentation

float block_coord_system[N_AXIS]
Todo:
An EEPROM read of the coordinate data may require a buffer sync when the cycle

Definition at line 506 of file gcode.c.

pl_data condition = gc_state.modal.spindle

Set condition flag for planner use.

Definition at line 962 of file gcode.c.

gc_state modal distance = gc_block.modal.distance

NOTE: Always default.

Definition at line 1018 of file gcode.c.

else

Remove single-meaning value words.

Definition at line 396 of file gcode.c.

pl_data feed_rate = gc_block.modal.feed_rate

Always copy this value. See feed rate error-checking.

Record data for planner use.

Definition at line 924 of file gcode.c.

parser_block_t gc_block

Definition at line 36 of file gcode.c.

parser_state_t gc_state

Declare gc extern struct.

Definition at line 35 of file gcode.c.

pl_data line_number = gc_block.values.n

NOTE: If no line number is present, the value is zero.

Record data for planner use.

Definition at line 918 of file gcode.c.

gc_state modal motion = gc_block.modal.motion

NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes.

Definition at line 1061 of file gcode.c.

Definition at line 859 of file gcode.c.

plan_line_data_t plan_data


STEP 4: EXECUTE!! Assumes that all error-checking has been completed and no failure modes exist. We just need to update the state and execute the block according to the order-of-execution.

Definition at line 858 of file gcode.c.

gc_state modal plane_select = gc_block.modal.plane_select

Definition at line 981 of file gcode.c.

gc_state modal program_flow = gc_block.modal.program_flow

Definition at line 1097 of file gcode.c.

gc_state tool = gc_block.values.t

Definition at line 949 of file gcode.c.

gc_state modal units = gc_block.modal.units

Definition at line 984 of file gcode.c.