Major g-code parser overhaul. 100%* compliant. Other related updates.

- Completely overhauled the g-code parser. It’s now 100%* compliant. (*
may have some bugs). Being compliant, here are some of the major
differences.

- SMALLER and JUST AS FAST! A number of optimizations were found that
sped things up and allowed for the more thorough error-checking to be
installed without a speed hit. Trimmed a lot of ‘fat’ in the parser and
still was able to make it significantly smaller than it was.

- No default feed rate setting! Removed completely! This doesn’t exist
in the g-code standard. So, it now errors out whenever it’s undefined
for motions that require it (G1/2/3/38.2).

- Any g-code parser error expunges the ENTIRE block. This means all
information is lost and not passed on to the running state. Before some
of the states would remain, which could have led to some problems.

- If the g-code block passes all of the error-checks, the g-code state
is updated and all motions are executed according to the order of
execution.

- Changes in spindle speed, when already running, will update the
output pin accordingly. This fixes a bug, where it wouldn’t update the
speed.

- Update g-code parser error reporting. Errors now return detailed
information of what exact went wrong. The most common errors return a
short text description. For less common errors, the parser reports
‘Invalid gcode ID:20’, where 20 is a error ID. A list of error code IDs
and their descriptions will be documented for user reference elsewhere
to save flash space.

- Other notable changes:

- Added a print integer routine for uint8 variables. This saved
significant flash space by switching from a heavier universal print
integer routine.

- Saved some flash space with our own short hypotenuse calculation

- Some arc computation flash and memory optimizations.
This commit is contained in:
Sonny Jeon 2014-05-25 16:05:28 -06:00
parent 06432c9de9
commit 532c359a11
22 changed files with 1162 additions and 741 deletions

View File

@ -29,7 +29,7 @@
#define config_h #define config_h
// Default settings. Used when resetting EEPROM. Change to desired name in defaults.h // Default settings. Used when resetting EEPROM. Change to desired name in defaults.h
#define DEFAULTS_SHERLINE_5400 #define DEFAULTS_GENERIC
// Serial baud rate // Serial baud rate
#define BAUD_RATE 115200 #define BAUD_RATE 115200

View File

@ -21,6 +21,7 @@
#include "system.h" #include "system.h"
#include "coolant_control.h" #include "coolant_control.h"
#include "protocol.h" #include "protocol.h"
#include "gcode.h"
void coolant_init() void coolant_init()
@ -44,6 +45,8 @@ void coolant_stop()
void coolant_run(uint8_t mode) void coolant_run(uint8_t mode)
{ {
if (sys.state != STATE_CHECK_MODE) { return; }
protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program. protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program.
if (mode == COOLANT_FLOOD_ENABLE) { if (mode == COOLANT_FLOOD_ENABLE) {
COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT);

View File

@ -22,11 +22,6 @@
#define coolant_control_h #define coolant_control_h
#define COOLANT_MIST_ENABLE 2
#define COOLANT_FLOOD_ENABLE 1
#define COOLANT_DISABLE 0 // Must be zero.
void coolant_init(); void coolant_init();
void coolant_stop(); void coolant_stop();
void coolant_run(uint8_t mode); void coolant_run(uint8_t mode);

View File

@ -42,7 +42,6 @@
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 250.0 // mm/min
#define DEFAULT_STEPPING_INVERT_MASK 0 #define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
@ -82,7 +81,6 @@
#define DEFAULT_Y_MAX_TRAVEL 125.0 // mm #define DEFAULT_Y_MAX_TRAVEL 125.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 170.0 // mm #define DEFAULT_Z_MAX_TRAVEL 170.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 254.0 // mm/min (10 ipm)
#define DEFAULT_STEPPING_INVERT_MASK 0 #define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
@ -125,7 +123,6 @@
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 250.0
#define DEFAULT_STEPPING_INVERT_MASK 0 #define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
@ -158,17 +155,16 @@
#define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY) #define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)
#define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY) #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)
#define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z) #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)
#define DEFAULT_X_MAX_RATE 800.0 // mm/min #define DEFAULT_X_MAX_RATE 500.0 // mm/min
#define DEFAULT_Y_MAX_RATE 800.0 // mm/min #define DEFAULT_Y_MAX_RATE 500.0 // mm/min
#define DEFAULT_Z_MAX_RATE 800.0 // mm/min #define DEFAULT_Z_MAX_RATE 500.0 // mm/min
#define DEFAULT_X_ACCELERATION (15.0*60*60) // 15*60*60 mm/min^2 = 15 mm/sec^2 #define DEFAULT_X_ACCELERATION (25.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2
#define DEFAULT_Y_ACCELERATION (15.0*60*60) // 15*60*60 mm/min^2 = 15 mm/sec^2 #define DEFAULT_Y_ACCELERATION (25.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2
#define DEFAULT_Z_ACCELERATION (15.0*60*60) // 15*60*60 mm/min^2 = 15 mm/sec^2 #define DEFAULT_Z_ACCELERATION (25.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2
#define DEFAULT_X_MAX_TRAVEL 200.0 // mm #define DEFAULT_X_MAX_TRAVEL 200.0 // mm
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 250.0
#define DEFAULT_STEPPING_INVERT_MASK 0 #define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
@ -209,7 +205,6 @@
#define DEFAULT_Y_MAX_TRAVEL 180.0 // mm #define DEFAULT_Y_MAX_TRAVEL 180.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 150.0 // mm #define DEFAULT_Z_MAX_TRAVEL 150.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 1000.0 // mm/min
#define DEFAULT_STEPPING_INVERT_MASK 0 #define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT)) #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_DIRECTION_BIT))
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)

1295
gcode.c

File diff suppressed because it is too large Load Diff

167
gcode.h
View File

@ -29,68 +29,151 @@
// mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute // mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute
// a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, // a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online,
// and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc). // and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc).
#define MODAL_GROUP_NONE 0 // NOTE: Modal group define values must be sequential and starting from zero.
#define MODAL_GROUP_0 1 // [G4,G10,G28,G30,G53,G92,G92.1] Non-modal #define MODAL_GROUP_G0 0 // [G4,G10,G28,G28.1,G30,G30.1,G53,G92,G92.1] Non-modal
#define MODAL_GROUP_1 2 // [G0,G1,G2,G3,G38.2,G80] Motion #define MODAL_GROUP_G1 1 // [G0,G1,G2,G3,G38.2,G80] Motion
#define MODAL_GROUP_2 3 // [G17,G18,G19] Plane selection #define MODAL_GROUP_G2 2 // [G17,G18,G19] Plane selection
#define MODAL_GROUP_3 4 // [G90,G91] Distance mode #define MODAL_GROUP_G3 3 // [G90,G91] Distance mode
#define MODAL_GROUP_4 5 // [M0,M1,M2,M30] Stopping #define MODAL_GROUP_G5 4 // [G93,G94] Feed rate mode
#define MODAL_GROUP_5 6 // [G93,G94] Feed rate mode #define MODAL_GROUP_G6 5 // [G20,G21] Units
#define MODAL_GROUP_6 7 // [G20,G21] Units #define MODAL_GROUP_G12 6 // [G54,G55,G56,G57,G58,G59] Coordinate system selection
#define MODAL_GROUP_7 8 // [M3,M4,M5] Spindle turning
#define MODAL_GROUP_8 9 // [M7,M8,M9] Coolant control #define MODAL_GROUP_M4 7 // [M0,M1,M2,M30] Stopping
#define MODAL_GROUP_12 10 // [G54,G55,G56,G57,G58,G59] Coordinate system selection #define MODAL_GROUP_M7 8 // [M3,M4,M5] Spindle turning
#define MODAL_GROUP_M8 9 // [M7,M8,M9] Coolant control
#define OTHER_INPUT_F 10
#define OTHER_INPUT_S 11
#define OTHER_INPUT_T 12
// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used // Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used
// internally by the parser to know which command to execute. // internally by the parser to know which command to execute.
#define MOTION_MODE_SEEK 0 // G0
#define MOTION_MODE_LINEAR 1 // G1
#define MOTION_MODE_CW_ARC 2 // G2
#define MOTION_MODE_CCW_ARC 3 // G3
#define MOTION_MODE_PROBE 4 // G38.x
#define MOTION_MODE_CANCEL 5 // G80
#define PROGRAM_FLOW_RUNNING 0 // Modal Group 0: Non-modal actions
#define PROGRAM_FLOW_PAUSED 1 // M0, M1 #define NON_MODAL_NO_ACTION 0 // (Default: Must be zero)
#define PROGRAM_FLOW_COMPLETED 2 // M2, M30
#define NON_MODAL_NONE 0
#define NON_MODAL_DWELL 1 // G4 #define NON_MODAL_DWELL 1 // G4
#define NON_MODAL_SET_COORDINATE_DATA 2 // G10 #define NON_MODAL_SET_COORDINATE_DATA 2 // G10
#define NON_MODAL_GO_HOME_0 3 // G28 #define NON_MODAL_GO_HOME_0 3 // G28
#define NON_MODAL_SET_HOME_0 4 // G28.1 #define NON_MODAL_SET_HOME_0 4 // G28.1
#define NON_MODAL_GO_HOME_1 5 // G30 #define NON_MODAL_GO_HOME_1 5 // G30
#define NON_MODAL_SET_HOME_1 6 // G30.1 #define NON_MODAL_SET_HOME_1 6 // G30.1
#define NON_MODAL_SET_COORDINATE_OFFSET 7 // G92 #define NON_MODAL_ABSOLUTE_OVERRIDE 7 // G53
#define NON_MODAL_RESET_COORDINATE_OFFSET 8 //G92.1 #define NON_MODAL_SET_COORDINATE_OFFSET 8 // G92
#define NON_MODAL_RESET_COORDINATE_OFFSET 9 //G92.1
// Modal Group 1: Motion modes
#define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero)
#define MOTION_MODE_LINEAR 1 // G1
#define MOTION_MODE_CW_ARC 2 // G2
#define MOTION_MODE_CCW_ARC 3 // G3
#define MOTION_MODE_PROBE 4 // G38.2
#define MOTION_MODE_NONE 5 // G80
// Modal Group 2: Plane select
#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero)
#define PLANE_SELECT_ZX 1 // G18
#define PLANE_SELECT_YZ 2 // G19
// Modal Group 3: Distance mode
#define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero)
#define DISTANCE_MODE_INCREMENTAL 1 // G91
// Modal Group 4: Program flow
#define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero)
#define PROGRAM_FLOW_PAUSED 1 // M0, M1
#define PROGRAM_FLOW_COMPLETED 2 // M2, M30
// Modal Group 5: Feed rate mode
#define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero)
#define FEED_RATE_MODE_INVERSE_TIME 1 // G93
// Modal Group 6: Units mode
#define UNITS_MODE_MM 0 // G21 (Default: Must be zero)
#define UNITS_MODE_INCHES 1 // G20
// Modal Group 7: Spindle control
#define SPINDLE_DISABLE 0 // M5 (Default: Must be zero)
#define SPINDLE_ENABLE_CW 1 // M3
#define SPINDLE_ENABLE_CCW 2 // M4
// Modal Group 8: Coolant control
#define COOLANT_DISABLE 0 // M9 (Default: Must be zero)
#define COOLANT_MIST_ENABLE 1 // M7
#define COOLANT_FLOOD_ENABLE 2 // M8
// Modal Group 12: Active work coordinate system
// N/A: Stores coordinate system value (54-59) to change to.
#define WORD_F 0
#define WORD_I 1
#define WORD_J 2
#define WORD_K 3
#define WORD_L 4
#define WORD_N 5
#define WORD_P 6
#define WORD_R 7
#define WORD_S 8
#define WORD_T 9
#define WORD_X 10
#define WORD_Y 11
#define WORD_Z 12
// NOTE: When this struct is zeroed, the above defines set the defaults for the system.
typedef struct {
uint8_t motion; // {G0,G1,G2,G3,G80}
uint8_t feed_rate; // {G93,G94}
uint8_t units; // {G20,G21}
uint8_t distance; // {G90,G91}
uint8_t plane_select; // {G17,G18,G19}
uint8_t coord_select; // {G54,G55,G56,G57,G58,G59}
uint8_t program_flow; // {M0,M1,M2,M30}
uint8_t coolant; // {M7,M8,M9}
uint8_t spindle; // {M3,M4,M5}
} gc_modal_t;
typedef struct { typedef struct {
uint8_t status_code; // Parser status for current block float f; // Feed
uint8_t motion_mode; // {G0, G1, G2, G3, G80} float ijk[3]; // I,J,K Axis arc offsets
uint8_t inverse_feed_rate_mode; // {G93, G94} uint8_t l; // G10 or canned cycles parameters
uint8_t inches_mode; // 0 = millimeter mode, 1 = inches mode {G20, G21} int32_t n; // Line number
uint8_t absolute_mode; // 0 = relative motion, 1 = absolute motion {G90, G91} float p; // G10 or dwell parameters
uint8_t program_flow; // {M0, M1, M2, M30} // float q; // G82 peck drilling
uint8_t coolant_mode; // 0 = Disable, 1 = Flood Enable, 2 = Mist Enable {M8, M9} float r; // Arc radius
uint8_t spindle_direction; // 1 = CW, 2 = CCW, 0 = Stop {M3, M4, M5} float s; // Spindle speed
// uint8_t t; // Tool selection
float xyz[3]; // X,Y,Z Translational axes
} gc_values_t;
typedef struct {
gc_modal_t modal;
float spindle_speed; // RPM float spindle_speed; // RPM
float feed_rate; // Millimeters/min float feed_rate; // Millimeters/min
float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code
uint8_t tool; uint8_t tool;
uint8_t plane_axis_0,
plane_axis_1, float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code
plane_axis_2; // The axes of the selected plane
uint8_t coord_select; // Active work coordinate system number. Default: 0=G54.
float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine
// position in mm. Loaded from EEPROM when called. // position in mm. Loaded from EEPROM when called.
float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to
// machine zero in mm. Non-persistent. Cleared upon reset and boot. // machine zero in mm. Non-persistent. Cleared upon reset and boot.
float arc_radius;
float arc_offset[N_AXIS];
} parser_state_t; } parser_state_t;
extern parser_state_t gc; extern parser_state_t gc_state;
typedef struct {
// uint16_t command_words; // NOTE: If this bitflag variable fills, G and M words can be separated.
// uint16_t value_words;
uint8_t non_modal_command;
gc_modal_t modal;
gc_values_t values;
} parser_block_t;
extern parser_block_t gc_block;
// Initialize the parser // Initialize the parser
void gc_init(); void gc_init();

View File

@ -97,16 +97,15 @@ void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate)
// of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal // of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal
// distance from segment to the circle when the end points both lie on the circle. // distance from segment to the circle when the end points both lie on the circle.
#ifdef USE_LINE_NUMBERS #ifdef USE_LINE_NUMBERS
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise, int32_t line_number) uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, int32_t line_number)
#else #else
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise) uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear)
#endif #endif
{ {
float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis0 = position[axis_0] + offset[axis_0];
float center_axis1 = position[axis_1] + offset[axis_1]; float center_axis1 = position[axis_1] + offset[axis_1];
float linear_travel = target[axis_linear] - position[axis_linear];
float r_axis0 = -offset[axis_0]; // Radius vector from center to current location float r_axis0 = -offset[axis_0]; // Radius vector from center to current location
float r_axis1 = -offset[axis_1]; float r_axis1 = -offset[axis_1];
float rt_axis0 = target[axis_0] - center_axis0; float rt_axis0 = target[axis_0] - center_axis0;
@ -114,7 +113,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
// CCW angle between position and target from circle center. Only one atan2() trig computation required. // CCW angle between position and target from circle center. Only one atan2() trig computation required.
float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1); float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
if (isclockwise) { // Correct atan2 output per direction if (gc_state.modal.motion == MOTION_MODE_CW_ARC) { // Correct atan2 output per direction
if (angular_travel >= 0) { angular_travel -= 2*M_PI; } if (angular_travel >= 0) { angular_travel -= 2*M_PI; }
} else { } else {
if (angular_travel <= 0) { angular_travel += 2*M_PI; } if (angular_travel <= 0) { angular_travel += 2*M_PI; }
@ -123,10 +122,8 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
// NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to // NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to
// (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit
// is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation. // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation.
// Computes: mm_per_arc_segment = sqrt(4*arc_tolerance*(2*radius-arc_tolerance)), // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases.
// segments = millimeters_of_travel/mm_per_arc_segment uint16_t segments = floor(fabs(0.5*angular_travel*radius)/
float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
uint16_t segments = floor(0.5*millimeters_of_travel/
sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) ); sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) );
if (segments) { if (segments) {
@ -136,7 +133,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
if (invert_feed_rate) { feed_rate *= segments; } if (invert_feed_rate) { feed_rate *= segments; }
float theta_per_segment = angular_travel/segments; float theta_per_segment = angular_travel/segments;
float linear_per_segment = linear_travel/segments; float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments;
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
and phi is the angle of rotation. Solution approach by Jens Geisler. and phi is the angle of rotation. Solution approach by Jens Geisler.
@ -166,17 +163,13 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0); float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0);
cos_T *= 0.5; cos_T *= 0.5;
float arc_target[N_AXIS];
float sin_Ti; float sin_Ti;
float cos_Ti; float cos_Ti;
float r_axisi; float r_axisi;
uint16_t i; uint16_t i;
uint8_t count = 0; uint8_t count = 0;
// Initialize the linear axis for (i = 1; i<segments; i++) { // Increment (segments-1).
arc_target[axis_linear] = position[axis_linear];
for (i = 1; i<segments; i++) { // Increment (segments-1)
if (count < N_ARC_CORRECTION) { if (count < N_ARC_CORRECTION) {
// Apply vector rotation matrix. ~40 usec // Apply vector rotation matrix. ~40 usec
@ -195,14 +188,14 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
} }
// Update arc_target location // Update arc_target location
arc_target[axis_0] = center_axis0 + r_axis0; position[axis_0] = center_axis0 + r_axis0;
arc_target[axis_1] = center_axis1 + r_axis1; position[axis_1] = center_axis1 + r_axis1;
arc_target[axis_linear] += linear_per_segment; position[axis_linear] += linear_per_segment;
#ifdef USE_LINE_NUMBERS #ifdef USE_LINE_NUMBERS
mc_line(arc_target, feed_rate, invert_feed_rate, line_number); mc_line(position, feed_rate, invert_feed_rate, line_number);
#else #else
mc_line(arc_target, feed_rate, invert_feed_rate); mc_line(position, feed_rate, invert_feed_rate);
#endif #endif
// Bail mid-circle on system abort. Runtime command check already performed by mc_line. // Bail mid-circle on system abort. Runtime command check already performed by mc_line.
@ -221,6 +214,8 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
// Execute dwell in seconds. // Execute dwell in seconds.
void mc_dwell(float seconds) void mc_dwell(float seconds)
{ {
if (sys.state != STATE_CHECK_MODE) { return; }
uint16_t i = floor(1000/DWELL_TIME_STEP*seconds); uint16_t i = floor(1000/DWELL_TIME_STEP*seconds);
protocol_buffer_synchronize(); protocol_buffer_synchronize();
delay_ms(floor(1000*seconds-i*DWELL_TIME_STEP)); // Delay millisecond remainder. delay_ms(floor(1000*seconds-i*DWELL_TIME_STEP)); // Delay millisecond remainder.
@ -290,7 +285,7 @@ void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate)
mc_line(target, feed_rate, invert_feed_rate); mc_line(target, feed_rate, invert_feed_rate);
#endif #endif
//TODO - make sure the probe isn't already closed // NOTE: Parser error-checking ensures the probe isn't already closed/triggered.
sys.probe_state = PROBE_ACTIVE; sys.probe_state = PROBE_ACTIVE;
sys.execute |= EXEC_CYCLE_START; sys.execute |= EXEC_CYCLE_START;
@ -328,7 +323,7 @@ void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate)
// Gcode parser position was circumvented by the this routine, so sync position now. // Gcode parser position was circumvented by the this routine, so sync position now.
gc_sync_position(); gc_sync_position();
//TODO - ouput a mandatory status update with the probe position. What if another was recently sent? // Output the probe position as message.
report_probe_parameters(); report_probe_parameters();
} }

View File

@ -38,11 +38,11 @@ void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate);
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used // the direction of helical travel, radius == circle radius, isclockwise boolean. Used
// for vector transformation direction. // for vector transformation direction.
#ifdef USE_LINE_NUMBERS #ifdef USE_LINE_NUMBERS
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise, int32_t line_number); uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, int32_t line_number);
#else #else
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise); uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear);
#endif #endif
// Dwell for a specific number of seconds // Dwell for a specific number of seconds

View File

@ -24,6 +24,7 @@
#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) #define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float)
// Extracts a floating point value from a string. The following code is based loosely on // Extracts a floating point value from a string. The following code is based loosely on
// the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely // the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely
// available conversion method examples, but has been highly optimized for Grbl. For known // available conversion method examples, but has been highly optimized for Grbl. For known
@ -31,7 +32,7 @@
// Scientific notation is officially not supported by g-code, and the 'E' character may // Scientific notation is officially not supported by g-code, and the 'E' character may
// be a g-code word on some CNC systems. So, 'E' notation will not be recognized. // be a g-code word on some CNC systems. So, 'E' notation will not be recognized.
// NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod(). // NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod().
int read_float(char *line, uint8_t *char_counter, float *float_ptr) uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr)
{ {
char *ptr = line + *char_counter; char *ptr = line + *char_counter;
unsigned char c; unsigned char c;
@ -150,3 +151,8 @@ uint8_t get_direction_mask(uint8_t axis_idx)
return(axis_mask); return(axis_mask);
} }
float hypot_f(float x, float y)
{
return(sqrt(x*x + y*y));
}

View File

@ -38,7 +38,7 @@
// Useful macros // Useful macros
#define clear_vector(a) memset(a, 0, sizeof(a)) #define clear_vector(a) memset(a, 0, sizeof(a))
#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS) #define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS)
#define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS) // #define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS)
#define max(a,b) (((a) > (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b))
@ -53,7 +53,7 @@
// Read a floating point value from a string. Line points to the input buffer, char_counter // Read a floating point value from a string. Line points to the input buffer, char_counter
// is the indexer pointing to the current character of the line, while float_ptr is // is the indexer pointing to the current character of the line, while float_ptr is
// a pointer to the result variable. Returns true when it succeeds // a pointer to the result variable. Returns true when it succeeds
int read_float(char *line, uint8_t *char_counter, float *float_ptr); uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr);
// Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms(). // Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms().
void delay_ms(uint16_t ms); void delay_ms(uint16_t ms);
@ -63,4 +63,6 @@ void delay_us(uint32_t us);
uint8_t get_direction_mask(uint8_t i); uint8_t get_direction_mask(uint8_t i);
float hypot_f(float x, float y);
#endif #endif

36
print.c
View File

@ -76,32 +76,52 @@ void print_uint8_base2(uint8_t n)
serial_write('0' + buf[i - 1]); serial_write('0' + buf[i - 1]);
} }
void print_uint32_base10(unsigned long n) void print_uint8_base10(uint8_t n)
{ {
unsigned char buf[10];
uint8_t i = 0;
if (n == 0) { if (n == 0) {
serial_write('0'); serial_write('0');
return; return;
} }
unsigned char buf[3];
uint8_t i = 0;
while (n > 0) { while (n > 0) {
buf[i++] = n % 10 + '0'; buf[i++] = n % 10 + '0';
n /= 10;
}
for (; i > 0; i--)
serial_write(buf[i - 1]);
}
void print_uint32_base10(unsigned long n)
{
if (n == 0) {
serial_write('0');
return;
}
unsigned char buf[10];
uint8_t i = 0;
while (n > 0) {
buf[i++] = n % 10;
n /= 10; n /= 10;
} }
for (; i > 0; i--) for (; i > 0; i--)
serial_write(buf[i-1]); serial_write('0' + buf[i-1]);
} }
void printInteger(long n) void printInteger(long n)
{ {
if (n < 0) { if (n < 0) {
serial_write('-'); serial_write('-');
n = -n; print_uint32_base10((-n));
} else {
print_uint32_base10(n);
} }
print_uint32_base10(n);
} }
// Convert float to string by immediately converting to a long integer, which contains // Convert float to string by immediately converting to a long integer, which contains

View File

@ -35,6 +35,8 @@ void print_uint32_base10(uint32_t n);
void print_uint8_base2(uint8_t n); void print_uint8_base2(uint8_t n);
void print_uint8_base10(uint8_t n);
void printFloat(float n); void printFloat(float n);
#endif #endif

View File

@ -30,13 +30,19 @@ void probe_init()
} }
// Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor.
uint8_t probe_get_state()
{
return(!(PROBE_PIN & PROBE_MASK));
}
// Monitors probe pin state and records the system position when detected. Called by the // Monitors probe pin state and records the system position when detected. Called by the
// stepper ISR per ISR tick. // stepper ISR per ISR tick.
// NOTE: This function must be extremely efficient as to not bog down the stepper ISR. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR.
void probe_state_monitor() void probe_state_monitor()
{ {
if (sys.probe_state == PROBE_ACTIVE) { if (sys.probe_state == PROBE_ACTIVE) {
if (!(PROBE_PIN & PROBE_MASK)) { if (probe_get_state()) {
sys.probe_state = PROBE_OFF; sys.probe_state = PROBE_OFF;
memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS); memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS);
sys.execute |= EXEC_FEED_HOLD; sys.execute |= EXEC_FEED_HOLD;

View File

@ -29,6 +29,9 @@
// Probe pin initialization routine. // Probe pin initialization routine.
void probe_init(); void probe_init();
// Returns probe pin state.
uint8_t probe_get_state();
// Monitors probe pin state and records the system position when detected. Called by the // Monitors probe pin state and records the system position when detected. Called by the
// stepper ISR per ISR tick. // stepper ISR per ISR tick.
void probe_state_monitor(); void probe_state_monitor();

View File

@ -36,37 +36,27 @@ static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
// Directs and executes one line of formatted input from protocol_process. While mostly // Directs and executes one line of formatted input from protocol_process. While mostly
// incoming streaming g-code blocks, this also directs and executes Grbl internal commands, // incoming streaming g-code blocks, this also directs and executes Grbl internal commands,
// such as settings, initiating the homing cycle, and toggling switch states. // such as settings, initiating the homing cycle, and toggling switch states.
// TODO: Eventually re-organize this function to more cleanly organize order of operations,
// which will hopefully reduce some of the current spaghetti logic and dynamic memory usage.
static void protocol_execute_line(char *line) static void protocol_execute_line(char *line)
{ {
protocol_execute_runtime(); // Runtime command check point. protocol_execute_runtime(); // Runtime command check point.
if (sys.abort) { return; } // Bail to calling function upon system abort if (sys.abort) { return; } // Bail to calling function upon system abort
uint8_t status;
if (line[0] == 0) { if (line[0] == 0) {
// Empty or comment line. Send status message for syncing purposes. // Empty or comment line. Send status message for syncing purposes.
status = STATUS_OK; report_status_message(STATUS_OK);
} else if (line[0] == '$') { } else if (line[0] == '$') {
// Grbl '$' system command // Grbl '$' system command
status = system_execute_line(line); report_status_message(system_execute_line(line));
} else if (sys.state == STATE_ALARM) {
// Everything else is gcode. Block if in alarm mode.
report_status_message(STATUS_ALARM_LOCK);
} else { } else {
// Everything else is gcode. Send to g-code parser! Block if in alarm mode. // Parse and execute g-code block!
if (sys.state == STATE_ALARM) { status = STATUS_ALARM_LOCK; } report_status_message(gc_execute_line(line));
else { status = gc_execute_line(line); }
// TODO: Separate the parsing from the g-code execution. Need to re-write the parser
// completely to do this. First parse the line completely, checking for modal group
// errors and storing all of the g-code words. Then, send the stored g-code words to
// a separate g-code executor. This will be more in-line with actual g-code protocol.
// TODO: Clean up the multi-tasking workflow with the execution of commands. It's a
// bit complicated and patch-worked. Could be made simplier to understand.
} }
report_status_message(status);
} }
@ -119,10 +109,25 @@ void protocol_main_loop()
if (c <= ' ') { if (c <= ' ') {
// Throw away whitepace and control characters // Throw away whitepace and control characters
} else if (c == '/') { } else if (c == '/') {
// Block delete not supported. Ignore character. // Block delete NOT SUPPORTED. Ignore character.
// NOTE: If supported, would simply need to check the system if block delete is enabled.
} else if (c == '(') { } else if (c == '(') {
// Enable comments flag and ignore all characters until ')' or EOL. // Enable comments flag and ignore all characters until ')' or EOL.
// NOTE: This doesn't follow the NIST definition exactly, but is good enough for now.
// In the future, we could simply remove the items within the comments, but retain the
// comment control characters, so that the g-code parser can error-check it.
iscomment = true; iscomment = true;
// } else if (c == ';') {
// Comment character to EOL NOT SUPPORTED. LinuxCNC definition. Not NIST.
// TODO: Install '%' feature
// } else if (c == '%') {
// Program start-end percent sign NOT SUPPORTED.
// NOTE: This maybe installed to tell Grbl when a program is running vs manual input,
// where, during a program, the system auto-cycle start will continue to execute
// everything until the next '%' sign. This will help fix resuming issues with certain
// functions that empty the planner buffer to execute its task on-time.
} else if (char_counter >= LINE_BUFFER_SIZE-1) { } else if (char_counter >= LINE_BUFFER_SIZE-1) {
// Detect line buffer overflow. Report error and reset line buffer. // Detect line buffer overflow. Report error and reset line buffer.
report_status_message(STATUS_OVERFLOW); report_status_message(STATUS_OVERFLOW);

122
report.c
View File

@ -51,22 +51,16 @@ void report_status_message(uint8_t status_code)
} else { } else {
printPgmString(PSTR("error: ")); printPgmString(PSTR("error: "));
switch(status_code) { switch(status_code) {
case STATUS_BAD_NUMBER_FORMAT:
printPgmString(PSTR("Bad number format")); break;
case STATUS_EXPECTED_COMMAND_LETTER: case STATUS_EXPECTED_COMMAND_LETTER:
printPgmString(PSTR("Expected command letter")); break; printPgmString(PSTR("Expected command letter")); break;
case STATUS_UNSUPPORTED_STATEMENT: case STATUS_BAD_NUMBER_FORMAT:
printPgmString(PSTR("Unsupported statement")); break; printPgmString(PSTR("Bad number format")); break;
case STATUS_ARC_RADIUS_ERROR:
printPgmString(PSTR("Invalid radius")); break;
case STATUS_MODAL_GROUP_VIOLATION:
printPgmString(PSTR("Modal group violation")); break;
case STATUS_INVALID_STATEMENT: case STATUS_INVALID_STATEMENT:
printPgmString(PSTR("Invalid statement")); break; printPgmString(PSTR("Invalid statement")); break;
case STATUS_NEGATIVE_VALUE:
printPgmString(PSTR("Value < 0")); break;
case STATUS_SETTING_DISABLED: case STATUS_SETTING_DISABLED:
printPgmString(PSTR("Setting disabled")); break; printPgmString(PSTR("Setting disabled")); break;
case STATUS_SETTING_VALUE_NEG:
printPgmString(PSTR("Value < 0.0")); break;
case STATUS_SETTING_STEP_PULSE_MIN: case STATUS_SETTING_STEP_PULSE_MIN:
printPgmString(PSTR("Value < 3 usec")); break; printPgmString(PSTR("Value < 3 usec")); break;
case STATUS_SETTING_READ_FAIL: case STATUS_SETTING_READ_FAIL:
@ -79,6 +73,18 @@ void report_status_message(uint8_t status_code)
printPgmString(PSTR("Homing not enabled")); break; printPgmString(PSTR("Homing not enabled")); break;
case STATUS_OVERFLOW: case STATUS_OVERFLOW:
printPgmString(PSTR("Line overflow")); break; printPgmString(PSTR("Line overflow")); break;
// Common g-code parser errors.
case STATUS_GCODE_MODAL_GROUP_VIOLATION:
printPgmString(PSTR("Modal group violation")); break;
case STATUS_GCODE_UNSUPPORTED_COMMAND:
printPgmString(PSTR("Unsupported command")); break;
case STATUS_GCODE_UNDEFINED_FEED_RATE:
printPgmString(PSTR("Undefined feed rate")); break;
default:
// Remaining g-code parser errors with error codes
printPgmString(PSTR("Invalid gcode ID:"));
print_uint8_base10(status_code); // Print error code for user reference
} }
printPgmString(PSTR("\r\n")); printPgmString(PSTR("\r\n"));
} }
@ -163,29 +169,28 @@ void report_grbl_settings() {
printPgmString(PSTR(" (z accel, mm/sec^2)\r\n$9=")); printFloat(-settings.max_travel[X_AXIS]); // Grbl internally store this as negative. printPgmString(PSTR(" (z accel, mm/sec^2)\r\n$9=")); printFloat(-settings.max_travel[X_AXIS]); // Grbl internally store this as negative.
printPgmString(PSTR(" (x max travel, mm)\r\n$10=")); printFloat(-settings.max_travel[Y_AXIS]); // Grbl internally store this as negative. printPgmString(PSTR(" (x max travel, mm)\r\n$10=")); printFloat(-settings.max_travel[Y_AXIS]); // Grbl internally store this as negative.
printPgmString(PSTR(" (y max travel, mm)\r\n$11=")); printFloat(-settings.max_travel[Z_AXIS]); // Grbl internally store this as negative. printPgmString(PSTR(" (y max travel, mm)\r\n$11=")); printFloat(-settings.max_travel[Z_AXIS]); // Grbl internally store this as negative.
printPgmString(PSTR(" (z max travel, mm)\r\n$12=")); printInteger(settings.pulse_microseconds); printPgmString(PSTR(" (z max travel, mm)\r\n$12=")); print_uint8_base10(settings.pulse_microseconds);
printPgmString(PSTR(" (step pulse, usec)\r\n$13=")); printFloat(settings.default_feed_rate); printPgmString(PSTR(" (step pulse, usec)\r\n$13=")); print_uint8_base10(settings.step_invert_mask);
printPgmString(PSTR(" (default feed, mm/min)\r\n$14=")); printInteger(settings.step_invert_mask);
printPgmString(PSTR(" (step port invert mask:")); print_uint8_base2(settings.step_invert_mask); printPgmString(PSTR(" (step port invert mask:")); print_uint8_base2(settings.step_invert_mask);
printPgmString(PSTR(")\r\n$15=")); printInteger(settings.dir_invert_mask); printPgmString(PSTR(")\r\n$14=")); print_uint8_base10(settings.dir_invert_mask);
printPgmString(PSTR(" (dir port invert mask:")); print_uint8_base2(settings.dir_invert_mask); printPgmString(PSTR(" (dir port invert mask:")); print_uint8_base2(settings.dir_invert_mask);
printPgmString(PSTR(")\r\n$16=")); printInteger(settings.stepper_idle_lock_time); printPgmString(PSTR(")\r\n$15=")); print_uint8_base10(settings.stepper_idle_lock_time);
printPgmString(PSTR(" (step idle delay, msec)\r\n$17=")); printFloat(settings.junction_deviation); printPgmString(PSTR(" (step idle delay, msec)\r\n$16=")); printFloat(settings.junction_deviation);
printPgmString(PSTR(" (junction deviation, mm)\r\n$18=")); printFloat(settings.arc_tolerance); printPgmString(PSTR(" (junction deviation, mm)\r\n$17=")); printFloat(settings.arc_tolerance);
printPgmString(PSTR(" (arc tolerance, mm)\r\n$19=")); printInteger(settings.decimal_places); printPgmString(PSTR(" (arc tolerance, mm)\r\n$18=")); print_uint8_base10(settings.decimal_places);
printPgmString(PSTR(" (n-decimals, int)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); printPgmString(PSTR(" (n-decimals, int)\r\n$19=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
printPgmString(PSTR(" (report inches, bool)\r\n$21=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START)); printPgmString(PSTR(" (report inches, bool)\r\n$20=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_AUTO_START));
printPgmString(PSTR(" (auto start, bool)\r\n$22=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); printPgmString(PSTR(" (auto start, bool)\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
printPgmString(PSTR(" (invert step enable, bool)\r\n$23=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)); printPgmString(PSTR(" (invert step enable, bool)\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));
printPgmString(PSTR(" (invert limit pins, bool)\r\n$24=")); printInteger(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); printPgmString(PSTR(" (invert limit pins, bool)\r\n$23=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));
printPgmString(PSTR(" (soft limits, bool)\r\n$25=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); printPgmString(PSTR(" (soft limits, bool)\r\n$24=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
printPgmString(PSTR(" (hard limits, bool)\r\n$26=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); printPgmString(PSTR(" (hard limits, bool)\r\n$25=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
printPgmString(PSTR(" (homing cycle, bool)\r\n$27=")); printInteger(settings.homing_dir_mask); printPgmString(PSTR(" (homing cycle, bool)\r\n$26=")); print_uint8_base10(settings.homing_dir_mask);
printPgmString(PSTR(" (homing dir invert mask:")); print_uint8_base2(settings.homing_dir_mask); printPgmString(PSTR(" (homing dir invert mask:")); print_uint8_base2(settings.homing_dir_mask);
printPgmString(PSTR(")\r\n$28=")); printFloat(settings.homing_feed_rate); printPgmString(PSTR(")\r\n$27=")); printFloat(settings.homing_feed_rate);
printPgmString(PSTR(" (homing feed, mm/min)\r\n$29=")); printFloat(settings.homing_seek_rate); printPgmString(PSTR(" (homing feed, mm/min)\r\n$28=")); printFloat(settings.homing_seek_rate);
printPgmString(PSTR(" (homing seek, mm/min)\r\n$30=")); printInteger(settings.homing_debounce_delay); printPgmString(PSTR(" (homing seek, mm/min)\r\n$29=")); print_uint8_base10(settings.homing_debounce_delay);
printPgmString(PSTR(" (homing debounce, msec)\r\n$31=")); printFloat(settings.homing_pulloff); printPgmString(PSTR(" (homing debounce, msec)\r\n$30=")); printFloat(settings.homing_pulloff);
printPgmString(PSTR(" (homing pull-off, mm)\r\n")); printPgmString(PSTR(" (homing pull-off, mm)\r\n"));
} }
@ -222,16 +227,11 @@ void report_ngc_parameters()
} }
printPgmString(PSTR("[G")); printPgmString(PSTR("[G"));
switch (coord_select) { switch (coord_select) {
case 0: printPgmString(PSTR("54:")); break; case 6: printPgmString(PSTR("28")); break;
case 1: printPgmString(PSTR("55:")); break; case 7: printPgmString(PSTR("30")); break;
case 2: printPgmString(PSTR("56:")); break; default: print_uint8_base10(coord_select+54); break; // G54-G59
case 3: printPgmString(PSTR("57:")); break;
case 4: printPgmString(PSTR("58:")); break;
case 5: printPgmString(PSTR("59:")); break;
case 6: printPgmString(PSTR("28:")); break;
case 7: printPgmString(PSTR("30:")); break;
// case 8: printPgmString(PSTR("92:")); break; // G92.2, G92.3 not supported. Hence not stored.
} }
printPgmString(PSTR(":"));
for (i=0; i<N_AXIS; i++) { for (i=0; i<N_AXIS; i++) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(coord_data[i]*INCH_PER_MM); } if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(coord_data[i]*INCH_PER_MM); }
else { printFloat(coord_data[i]); } else { printFloat(coord_data[i]); }
@ -241,8 +241,8 @@ void report_ngc_parameters()
} }
printPgmString(PSTR("[G92:")); // Print G92,G92.1 which are not persistent in memory printPgmString(PSTR("[G92:")); // Print G92,G92.1 which are not persistent in memory
for (i=0; i<N_AXIS; i++) { for (i=0; i<N_AXIS; i++) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(gc.coord_offset[i]*INCH_PER_MM); } if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(gc_state.coord_offset[i]*INCH_PER_MM); }
else { printFloat(gc.coord_offset[i]); } else { printFloat(gc_state.coord_offset[i]); }
if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); } if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
else { printPgmString(PSTR("]\r\n")); } else { printPgmString(PSTR("]\r\n")); }
} }
@ -253,44 +253,45 @@ void report_ngc_parameters()
// Print current gcode parser mode state // Print current gcode parser mode state
void report_gcode_modes() void report_gcode_modes()
{ {
switch (gc.motion_mode) { switch (gc_state.modal.motion) {
case MOTION_MODE_SEEK : printPgmString(PSTR("[G0")); break; case MOTION_MODE_SEEK : printPgmString(PSTR("[G0")); break;
case MOTION_MODE_LINEAR : printPgmString(PSTR("[G1")); break; case MOTION_MODE_LINEAR : printPgmString(PSTR("[G1")); break;
case MOTION_MODE_CW_ARC : printPgmString(PSTR("[G2")); break; case MOTION_MODE_CW_ARC : printPgmString(PSTR("[G2")); break;
case MOTION_MODE_CCW_ARC : printPgmString(PSTR("[G3")); break; case MOTION_MODE_CCW_ARC : printPgmString(PSTR("[G3")); break;
case MOTION_MODE_CANCEL : printPgmString(PSTR("[G80")); break; case MOTION_MODE_NONE : printPgmString(PSTR("[G80")); break;
} }
printPgmString(PSTR(" G")); printPgmString(PSTR(" G"));
printInteger(gc.coord_select+54); print_uint8_base10(gc_state.modal.coord_select+54);
if (gc.plane_axis_0 == X_AXIS) { switch (gc_state.modal.plane_select) {
if (gc.plane_axis_1 == Y_AXIS) { printPgmString(PSTR(" G17")); } case PLANE_SELECT_XY : printPgmString(PSTR(" G17")); break;
else { printPgmString(PSTR(" G18")); } case PLANE_SELECT_ZX : printPgmString(PSTR(" G18")); break;
} else { printPgmString(PSTR(" G19")); } case PLANE_SELECT_YZ : printPgmString(PSTR(" G19")); break;
}
if (gc.inches_mode) { printPgmString(PSTR(" G20")); } if (gc_state.modal.units == UNITS_MODE_MM) { printPgmString(PSTR(" G21")); }
else { printPgmString(PSTR(" G21")); } else { printPgmString(PSTR(" G20")); }
if (gc.absolute_mode) { printPgmString(PSTR(" G90")); } if (gc_state.modal.distance == DISTANCE_MODE_ABSOLUTE) { printPgmString(PSTR(" G90")); }
else { printPgmString(PSTR(" G91")); } else { printPgmString(PSTR(" G91")); }
if (gc.inverse_feed_rate_mode) { printPgmString(PSTR(" G93")); } if (gc_state.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { printPgmString(PSTR(" G93")); }
else { printPgmString(PSTR(" G94")); } else { printPgmString(PSTR(" G94")); }
switch (gc.program_flow) { switch (gc_state.modal.program_flow) {
case PROGRAM_FLOW_RUNNING : printPgmString(PSTR(" M0")); break; case PROGRAM_FLOW_RUNNING : printPgmString(PSTR(" M0")); break;
case PROGRAM_FLOW_PAUSED : printPgmString(PSTR(" M1")); break; case PROGRAM_FLOW_PAUSED : printPgmString(PSTR(" M1")); break;
case PROGRAM_FLOW_COMPLETED : printPgmString(PSTR(" M2")); break; case PROGRAM_FLOW_COMPLETED : printPgmString(PSTR(" M2")); break;
} }
switch (gc.spindle_direction) { switch (gc_state.modal.spindle) {
case SPINDLE_ENABLE_CW : printPgmString(PSTR(" M3")); break; case SPINDLE_ENABLE_CW : printPgmString(PSTR(" M3")); break;
case SPINDLE_ENABLE_CCW : printPgmString(PSTR(" M4")); break; case SPINDLE_ENABLE_CCW : printPgmString(PSTR(" M4")); break;
case SPINDLE_DISABLE : printPgmString(PSTR(" M5")); break; case SPINDLE_DISABLE : printPgmString(PSTR(" M5")); break;
} }
switch (gc.coolant_mode) { switch (gc_state.modal.coolant) {
case COOLANT_DISABLE : printPgmString(PSTR(" M9")); break; case COOLANT_DISABLE : printPgmString(PSTR(" M9")); break;
case COOLANT_FLOOD_ENABLE : printPgmString(PSTR(" M8")); break; case COOLANT_FLOOD_ENABLE : printPgmString(PSTR(" M8")); break;
#ifdef ENABLE_M7 #ifdef ENABLE_M7
@ -299,11 +300,10 @@ void report_gcode_modes()
} }
printPgmString(PSTR(" T")); printPgmString(PSTR(" T"));
printInteger(gc.tool); print_uint8_base10(gc_state.tool);
printPgmString(PSTR(" F")); printPgmString(PSTR(" F"));
if (gc.inches_mode) { printFloat(gc.feed_rate*INCH_PER_MM); } printFloat(gc_state.feed_rate);
else { printFloat(gc.feed_rate); }
printPgmString(PSTR("]\r\n")); printPgmString(PSTR("]\r\n"));
} }
@ -311,7 +311,7 @@ void report_gcode_modes()
// Prints specified startup line // Prints specified startup line
void report_startup_line(uint8_t n, char *line) void report_startup_line(uint8_t n, char *line)
{ {
printPgmString(PSTR("$N")); printInteger(n); printPgmString(PSTR("$N")); print_uint8_base10(n);
printPgmString(PSTR("=")); printString(line); printPgmString(PSTR("=")); printString(line);
printPgmString(PSTR("\r\n")); printPgmString(PSTR("\r\n"));
} }
@ -366,9 +366,9 @@ void report_realtime_status()
printPgmString(PSTR("WPos:")); printPgmString(PSTR("WPos:"));
for (i=0; i< N_AXIS; i++) { for (i=0; i< N_AXIS; i++) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
print_position[i] -= (gc.coord_system[i]+gc.coord_offset[i])*INCH_PER_MM; print_position[i] -= (gc_state.coord_system[i]+gc_state.coord_offset[i])*INCH_PER_MM;
} else { } else {
print_position[i] -= gc.coord_system[i]+gc.coord_offset[i]; print_position[i] -= gc_state.coord_system[i]+gc_state.coord_offset[i];
} }
printFloat(print_position[i]); printFloat(print_position[i]);
if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); } if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }

View File

@ -22,20 +22,36 @@
// Define Grbl status codes. // Define Grbl status codes.
#define STATUS_OK 0 #define STATUS_OK 0
#define STATUS_BAD_NUMBER_FORMAT 1 #define STATUS_EXPECTED_COMMAND_LETTER 1
#define STATUS_EXPECTED_COMMAND_LETTER 2 #define STATUS_BAD_NUMBER_FORMAT 2
#define STATUS_UNSUPPORTED_STATEMENT 3 #define STATUS_INVALID_STATEMENT 3
#define STATUS_ARC_RADIUS_ERROR 4 #define STATUS_NEGATIVE_VALUE 4
#define STATUS_MODAL_GROUP_VIOLATION 5 #define STATUS_SETTING_DISABLED 5
#define STATUS_INVALID_STATEMENT 6 #define STATUS_SETTING_STEP_PULSE_MIN 6
#define STATUS_SETTING_DISABLED 7 #define STATUS_SETTING_READ_FAIL 7
#define STATUS_SETTING_VALUE_NEG 8 #define STATUS_IDLE_ERROR 8
#define STATUS_SETTING_STEP_PULSE_MIN 9 #define STATUS_ALARM_LOCK 9
#define STATUS_SETTING_READ_FAIL 10 #define STATUS_SOFT_LIMIT_ERROR 10
#define STATUS_IDLE_ERROR 11 #define STATUS_OVERFLOW 11
#define STATUS_ALARM_LOCK 12
#define STATUS_SOFT_LIMIT_ERROR 13 #define STATUS_GCODE_UNSUPPORTED_COMMAND 20
#define STATUS_OVERFLOW 14 #define STATUS_GCODE_MODAL_GROUP_VIOLATION 21
#define STATUS_GCODE_UNDEFINED_FEED_RATE 22
#define STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER 23
#define STATUS_GCODE_AXIS_COMMAND_CONFLICT 24
#define STATUS_GCODE_WORD_REPEATED 25
#define STATUS_GCODE_NO_AXIS_WORDS 26
#define STATUS_GCODE_INVALID_LINE_NUMBER 27
#define STATUS_GCODE_VALUE_WORD_MISSING 28
#define STATUS_GCODE_UNSUPPORTED_COORD_SYS 29
#define STATUS_GCODE_G53_INVALID_MOTION_MODE 30
#define STATUS_GCODE_AXIS_WORDS_EXIST 31
#define STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE 32
#define STATUS_GCODE_INVALID_TARGET 33
#define STATUS_GCODE_ARC_RADIUS_ERROR 34
#define STATUS_GCODE_NO_OFFSETS_IN_PLANE 35
#define STATUS_GCODE_PROBE_TRIGGERED 36
#define STATUS_GCODE_UNUSED_WORDS 37
// Define Grbl alarm codes. Less than zero to distinguish alarm error from status error. // Define Grbl alarm codes. Less than zero to distinguish alarm error from status error.
#define ALARM_LIMIT_ERROR -1 #define ALARM_LIMIT_ERROR -1

View File

@ -66,7 +66,6 @@ void settings_reset() {
settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM; settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM;
settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM; settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM;
settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS; settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS;
settings.default_feed_rate = DEFAULT_FEEDRATE;
settings.max_rate[X_AXIS] = DEFAULT_X_MAX_RATE; settings.max_rate[X_AXIS] = DEFAULT_X_MAX_RATE;
settings.max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE; settings.max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE;
settings.max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE; settings.max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE;
@ -161,7 +160,7 @@ uint8_t read_global_settings() {
// A helper method to set settings from command line // A helper method to set settings from command line
uint8_t settings_store_global_setting(int parameter, float value) { uint8_t settings_store_global_setting(int parameter, float value) {
if (value < 0.0) { return(STATUS_SETTING_VALUE_NEG); } if (value < 0.0) { return(STATUS_NEGATIVE_VALUE); }
switch(parameter) { switch(parameter) {
case 0: case 1: case 2: case 0: case 1: case 2:
settings.steps_per_mm[parameter] = value; break; settings.steps_per_mm[parameter] = value; break;
@ -177,52 +176,51 @@ uint8_t settings_store_global_setting(int parameter, float value) {
case 12: case 12:
if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }
settings.pulse_microseconds = round(value); break; settings.pulse_microseconds = round(value); break;
case 13: settings.default_feed_rate = value; break; case 13: settings.step_invert_mask = trunc(value); break;
case 14: settings.step_invert_mask = trunc(value); break; case 14: settings.dir_invert_mask = trunc(value); break;
case 15: settings.dir_invert_mask = trunc(value); break; case 15: settings.stepper_idle_lock_time = round(value); break;
case 16: settings.stepper_idle_lock_time = round(value); break; case 16: settings.junction_deviation = fabs(value); break;
case 17: settings.junction_deviation = fabs(value); break; case 17: settings.arc_tolerance = value; break;
case 18: settings.arc_tolerance = value; break; case 18: settings.decimal_places = round(value); break;
case 19: settings.decimal_places = round(value); break; case 19:
case 20:
if (value) { settings.flags |= BITFLAG_REPORT_INCHES; } if (value) { settings.flags |= BITFLAG_REPORT_INCHES; }
else { settings.flags &= ~BITFLAG_REPORT_INCHES; } else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
break; break;
case 21: // Reset to ensure change. Immediate re-init may cause problems. case 20: // Reset to ensure change. Immediate re-init may cause problems.
if (value) { settings.flags |= BITFLAG_AUTO_START; } if (value) { settings.flags |= BITFLAG_AUTO_START; }
else { settings.flags &= ~BITFLAG_AUTO_START; } else { settings.flags &= ~BITFLAG_AUTO_START; }
break; break;
case 22: // Reset to ensure change. Immediate re-init may cause problems. case 21: // Reset to ensure change. Immediate re-init may cause problems.
if (value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } if (value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
break; break;
case 23: // Reset to ensure change. Immediate re-init may cause problems. case 22: // Reset to ensure change. Immediate re-init may cause problems.
if (value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; } if (value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; }
else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; } else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; }
break; break;
case 24: case 23:
if (value) { if (value) {
if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); } if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); }
settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE;
} else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; } } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; }
break; break;
case 25: case 24:
if (value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } if (value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later. limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later.
break; break;
case 26: case 25:
if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; } if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; }
else { else {
settings.flags &= ~BITFLAG_HOMING_ENABLE; settings.flags &= ~BITFLAG_HOMING_ENABLE;
settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits. settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits.
} }
break; break;
case 27: settings.homing_dir_mask = trunc(value); break; case 26: settings.homing_dir_mask = trunc(value); break;
case 28: settings.homing_feed_rate = value; break; case 27: settings.homing_feed_rate = value; break;
case 29: settings.homing_seek_rate = value; break; case 28: settings.homing_seek_rate = value; break;
case 30: settings.homing_debounce_delay = round(value); break; case 29: settings.homing_debounce_delay = round(value); break;
case 31: settings.homing_pulloff = value; break; case 30: settings.homing_pulloff = value; break;
default: default:
return(STATUS_INVALID_STATEMENT); return(STATUS_INVALID_STATEMENT);
} }

View File

@ -25,12 +25,12 @@
#include "system.h" #include "system.h"
#define GRBL_VERSION "0.9d" #define GRBL_VERSION "0.9e"
#define GRBL_VERSION_BUILD "20140228" #define GRBL_VERSION_BUILD "20140525"
// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl // Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl
// when firmware is upgraded. Always stored in byte 0 of eeprom // when firmware is upgraded. Always stored in byte 0 of eeprom
#define SETTINGS_VERSION 6 #define SETTINGS_VERSION 7
// Define bit flag masks for the boolean settings in settings.flag. // Define bit flag masks for the boolean settings in settings.flag.
#define BITFLAG_REPORT_INCHES bit(0) #define BITFLAG_REPORT_INCHES bit(0)
@ -65,7 +65,6 @@ typedef struct {
float acceleration[N_AXIS]; float acceleration[N_AXIS];
float max_travel[N_AXIS]; float max_travel[N_AXIS];
uint8_t pulse_microseconds; uint8_t pulse_microseconds;
float default_feed_rate;
uint8_t step_invert_mask; uint8_t step_invert_mask;
uint8_t dir_invert_mask; uint8_t dir_invert_mask;
uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.

View File

@ -22,6 +22,7 @@
#include "system.h" #include "system.h"
#include "spindle_control.h" #include "spindle_control.h"
#include "protocol.h" #include "protocol.h"
#include "gcode.h"
void spindle_init() void spindle_init()
@ -56,6 +57,8 @@ void spindle_stop()
void spindle_run(uint8_t direction, float rpm) void spindle_run(uint8_t direction, float rpm)
{ {
if (sys.state != STATE_CHECK_MODE) { return; }
// Empty planner buffer to ensure spindle is set when programmed. // Empty planner buffer to ensure spindle is set when programmed.
protocol_buffer_synchronize(); protocol_buffer_synchronize();

View File

@ -23,11 +23,6 @@
#define spindle_control_h #define spindle_control_h
#define SPINDLE_DISABLE 0 // Must be zero.
#define SPINDLE_ENABLE_CW 1
#define SPINDLE_ENABLE_CCW 2
// Initializes spindle pins and hardware PWM, if enabled. // Initializes spindle pins and hardware PWM, if enabled.
void spindle_init(); void spindle_init();

View File

@ -87,11 +87,11 @@ uint8_t system_execute_line(char *line)
switch( line[char_counter] ) { switch( line[char_counter] ) {
case 0 : report_grbl_help(); break; case 0 : report_grbl_help(); break;
case 'G' : // Prints gcode parser state case 'G' : // Prints gcode parser state
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
else { report_gcode_modes(); } else { report_gcode_modes(); }
break; break;
case 'C' : // Set check g-code mode [IDLE/CHECK] case 'C' : // Set check g-code mode [IDLE/CHECK]
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
// Perform reset when toggling off. Check g-code mode should only work if Grbl // Perform reset when toggling off. Check g-code mode should only work if Grbl
// is idle and ready, regardless of alarm locks. This is mainly to keep things // is idle and ready, regardless of alarm locks. This is mainly to keep things
// simple and consistent. // simple and consistent.
@ -105,7 +105,7 @@ uint8_t system_execute_line(char *line)
} }
break; break;
case 'X' : // Disable alarm lock [ALARM] case 'X' : // Disable alarm lock [ALARM]
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
if (sys.state == STATE_ALARM) { if (sys.state == STATE_ALARM) {
report_feedback_message(MESSAGE_ALARM_UNLOCK); report_feedback_message(MESSAGE_ALARM_UNLOCK);
sys.state = STATE_IDLE; sys.state = STATE_IDLE;
@ -129,11 +129,11 @@ uint8_t system_execute_line(char *line)
if ( !(sys.state == STATE_IDLE || sys.state == STATE_ALARM) ) { return(STATUS_IDLE_ERROR); } if ( !(sys.state == STATE_IDLE || sys.state == STATE_ALARM) ) { return(STATUS_IDLE_ERROR); }
switch( line[char_counter] ) { switch( line[char_counter] ) {
case '$' : // Prints Grbl settings [IDLE/ALARM] case '$' : // Prints Grbl settings [IDLE/ALARM]
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
else { report_grbl_settings(); } else { report_grbl_settings(); }
break; break;
case '#' : // Print Grbl NGC parameters case '#' : // Print Grbl NGC parameters
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
else { report_ngc_parameters(); } else { report_ngc_parameters(); }
break; break;
case 'H' : // Perform homing cycle [IDLE/ALARM] case 'H' : // Perform homing cycle [IDLE/ALARM]
@ -151,7 +151,7 @@ uint8_t system_execute_line(char *line)
report_build_info(line); report_build_info(line);
} }
} else { // Store startup line [IDLE/ALARM] } else { // Store startup line [IDLE/ALARM]
if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); } if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }
helper_var = char_counter; // Set helper variable as counter to start of user info line. helper_var = char_counter; // Set helper variable as counter to start of user info line.
do { do {
line[char_counter-helper_var] = line[char_counter]; line[char_counter-helper_var] = line[char_counter];
@ -176,7 +176,7 @@ uint8_t system_execute_line(char *line)
} }
default : // Storing setting methods [IDLE/ALARM] default : // Storing setting methods [IDLE/ALARM]
if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); } if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); }
if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); } if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }
if (helper_var) { // Store startup line if (helper_var) { // Store startup line
// Prepare sending gcode block to gcode parser by shifting all characters // Prepare sending gcode block to gcode parser by shifting all characters
helper_var = char_counter; // Set helper variable as counter to start of gcode block helper_var = char_counter; // Set helper variable as counter to start of gcode block
@ -192,7 +192,7 @@ uint8_t system_execute_line(char *line)
} }
} else { // Store global setting. } else { // Store global setting.
if(!read_float(line, &char_counter, &value)) { return(STATUS_BAD_NUMBER_FORMAT); } if(!read_float(line, &char_counter, &value)) { return(STATUS_BAD_NUMBER_FORMAT); }
if(line[char_counter] != 0) { return(STATUS_UNSUPPORTED_STATEMENT); } if(line[char_counter] != 0) { return(STATUS_INVALID_STATEMENT); }
return(settings_store_global_setting(parameter, value)); return(settings_store_global_setting(parameter, value));
} }
} }