diff --git a/g2core/canonical_machine.cpp b/g2core/canonical_machine.cpp
index 1d07d2ae..9a885ee0 100644
--- a/g2core/canonical_machine.cpp
+++ b/g2core/canonical_machine.cpp
@@ -694,8 +694,6 @@ void canonical_machine_init()
// memset(&cm, 0, sizeof(cm)); // do not reset canonicalMachineSingleton once it's been initialized
memset(&cm, 0, sizeof(cmSingleton_t)); // do not reset canonicalMachineSingleton once it's been initialized
memset(&cm.gm, 0, sizeof(GCodeState_t)); // clear all values, pointers and status
- memset(&cm.gn, 0, sizeof(GCodeInput_t));
- memset(&cm.gf, 0, sizeof(GCodeFlags_t));
canonical_machine_init_assertions(); // establish assertions
ACTIVE_MODEL = MODEL; // setup initial Gcode model pointer
@@ -1037,10 +1035,11 @@ stat_t cm_set_arc_distance_mode(const uint8_t mode)
* cm_set_work_offsets() immediately afterwards.
*/
-stat_t cm_set_g10_data(const uint8_t P_word, const uint8_t L_word,
+stat_t cm_set_g10_data(const uint8_t P_word, const bool P_flag,
+ const uint8_t L_word, const bool L_flag,
const float offset[], const bool flag[])
{
- if (!cm.gf.L_word) {
+ if (!L_flag) {
return (STAT_L_WORD_IS_MISSING);
}
@@ -1056,8 +1055,9 @@ stat_t cm_set_g10_data(const uint8_t P_word, const uint8_t L_word,
cm.offset[P_word][axis] = _to_millimeters(offset[axis]);
} else {
// Should L20 take into account G92 offsets?
- cm.offset[P_word][axis] = cm.gmx.position[axis] -
- _to_millimeters(offset[axis]) -
+ cm.offset[P_word][axis] =
+ cm.gmx.position[axis] -
+ _to_millimeters(offset[axis]) -
cm.tl_offset[axis];
}
// persist offsets once machining cycle is over
@@ -1077,8 +1077,8 @@ stat_t cm_set_g10_data(const uint8_t P_word, const uint8_t L_word,
} else {
// L10 should also take into account G92 offset
cm.tt_offset[P_word][axis] =
- cm.gmx.position[axis] - _to_millimeters(offset[axis]) -
- cm.offset[cm.gm.coord_system][axis] -
+ cm.gmx.position[axis] - _to_millimeters(offset[axis]) -
+ cm.offset[cm.gm.coord_system][axis] -
(cm.gmx.origin_offset[axis] * cm.gmx.origin_offset_enable);
}
// persist offsets once machining cycle is over
@@ -1101,27 +1101,27 @@ stat_t cm_set_g10_data(const uint8_t P_word, const uint8_t L_word,
* cm_set_coord_system() - G54-G59
* _exec_offset() - callback from planner
*/
-stat_t cm_set_tl_offset(const uint8_t H_word, bool apply_additional)
+
+stat_t cm_set_tl_offset(const uint8_t H_word, const bool H_flag, const bool apply_additional)
{
uint8_t tool;
- if (cm.gf.H_word)
- {
- if (cm.gn.H_word > TOOLS) {
+ if (H_flag) {
+ if (H_word > TOOLS) {
return (STAT_H_WORD_IS_INVALID);
}
- if (cm.gn.H_word == 0) { // interpret H0 as "current tool", just like no H at all.
+ if (H_word == 0) { // interpret H0 as "current tool", just like no H at all.
tool = cm.gm.tool;
} else {
- tool = cm.gn.H_word;
+ tool = H_word;
}
- } else {
+ } else {
tool = cm.gm.tool;
}
if (apply_additional) {
for (uint8_t axis = AXIS_X; axis < AXES; axis++) {
cm.tl_offset[axis] += cm.tt_offset[tool][axis];
}
- } else {
+ } else {
for (uint8_t axis = AXIS_X; axis < AXES; axis++) {
cm.tl_offset[axis] = cm.tt_offset[tool][axis];
}
@@ -1595,7 +1595,7 @@ stat_t cm_m48_enable(uint8_t enable) // M48, M49
}
/*
- * cm_feed_rate_override_enable() - M50
+ * cm_mfo_control() - M50 manual feed rate override comtrol
*
* M50 enables manual feedrate override and the optional P override parameter.
* P is expressed as M% to N% of programmed feedrate, typically a value from 0.05 to 2.000.
@@ -1634,38 +1634,64 @@ stat_t cm_m48_enable(uint8_t enable) // M48, M49
* ENABLE ENABLE M50 Pn ENABLE start ramp w/new P value; store P value
* (Note: new ramp will supercede any existing ramp)
*/
-stat_t cm_mfo_enable(uint8_t enable) // M50
+
+stat_t cm_mfo_control(const float P_word, const bool P_flag) // M50
{
bool new_enable = true;
bool new_override = false;
- if (cm.gf.parameter) { // if parameter is present in Gcode block
- if (fp_ZERO(cm.gn.parameter)) {
- new_enable = false; // P0 disables override
+ if (P_flag) { // if parameter is present in Gcode block
+ if (fp_ZERO(P_word)) {
+ new_enable = false; // P0 disables override
} else {
- if (cm.gn.parameter < FEED_OVERRIDE_MIN) {
+ if (P_word < FEED_OVERRIDE_MIN) {
return (STAT_INPUT_LESS_THAN_MIN_VALUE);
}
- if (cm.gn.parameter > FEED_OVERRIDE_MAX) {
+ if (P_word > FEED_OVERRIDE_MAX) {
return (STAT_INPUT_EXCEEDS_MAX_VALUE);
}
- cm.gmx.mfo_factor = cm.gn.parameter; // it validates - store it.
+ cm.gmx.mfo_factor = P_word; // P word is valid, store it.
new_override = true;
}
}
- if (cm.gmx.m48_enable) { // if master enable is ON
+ if (cm.gmx.m48_enable) { // if master enable is ON
if (new_enable && (new_override || !cm.gmx.mfo_enable)) { // 3 cases to start a ramp
mp_start_feed_override(FEED_OVERRIDE_RAMP_TIME, cm.gmx.mfo_factor);
} else if (cm.gmx.mfo_enable && !new_enable) { // case to turn off the ramp
mp_end_feed_override(FEED_OVERRIDE_RAMP_TIME);
}
}
- cm.gmx.mfo_enable = new_enable; // always update the enable state
+ cm.gmx.mfo_enable = new_enable; // always update the enable state
return (STAT_OK);
}
-// if ((new_enable && new_override) || (new_enable && !cm.gmx.mfo_enable)) {
-// if (!(cm.gmx.mfo_enable && new_override)) {
-
+stat_t cm_mto_control(const float P_word, const bool P_flag) // M50.1
+{
+ bool new_enable = true;
+ bool new_override = false;
+ if (P_flag) { // if parameter is present in Gcode block
+ if (fp_ZERO(P_word)) {
+ new_enable = false; // P0 disables override
+ } else {
+ if (P_word < TRAVERSE_OVERRIDE_MIN) {
+ return (STAT_INPUT_LESS_THAN_MIN_VALUE);
+ }
+ if (P_word > TRAVERSE_OVERRIDE_MAX) {
+ return (STAT_INPUT_EXCEEDS_MAX_VALUE);
+ }
+ cm.gmx.mto_factor = P_word; // P word is valid, store it.
+ new_override = true;
+ }
+ }
+ if (cm.gmx.m48_enable) { // if master enable is ON
+ if (new_enable && (new_override || !cm.gmx.mfo_enable)) { // 3 cases to start a ramp
+ mp_start_traverse_override(FEED_OVERRIDE_RAMP_TIME, cm.gmx.mto_factor);
+ } else if (cm.gmx.mto_enable && !new_enable) { // case to turn off the ramp
+ mp_end_traverse_override(FEED_OVERRIDE_RAMP_TIME);
+ }
+ }
+ cm.gmx.mto_enable = new_enable; // always update the enable state
+ return (STAT_OK);
+}
/************************************************
* Feedhold and Related Functions (no NIST ref) *
@@ -2582,7 +2608,9 @@ stat_t cm_run_qf(nvObj_t *nv)
stat_t cm_run_home(nvObj_t *nv)
{
if (fp_TRUE(nv->value)) {
- cm_homing_cycle_start();
+ float axes[] = { 1,1,1,1,1,1 };
+ bool flags[] = { 1,1,1,1,1,1 };
+ cm_homing_cycle_start(axes, flags);
}
return (STAT_OK);
}
diff --git a/g2core/canonical_machine.h b/g2core/canonical_machine.h
index e2c165d6..dfa6cb8b 100644
--- a/g2core/canonical_machine.h
+++ b/g2core/canonical_machine.h
@@ -405,96 +405,6 @@ typedef struct GCodeStateExtended { // Gcode dynamic state extensions - used
} GCodeStateX_t;
-typedef struct GCodeInput { // Gcode model inputs - meaning depends on context
-
- uint8_t next_action; // handles G modal group 1 moves & non-modals
- cmMotionMode motion_mode; // Group1: G0, G1, G2, G3, G38.2, G80, G81, G82
- // G83, G84, G85, G86, G87, G88, G89
-
- uint8_t program_flow; // used only by the gcode_parser
- uint32_t linenum; // N word
- float target[AXES]; // XYZABC where the move should go
-
- uint8_t H_word; // H word - used by G43s
- uint8_t L_word; // L word - used by G10s
-
- float feed_rate; // F - normalized to millimeters/minute
- uint8_t feed_rate_mode; // See cmFeedRateMode for settings
- float parameter; // P - parameter used for dwell time in seconds, G10 coord select...
- float arc_radius; // R - radius value in arc radius mode
- float arc_offset[3]; // IJK - used by arc commands
-
- bool m48_enable; // M48/M49 input (enables for feed and spindle)
- bool mfo_enable; // M50 feedrate override enable
- bool mto_enable; // Mxx traverse override enable
- bool sso_enable; // M51 spindle speed override enable
-
- uint8_t select_plane; // G17,G18,G19 - values to set plane to
- uint8_t units_mode; // G20,G21 - 0=inches (G20), 1 = mm (G21)
- uint8_t coord_system; // G54-G59 - select coordinate system 1-9
- uint8_t path_control; // G61... EXACT_PATH, EXACT_STOP, CONTINUOUS
- uint8_t distance_mode; // G91 0=use absolute coords(G90), 1=incremental movement
- uint8_t arc_distance_mode; // G90.1=use absolute IJK offsets, G91.1=incremental IJK offsets
- uint8_t origin_offset_mode; // G92...TRUE=in origin offset mode
- uint8_t absolute_override; // G53 TRUE = move using machine coordinates - this block only (G53)
- uint8_t tool; // Tool after T and M6 (tool_select and tool_change)
- uint8_t tool_select; // T value - T sets this value
- uint8_t tool_change; // M6 tool change flag - moves "tool_select" to "tool"
- uint8_t mist_coolant; // TRUE = mist on (M7), FALSE = off (M9)
- uint8_t flood_coolant; // TRUE = flood on (M8), FALSE = off (M9)
-
- uint8_t spindle_control; // 0=OFF (M5), 1=CW (M3), 2=CCW (M4)
- float spindle_speed; // in RPM
- float spindle_override_factor; // 1.0000 x S spindle speed. Go up or down from there
- uint8_t spindle_override_enable; // TRUE = override enabled
-
-// unimplemented gcode parameters
-// float cutter_radius; // D - cutter radius compensation (0 is off)
-
-} GCodeInput_t;
-
-typedef struct GCodeFlags { // Gcode model input flags
- bool next_action;
- bool motion_mode;
- bool modals[MODAL_GROUP_COUNT];
- bool program_flow;
- bool linenum;
- bool target[AXES];
-
- bool H_word;
- bool L_word;
- bool feed_rate;
- bool feed_rate_mode;
-
- bool m48_enable;
- bool mfo_enable;
- bool mto_enable;
- bool sso_enable;
-
- bool select_plane;
- bool units_mode;
- bool coord_system;
- bool path_control;
- bool distance_mode;
- bool arc_distance_mode;
- bool origin_offset_mode;
- bool absolute_override;
- bool tool;
- bool tool_select;
- bool tool_change;
- bool mist_coolant;
- bool flood_coolant;
-
- bool spindle_control;
- bool spindle_speed;
- bool spindle_override_factor;
- bool spindle_override_enable;
-
- bool parameter;
- bool arc_radius;
- bool arc_offset[3];
-} GCodeFlags_t;
-
/*****************************************************************************
* CANONICAL MACHINE STRUCTURES
*/
@@ -589,8 +499,6 @@ typedef struct cmSingleton { // struct to manage cm globals and c
GCodeState_t *am; // active Gcode model is maintained by state management
GCodeState_t gm; // core gcode model state
GCodeStateX_t gmx; // extended gcode model state
- GCodeInput_t gn; // gcode input values - transient
- GCodeFlags_t gf; // gcode input flags - transient
magic_t magic_end;
} cmSingleton_t;
@@ -680,9 +588,11 @@ stat_t cm_select_plane(const uint8_t plane); // G
stat_t cm_set_units_mode(const uint8_t mode); // G20, G21
stat_t cm_set_distance_mode(const uint8_t mode); // G90, G91
stat_t cm_set_arc_distance_mode(const uint8_t mode); // G90.1, G91.1
-stat_t cm_set_tl_offset(const uint8_t H_word, bool apply_additional); // G43, G43.2
+stat_t cm_set_tl_offset(const uint8_t H_word, const bool H_flag, // G43, G43.2
+ const bool apply_additional);
stat_t cm_cancel_tl_offset(void); // G49
-stat_t cm_set_g10_data(const uint8_t P_word, const uint8_t L_word, // G10
+stat_t cm_set_g10_data(const uint8_t P_word, const bool P_flag, // G10
+ const uint8_t L_word, const bool L_flag,
const float offset[], const bool flag[]);
void cm_set_position(const uint8_t axis, const float position); // set absolute position - single axis
@@ -722,17 +632,20 @@ stat_t cm_arc_feed(const float target[], const bool target_f[], // G
// see spindle.h for spindle functions - which would go right here
// Tool Functions (4.3.8)
-stat_t cm_select_tool(const uint8_t tool); // T parameter
-stat_t cm_change_tool(const uint8_t tool); // M6
+stat_t cm_select_tool(const uint8_t tool); // T parameter
+stat_t cm_change_tool(const uint8_t tool); // M6
// Miscellaneous Functions (4.3.9)
// see coolant.h for coolant functions - which would go right here
-void cm_message(const char *message); // msg to console (e.g. Gcode comments)
+void cm_message(const char *message); // msg to console (e.g. Gcode comments)
void cm_reset_overrides(void);
-stat_t cm_m48_enable(uint8_t enable); // M48, M49
-stat_t cm_mfo_enable(uint8_t enable); // M50
+stat_t cm_m48_enable(uint8_t enable); // M48, M49
+stat_t cm_mfo_enable(uint8_t enable); // M50
+stat_t cm_mfo_control(const float P_word, const bool P_flag); // M50
+stat_t cm_mto_control(const float P_word, const bool P_flag); // M50.1
+// See spindle.cpp for cm_sso_control() // M51
// Program Functions (4.3.10)
void cm_request_feedhold(void);
@@ -761,8 +674,8 @@ stat_t cm_json_wait(char *json_string); // M102
/*--- Cycles ---*/
// Homing cycles
-stat_t cm_homing_cycle_start(void); // G28.2
-stat_t cm_homing_cycle_start_no_set(void); // G28.4
+stat_t cm_homing_cycle_start(const float axes[], const bool flags[]); // G28.2
+stat_t cm_homing_cycle_start_no_set(const float axes[], const bool flags[]); // G28.4
stat_t cm_homing_cycle_callback(void); // G28.2/.4 main loop callback
// Probe cycles
diff --git a/g2core/cycle_homing.cpp b/g2core/cycle_homing.cpp
index 8058213a..1c13a3f1 100644
--- a/g2core/cycle_homing.cpp
+++ b/g2core/cycle_homing.cpp
@@ -2,8 +2,8 @@
* cycle_homing.cpp - homing cycle extension to canonical_machine
* This file is part of the g2core project
*
- * Copyright (c) 2010 - 2016 Alden S. Hart, Jr.
- * Copyright (c) 2013 - 2016 Robert Giseburt
+ * Copyright (c) 2010 - 2017 Alden S. Hart, Jr.
+ * Copyright (c) 2013 - 2017 Robert Giseburt
*
* This file ("the software") is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 as published by the
@@ -49,6 +49,8 @@ struct hmHomingSingleton { // persistent homing runtime variables
bool set_coordinates; // G28.4 flag. true = set coords to zero at the end of homing cycle
stat_t (*func)(int8_t axis); // binding for callback function state machine
+ bool axis_flags[AXES]; // local storage for axis flags
+
// per-axis parameters
float direction; // set to 1 for positive (max), -1 for negative (to min);
float search_travel; // signed distance to travel in search
@@ -152,7 +154,7 @@ static stat_t _set_homing_func(stat_t (*func)(int8_t axis)) {
* to cm_get_runtime_busy() is about.
*/
-stat_t cm_homing_cycle_start(void) {
+stat_t cm_homing_cycle_start(const float axes[], const bool flags[]) {
// save relevant non-axis parameters from Gcode model
hm.saved_units_mode = (cmUnitsMode)cm_get_units_mode(ACTIVE_MODEL);
hm.saved_coord_system = (cmCoordSystem)cm_get_coord_system(ACTIVE_MODEL);
@@ -160,6 +162,8 @@ stat_t cm_homing_cycle_start(void) {
hm.saved_feed_rate_mode = (cmFeedRateMode)cm_get_feed_rate_mode(ACTIVE_MODEL);
hm.saved_feed_rate = cm_get_feed_rate(ACTIVE_MODEL);
+ copy_vector(hm.axis_flags, flags);
+
// set working values
cm_set_units_mode(MILLIMETERS);
cm_set_distance_mode(INCREMENTAL_DISTANCE_MODE);
@@ -178,8 +182,8 @@ stat_t cm_homing_cycle_start(void) {
return (STAT_OK);
}
-stat_t cm_homing_cycle_start_no_set(void) {
- cm_homing_cycle_start();
+stat_t cm_homing_cycle_start_no_set(const float axes[], const bool flags[]) {
+ cm_homing_cycle_start(axes, flags);
hm.set_coordinates = false; // set flag to not update position variables at the end of the cycle
return (STAT_OK);
}
@@ -407,38 +411,38 @@ static stat_t _homing_finalize_exit(int8_t axis) // third part of return to hom
static int8_t _get_next_axis(int8_t axis) {
#if (HOMING_AXES <= 4)
if (axis == -1) { // inelegant brute force solution
- if (cm.gf.target[AXIS_Z]) {
+ if (hm.axis_flags[AXIS_Z]) {
return (AXIS_Z);
}
- if (cm.gf.target[AXIS_X]) {
+ if (hm.axis_flags[AXIS_X]) {
return (AXIS_X);
}
- if (cm.gf.target[AXIS_Y]) {
+ if (hm.axis_flags[AXIS_Y]) {
return (AXIS_Y);
}
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
return (-2); // error
} else if (axis == AXIS_Z) {
- if (cm.gf.target[AXIS_X]) {
+ if (hm.axis_flags[AXIS_X]) {
return (AXIS_X);
}
- if (cm.gf.target[AXIS_Y]) {
+ if (hm.axis_flags[AXIS_Y]) {
return (AXIS_Y);
}
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
} else if (axis == AXIS_X) {
- if (cm.gf.target[AXIS_Y]) {
+ if (hm.axis_flags[AXIS_Y]) {
return (AXIS_Y);
}
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
} else if (axis == AXIS_Y) {
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
}
@@ -446,77 +450,77 @@ static int8_t _get_next_axis(int8_t axis) {
#else
if (axis == -1) {
- if (cm.gf.target[AXIS_Z]) {
+ if (hm.axis_flags[AXIS_Z]) {
return (AXIS_Z);
}
- if (cm.gf.target[AXIS_X]) {
+ if (hm.axis_flags[AXIS_X]) {
return (AXIS_X);
}
- if (cm.gf.target[AXIS_Y]) {
+ if (hm.axis_flags[AXIS_Y]) {
return (AXIS_Y);
}
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
- if (cm.gf.target[AXIS_B]) {
+ if (hm.axis_flags[AXIS_B]) {
return (AXIS_B);
}
- if (cm.gf.target[AXIS_C]) {
+ if (hm.axis_flags[AXIS_C]) {
return (AXIS_C);
}
return (-2); // error
} else if (axis == AXIS_Z) {
- if (cm.gf.target[AXIS_X]) {
+ if (hm.axis_flags[AXIS_X]) {
return (AXIS_X);
}
- if (cm.gf.target[AXIS_Y]) {
+ if (hm.axis_flags[AXIS_Y]) {
return (AXIS_Y);
}
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
- if (cm.gf.target[AXIS_B]) {
+ if (hm.axis_flags[AXIS_B]) {
return (AXIS_B);
}
- if (cm.gf.target[AXIS_C]) {
+ if (hm.axis_flags[AXIS_C]) {
return (AXIS_C);
}
} else if (axis == AXIS_X) {
- if (cm.gf.target[AXIS_Y]) {
+ if (hm.axis_flags[AXIS_Y]) {
return (AXIS_Y);
}
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
- if (cm.gf.target[AXIS_B]) {
+ if (hm.axis_flags[AXIS_B]) {
return (AXIS_B);
}
- if (cm.gf.target[AXIS_C]) {
+ if (hm.axis_flags[AXIS_C]) {
return (AXIS_C);
}
} else if (axis == AXIS_Y) {
- if (cm.gf.target[AXIS_A]) {
+ if (hm.axis_flags[AXIS_A]) {
return (AXIS_A);
}
- if (cm.gf.target[AXIS_B]) {
+ if (hm.axis_flags[AXIS_B]) {
return (AXIS_B);
}
- if (cm.gf.target[AXIS_C]) {
+ if (hm.axis_flags[AXIS_C]) {
return (AXIS_C);
}
} else if (axis == AXIS_A) {
- if (cm.gf.target[AXIS_B]) {
+ if (hm.axis_flags[AXIS_B]) {
return (AXIS_B);
}
- if (cm.gf.target[AXIS_C]) {
+ if (hm.axis_flags[AXIS_C]) {
return (AXIS_C);
}
} else if (axis == AXIS_B) {
- if (cm.gf.target[AXIS_C]) {
+ if (hm.axis_flags[AXIS_C]) {
return (AXIS_C);
}
}
return (-1); // done
#endif // (HOMING_AXES <= 4)
-}
+}
\ No newline at end of file
diff --git a/g2core/g2core.cppproj b/g2core/g2core.cppproj
index 5ce23b64..4669f074 100644
--- a/g2core/g2core.cppproj
+++ b/g2core/g2core.cppproj
@@ -5,7 +5,7 @@
7.0
com.Atmel.ARMGCC.CPP
{44ea8fec-55d7-4149-8a78-a574fc26bf51}
- ATSAM3X8E
+ ATSAM3X8C
none
Executable
CPP
@@ -21,10 +21,8 @@
exception_table
1
3.5.0
-
-
-
-
+ SWD
+ com.atmel.avrdbg.tool.atmelice
com.atmel.avrdbg.tool.samice
J-Link
@@ -70,12 +68,12 @@
- 10000000
+ 2000000
SWD
com.atmel.avrdbg.tool.atmelice
- J41800036434
+ J41800030015
Atmel-ICE
True
@@ -102,9 +100,9 @@
True
true
- J41800036434
+ J41800030015
0x284E0A60
- 10000000
+ 2000000
diff --git a/g2core/gcode_parser.cpp b/g2core/gcode_parser.cpp
index 674a7028..f8d71d93 100644
--- a/g2core/gcode_parser.cpp
+++ b/g2core/gcode_parser.cpp
@@ -2,8 +2,8 @@
* gcode_parser.cpp - rs274/ngc Gcode parser
* This file is part of the g2core project
*
- * Copyright (c) 2010 - 2016 Alden S. Hart, Jr.
- * Copyright (c) 2016 Rob Giseburt
+ * Copyright (c) 2010 - 2017 Alden S. Hart, Jr.
+ * Copyright (c) 2016 - 2017 Rob Giseburt
*
* This file ("the software") is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 as published by the
@@ -27,6 +27,94 @@
#include "util.h"
#include "xio.h" // for char definitions
+// Structures used by Gcode parser
+
+typedef struct GCodeInputValue { // Gcode inputs - meaning depends on context
+
+ uint8_t next_action; // handles G modal group 1 moves & non-modals
+ cmMotionMode motion_mode; // Group1: G0, G1, G2, G3, G38.2, G80, G81, G82, G83, G84, G85, G86, G87, G88, G89
+ uint8_t program_flow; // used only by the gcode_parser
+ uint32_t linenum; // N word
+
+ float target[AXES]; // XYZABC where the move should go
+ float arc_offset[3]; // IJK - used by arc commands
+ float arc_radius; // R - radius value in arc radius mode
+
+ float F_word; // F - normalized to millimeters/minute
+ uint8_t H_word; // H word - used by G43s
+ uint8_t L_word; // L word - used by G10s
+ float P_word; // P - parameter used for dwell time in seconds, G10 coord select...
+ float S_word; // S word - in RPM
+
+ uint8_t feed_rate_mode; // See cmFeedRateMode for settings
+ uint8_t select_plane; // G17,G18,G19 - values to set plane to
+ uint8_t units_mode; // G20,G21 - 0=inches (G20), 1 = mm (G21)
+ uint8_t coord_system; // G54-G59 - select coordinate system 1-9
+ uint8_t path_control; // G61... EXACT_PATH, EXACT_STOP, CONTINUOUS
+ uint8_t distance_mode; // G91 0=use absolute coords(G90), 1=incremental movement
+ uint8_t arc_distance_mode; // G90.1=use absolute IJK offsets, G91.1=incremental IJK offsets
+ uint8_t origin_offset_mode; // G92...TRUE=in origin offset mode
+ uint8_t absolute_override; // G53 TRUE = move using machine coordinates - this block only (G53)
+ uint8_t tool; // Tool after T and M6 (tool_select and tool_change)
+ uint8_t tool_select; // T value - T sets this value
+ uint8_t tool_change; // M6 tool change flag - moves "tool_select" to "tool"
+ uint8_t mist_coolant; // TRUE = mist on (M7), FALSE = off (M9)
+ uint8_t flood_coolant; // TRUE = flood on (M8), FALSE = off (M9)
+ uint8_t spindle_control; // 0=OFF (M5), 1=CW (M3), 2=CCW (M4)
+
+ bool m48_enable; // M48/M49 input (enables for feed and spindle)
+ bool mfo_control; // M50 feedrate override control
+ bool mto_control; // M50.1 traverse override control
+ bool sso_control; // M51 spindle speed override control
+} GCodeValue_t;
+
+typedef struct GCodeFlags { // Gcode input flags
+
+ bool next_action;
+ bool motion_mode;
+ bool program_flow;
+ bool linenum;
+
+ bool target[AXES];
+ bool arc_offset[3];
+ bool arc_radius;
+
+ bool F_word;
+ bool H_word;
+ bool L_word;
+ bool P_word;
+ bool S_word;
+
+ bool feed_rate_mode;
+ bool select_plane;
+ bool units_mode;
+ bool coord_system;
+ bool path_control;
+ bool distance_mode;
+ bool arc_distance_mode;
+ bool origin_offset_mode;
+ bool absolute_override;
+ bool tool;
+ bool tool_select;
+ bool tool_change;
+ bool mist_coolant;
+ bool flood_coolant;
+ bool spindle_control;
+
+ bool m48_enable;
+ bool mfo_control;
+ bool mto_control;
+ bool sso_control;
+} GCodeFlag_t;
+
+typedef struct GCodeParser {
+ bool modals[MODAL_GROUP_COUNT];
+} GCodeParser_t;
+
+GCodeParser_t gp; // main parser struct
+GCodeValue_t gv; // gcode input values
+GCodeFlag_t gf; // gcode input flags
+
// local helper functions and macros
static void _normalize_gcode_block(char *str, char **active_comment, uint8_t *block_delete_flag);
static stat_t _get_next_gcode_word(char **pstr, char *letter, float *value);
@@ -35,9 +123,19 @@ static stat_t _validate_gcode_block(char *active_comment);
static stat_t _parse_gcode_block(char *line, char *active_comment); // Parse the block into the GN/GF structs
static stat_t _execute_gcode_block(char *active_comment); // Execute the gcode block
-#define SET_MODAL(m,parm,val) ({cm.gn.parm=val; cm.gf.parm=true; cm.gf.modals[m]=true; break;})
-#define SET_NON_MODAL(parm,val) ({cm.gn.parm=val; cm.gf.parm=true; break;})
-#define EXEC_FUNC(f,v) if(cm.gf.v) { status=f(cm.gn.v);}
+#define SET_MODAL(m,parm,val) ({gv.parm=val; gf.parm=true; gp.modals[m]=true; break;})
+#define SET_NON_MODAL(parm,val) ({gv.parm=val; gf.parm=true; break;})
+#define EXEC_FUNC(f,v) if(gf.v) { status=f(gv.v);}
+
+/*
+ * gcode_parser_init()
+ */
+
+void gcode_parser_init()
+{
+ memset(&gv, 0, sizeof(GCodeValue_t));
+ memset(&gf, 0, sizeof(GCodeFlag_t));
+}
/*
* gcode_parser() - parse a block (line) of gcode
@@ -409,22 +507,22 @@ static stat_t _validate_gcode_block(char *active_comment)
static stat_t _parse_gcode_block(char *buf, char *active_comment)
{
- char *pstr = (char *)buf; // persistent pointer into gcode block for parsing words
- char letter; // parsed letter, eg.g. G or X or Y
- float value = 0; // value parsed from letter (e.g. 2 for G2)
+ char *pstr = (char *)buf; // persistent pointer into gcode block for parsing words
+ char letter; // parsed letter, eg.g. G or X or Y
+ float value = 0; // value parsed from letter (e.g. 2 for G2)
stat_t status = STAT_OK;
// set initial state for new move
- memset(&cm.gn, 0, sizeof(GCodeInput_t)); // clear all next-state values
- memset(&cm.gf, 0, sizeof(GCodeFlags_t)); // clear all next-state flags
- cm.gn.motion_mode = cm_get_motion_mode(MODEL); // get motion mode from previous block
+ memset(&gv, 0, sizeof(GCodeValue_t)); // clear all next-state values
+ memset(&gf, 0, sizeof(GCodeFlag_t)); // clear all next-state flags
+ gv.motion_mode = cm_get_motion_mode(MODEL); // get motion mode from previous block
// Causes a later exception if
// (1) INVERSE_TIME_MODE is active and a feed rate is not provided or
// (2) INVERSE_TIME_MODE is changed to UNITS_PER_MINUTE and a new feed rate is missing
if (cm.gm.feed_rate_mode == INVERSE_TIME_MODE) {// new feed rate req'd when in INV_TIME_MODE
- cm.gn.feed_rate = 0;
- cm.gf.feed_rate = true;
+ gv.F_word = 0;
+ gf.F_word = true;
}
// extract commands and parameters
@@ -547,8 +645,14 @@ static stat_t _parse_gcode_block(char *buf, char *active_comment)
case 9: SET_MODAL (MODAL_GROUP_M8, flood_coolant, false);
case 48: SET_MODAL (MODAL_GROUP_M9, m48_enable, true);
case 49: SET_MODAL (MODAL_GROUP_M9, m48_enable, false);
- case 50: SET_MODAL (MODAL_GROUP_M9, mfo_enable, true);
- case 51: SET_MODAL (MODAL_GROUP_M9, sso_enable, true);
+ case 50: SET_MODAL (MODAL_GROUP_M9, mfo_control, true);
+ switch (_point(value)) {
+ case 0: SET_MODAL (MODAL_GROUP_M9, mfo_control, true);
+ case 1: SET_MODAL (MODAL_GROUP_M9, mto_control, true);
+ default: status = STAT_GCODE_COMMAND_UNSUPPORTED;
+ }
+ break;
+ case 51: SET_MODAL (MODAL_GROUP_M9, sso_control, true);
case 100: SET_NON_MODAL (next_action, NEXT_ACTION_JSON_COMMAND_SYNC);
case 101: SET_NON_MODAL (next_action, NEXT_ACTION_JSON_WAIT);
default: status = STAT_MCODE_COMMAND_UNSUPPORTED;
@@ -556,9 +660,9 @@ static stat_t _parse_gcode_block(char *buf, char *active_comment)
break;
case 'T': SET_NON_MODAL (tool_select, (uint8_t)trunc(value));
- case 'F': SET_NON_MODAL (feed_rate, value);
- case 'P': SET_NON_MODAL (parameter, value); // used for dwell time, G10 coord select
- case 'S': SET_NON_MODAL (spindle_speed, value);
+ case 'F': SET_NON_MODAL (F_word, value);
+ case 'P': SET_NON_MODAL (P_word, value); // used for dwell time, G10 coord select
+ case 'S': SET_NON_MODAL (S_word, value);
case 'X': SET_NON_MODAL (target[AXIS_X], value);
case 'Y': SET_NON_MODAL (target[AXIS_Y], value);
case 'Z': SET_NON_MODAL (target[AXIS_Z], value);
@@ -628,42 +732,43 @@ static stat_t _execute_gcode_block(char *active_comment)
{
stat_t status = STAT_OK;
- cm_set_model_linenum(cm.gn.linenum);
+ cm_set_model_linenum(gv.linenum);
EXEC_FUNC(cm_set_feed_rate_mode, feed_rate_mode); // G93, G94
- EXEC_FUNC(cm_set_feed_rate, feed_rate); // F
- EXEC_FUNC(cm_set_spindle_speed, spindle_speed); // S
-// EXEC_FUNC(cm_spindle_override_factor, spindle_override_factor);
+ EXEC_FUNC(cm_set_feed_rate, F_word); // F
+ EXEC_FUNC(cm_set_spindle_speed, S_word); // S
+ if (gf.sso_control) { // spindle speed override
+ ritorno(cm_sso_control(gv.P_word, gf.P_word));
+ }
+
EXEC_FUNC(cm_select_tool, tool_select); // tool_select is where it's written
EXEC_FUNC(cm_change_tool, tool_change); // M6
EXEC_FUNC(cm_spindle_control, spindle_control); // spindle CW, CCW, OFF
-/*
- EXEC_FUNC(cm_feed_rate_override_enable, feed_rate_override_enable);
- EXEC_FUNC(cm_traverse_override_enable, traverse_override_enable);
- EXEC_FUNC(cm_spindle_override_enable, spindle_override_enable);
- EXEC_FUNC(cm_override_enables, override_enables);
-*/
EXEC_FUNC(cm_mist_coolant_control, mist_coolant); // M7, M9
EXEC_FUNC(cm_flood_coolant_control, flood_coolant); // M8, M9 also disables mist coolant if OFF
EXEC_FUNC(cm_m48_enable, m48_enable);
- EXEC_FUNC(cm_mfo_enable, mfo_enable);
-// EXEC_FUNC(cm_mfo_enable, feed_rate_override_factor);
-// EXEC_FUNC(cm_sso_enable, sso_enable);
- if (cm.gn.next_action == NEXT_ACTION_DWELL) { // G4 - dwell
- ritorno(cm_dwell(cm.gn.parameter)); // return if error, otherwise complete the block
+ if (gf.mfo_control) { // manual feedrate override
+ ritorno(cm_mfo_control(gv.P_word, gf.P_word));
+ }
+ if (gf.mto_control) { // manual traverse override
+ ritorno(cm_mto_control(gv.P_word, gf.P_word));
+ }
+
+ if (gv.next_action == NEXT_ACTION_DWELL) { // G4 - dwell
+ ritorno(cm_dwell(gv.P_word)); // return if error, otherwise complete the block
}
EXEC_FUNC(cm_select_plane, select_plane); // G17, G18, G19
EXEC_FUNC(cm_set_units_mode, units_mode); // G20, G21
//--> cutter radius compensation goes here
- switch (cm.gn.next_action) { // Tool length offsets
+ switch (gv.next_action) { // Tool length offsets
case NEXT_ACTION_SET_TL_OFFSET: { // G43
- ritorno(cm_set_tl_offset(cm.gn.H_word, false));
+ ritorno(cm_set_tl_offset(gv.H_word, gf.H_word, false));
break;
}
case NEXT_ACTION_SET_ADDITIONAL_TL_OFFSET: { // G43.2
- ritorno(cm_set_tl_offset(cm.gn.H_word, true));
+ ritorno(cm_set_tl_offset(gv.H_word, gf.H_word, true));
break;
}
case NEXT_ACTION_CANCEL_TL_OFFSET: { // G49
@@ -673,51 +778,56 @@ static stat_t _execute_gcode_block(char *active_comment)
}
EXEC_FUNC(cm_set_coord_system, coord_system); // G54, G55, G56, G57, G58, G59
-// EXEC_FUNC(cm_set_path_control, path_control); // G61, G61.1, G64
- if(cm.gf.path_control) { status = cm_set_path_control(MODEL, cm.gn.path_control); }
+
+ if (gf.path_control) { // G61, G61.1, G64
+ status = cm_set_path_control(MODEL, gv.path_control);
+ }
EXEC_FUNC(cm_set_distance_mode, distance_mode); // G90, G91
EXEC_FUNC(cm_set_arc_distance_mode, arc_distance_mode); // G90.1, G91.1
//--> set retract mode goes here
- switch (cm.gn.next_action) {
- case NEXT_ACTION_SET_G28_POSITION: { status = cm_set_g28_position(); break;} // G28.1
- case NEXT_ACTION_GOTO_G28_POSITION: { status = cm_goto_g28_position(cm.gn.target, cm.gf.target); break;} // G28
- case NEXT_ACTION_SET_G30_POSITION: { status = cm_set_g30_position(); break;} // G30.1
- case NEXT_ACTION_GOTO_G30_POSITION: { status = cm_goto_g30_position(cm.gn.target, cm.gf.target); break;} // G30
+ switch (gv.next_action) {
+ case NEXT_ACTION_SET_G28_POSITION: { status = cm_set_g28_position(); break;} // G28.1
+ case NEXT_ACTION_GOTO_G28_POSITION: { status = cm_goto_g28_position(gv.target, gf.target); break;} // G28
+ case NEXT_ACTION_SET_G30_POSITION: { status = cm_set_g30_position(); break;} // G30.1
+ case NEXT_ACTION_GOTO_G30_POSITION: { status = cm_goto_g30_position(gv.target, gf.target); break;} // G30
- case NEXT_ACTION_SEARCH_HOME: { status = cm_homing_cycle_start(); break;} // G28.2
- case NEXT_ACTION_SET_ABSOLUTE_ORIGIN: { status = cm_set_absolute_origin(cm.gn.target, cm.gf.target); break;}// G28.3
- case NEXT_ACTION_HOMING_NO_SET: { status = cm_homing_cycle_start_no_set(); break;} // G28.4
+ case NEXT_ACTION_SEARCH_HOME: { status = cm_homing_cycle_start(gv.target, gf.target); break;} // G28.2
+ case NEXT_ACTION_SET_ABSOLUTE_ORIGIN: { status = cm_set_absolute_origin(gv.target, gf.target); break;} // G28.3
+ case NEXT_ACTION_HOMING_NO_SET: { status = cm_homing_cycle_start_no_set(gv.target, gf.target); break;} // G28.4
- case NEXT_ACTION_STRAIGHT_PROBE_ERR: { status = cm_straight_probe(cm.gn.target, cm.gf.target, true, true); break;} // G38.2
- case NEXT_ACTION_STRAIGHT_PROBE: { status = cm_straight_probe(cm.gn.target, cm.gf.target, false, true); break;} // G38.3
- case NEXT_ACTION_STRAIGHT_PROBE_AWAY_ERR:{ status = cm_straight_probe(cm.gn.target, cm.gf.target, true, false); break;} // G38.4
- case NEXT_ACTION_STRAIGHT_PROBE_AWAY: { status = cm_straight_probe(cm.gn.target, cm.gf.target, false, false); break;} // G38.5
+ case NEXT_ACTION_STRAIGHT_PROBE_ERR: { status = cm_straight_probe(gv.target, gf.target, true, true); break;} // G38.2
+ case NEXT_ACTION_STRAIGHT_PROBE: { status = cm_straight_probe(gv.target, gf.target, false, true); break;} // G38.3
+ case NEXT_ACTION_STRAIGHT_PROBE_AWAY_ERR:{ status = cm_straight_probe(gv.target, gf.target, true, false); break;} // G38.4
+ case NEXT_ACTION_STRAIGHT_PROBE_AWAY: { status = cm_straight_probe(gv.target, gf.target, false, false); break;}// G38.5
- case NEXT_ACTION_SET_G10_DATA: { status = cm_set_g10_data(cm.gn.parameter, cm.gn.L_word, cm.gn.target, cm.gf.target); break;}
- case NEXT_ACTION_SET_ORIGIN_OFFSETS: { status = cm_set_origin_offsets(cm.gn.target, cm.gf.target); break;}// G92
- case NEXT_ACTION_RESET_ORIGIN_OFFSETS: { status = cm_reset_origin_offsets(); break;} // G92.1
- case NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS: { status = cm_suspend_origin_offsets(); break;} // G92.2
- case NEXT_ACTION_RESUME_ORIGIN_OFFSETS: { status = cm_resume_origin_offsets(); break;} // G92.3
+ case NEXT_ACTION_SET_G10_DATA: { status = cm_set_g10_data(gv.P_word, gf.P_word,
+ gv.L_word, gf.L_word,
+ gv.target, gf.target); break;}
+
+ case NEXT_ACTION_SET_ORIGIN_OFFSETS: { status = cm_set_origin_offsets(gv.target, gf.target); break;}// G92
+ case NEXT_ACTION_RESET_ORIGIN_OFFSETS: { status = cm_reset_origin_offsets(); break;} // G92.1
+ case NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS: { status = cm_suspend_origin_offsets(); break;} // G92.2
+ case NEXT_ACTION_RESUME_ORIGIN_OFFSETS: { status = cm_resume_origin_offsets(); break;} // G92.3
- case NEXT_ACTION_JSON_COMMAND_SYNC: { status = cm_json_command(active_comment); break;} // M100
- case NEXT_ACTION_JSON_WAIT: { status = cm_json_wait(active_comment); break;} // M101
-// case NEXT_ACTION_JSON_COMMAND_IMMEDIATE: { status = mp_json_command_immediate(active_comment); break;} // M102
+ case NEXT_ACTION_JSON_COMMAND_SYNC: { status = cm_json_command(active_comment); break;} // M100
+ case NEXT_ACTION_JSON_WAIT: { status = cm_json_wait(active_comment); break;} // M101
+// case NEXT_ACTION_JSON_COMMAND_IMMEDIATE: { status = mp_json_command_immediate(active_comment); break;} // M102
case NEXT_ACTION_DEFAULT: {
- cm_set_absolute_override(MODEL, cm.gn.absolute_override); // apply absolute override
- switch (cm.gn.motion_mode) {
- case MOTION_MODE_CANCEL_MOTION_MODE: { cm.gm.motion_mode = cm.gn.motion_mode; break;} // G80
- case MOTION_MODE_STRAIGHT_TRAVERSE: { status = cm_straight_traverse(cm.gn.target, cm.gf.target); break;} // G0
- case MOTION_MODE_STRAIGHT_FEED: { status = cm_straight_feed(cm.gn.target, cm.gf.target); break;} // G1
- case MOTION_MODE_CW_ARC: // G2
- case MOTION_MODE_CCW_ARC: { status = cm_arc_feed(cm.gn.target, cm.gf.target, // G3
- cm.gn.arc_offset, cm.gf.arc_offset,
- cm.gn.arc_radius, cm.gf.arc_radius,
- cm.gn.parameter, cm.gf.parameter,
- cm.gf.modals[MODAL_GROUP_G1],
- cm.gn.motion_mode);
+ cm_set_absolute_override(MODEL, gv.absolute_override); // apply absolute override
+ switch (gv.motion_mode) {
+ case MOTION_MODE_CANCEL_MOTION_MODE: { cm.gm.motion_mode = gv.motion_mode; break;} // G80
+ case MOTION_MODE_STRAIGHT_TRAVERSE: { status = cm_straight_traverse(gv.target, gf.target); break;} // G0
+ case MOTION_MODE_STRAIGHT_FEED: { status = cm_straight_feed(gv.target, gf.target); break;} // G1
+ case MOTION_MODE_CW_ARC: // G2
+ case MOTION_MODE_CCW_ARC: { status = cm_arc_feed(gv.target, gf.target, // G3
+ gv.arc_offset, gf.arc_offset,
+ gv.arc_radius, gf.arc_radius,
+ gv.P_word, gf.P_word,
+ gp.modals[MODAL_GROUP_G1],
+ gv.motion_mode);
break;
}
default: break;
@@ -727,8 +837,8 @@ static stat_t _execute_gcode_block(char *active_comment)
}
// do the program stops and ends : M0, M1, M2, M30, M60
- if (cm.gf.program_flow == true) {
- if (cm.gn.program_flow == PROGRAM_STOP) {
+ if (gf.program_flow == true) {
+ if (gv.program_flow == PROGRAM_STOP) {
cm_program_stop();
} else {
cm_program_end();
diff --git a/g2core/gcode_parser.h b/g2core/gcode_parser.h
old mode 100755
new mode 100644
index 25570c0c..4b61de8d
--- a/g2core/gcode_parser.h
+++ b/g2core/gcode_parser.h
@@ -2,7 +2,7 @@
* gcode_parser.h - rs274/ngc Gcode parser
* This file is part of the g2core project
*
- * Copyright (c) 2010 - 2016 Alden S. Hart, Jr.
+ * Copyright (c) 2010 - 2017 Alden S. Hart, Jr.
*
* This file ("the software") is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 as published by the
@@ -17,8 +17,8 @@
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef GCODE_PARSER_H_ONCE
-#define GCODE_PARSER_H_ONCE
+#ifndef GCODE_H_ONCE
+#define GCODE_H_ONCE
/*
* Global Scope Functions
@@ -27,4 +27,4 @@ stat_t gcode_parser(char* block);
stat_t gc_get_gc(nvObj_t* nv);
stat_t gc_run_gc(nvObj_t* nv);
-#endif // End of include guard: GCODE_PARSER_H_ONCE
+#endif // End of include guard: GCODE_H_ONCE
diff --git a/g2core/planner.cpp b/g2core/planner.cpp
index 205ed8c0..057010c2 100644
--- a/g2core/planner.cpp
+++ b/g2core/planner.cpp
@@ -597,6 +597,16 @@ void mp_end_feed_override(const float ramp_time)
mp_start_feed_override (FEED_OVERRIDE_RAMP_TIME, 1.00);
}
+void mp_start_traverse_override(const float ramp_time, const float override_factor)
+{
+ return;
+}
+
+void mp_end_traverse_override(const float ramp_time)
+{
+ return;
+}
+
/*
* mp_planner_time_accounting() - gather time in planner
*/
diff --git a/g2core/planner.h b/g2core/planner.h
index 9a1da416..dcc14f53 100644
--- a/g2core/planner.h
+++ b/g2core/planner.h
@@ -553,6 +553,8 @@ stat_t mp_planner_callback();
void mp_replan_queue(mpBuf_t *bf);
void mp_start_feed_override(const float ramp_time, const float override);
void mp_end_feed_override(const float ramp_time);
+void mp_start_traverse_override(const float ramp_time, const float override);
+void mp_end_traverse_override(const float ramp_time);
void mp_planner_time_accounting(void);
// planner buffer primitives
diff --git a/g2core/spindle.cpp b/g2core/spindle.cpp
index df86f333..e61e1ee4 100644
--- a/g2core/spindle.cpp
+++ b/g2core/spindle.cpp
@@ -2,7 +2,7 @@
* spindle.cpp - canonical machine spindle driver
* This file is part of the g2core project
*
- * Copyright (c) 2010 - 2016 Alden S. Hart, Jr.
+ * Copyright (c) 2010 - 2017 Alden S. Hart, Jr.
*
* This file ("the software") is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 as published by the
@@ -222,28 +222,50 @@ static float _get_spindle_pwm (cmSpindleEnable enable, cmSpindleDir direction)
/*
- * cm_spindle_override_enable()
- * cm_spindle_override_factor()
+ * cm_spindle_override_control()
+ * cm_start_spindle_override()
+ * cm_end_spindle_override()
*/
-/*
-stat_t cm_spindle_override_enable(uint8_t flag) // M51.1
+
+stat_t cm_sso_control(const float P_word, const bool P_flag) // M51
{
- if (fp_TRUE(cm.gf.parameter) && fp_ZERO(cm.gn.parameter)) {
- spindle.override_enable = false;
- } else {
- spindle.override_enable = true;
+ bool new_enable = true;
+ bool new_override = false;
+ if (P_flag) { // if parameter is present in Gcode block
+ if (fp_ZERO(P_word)) {
+ new_enable = false; // P0 disables override
+ } else {
+ if (P_word < SPINDLE_OVERRIDE_MIN) {
+ return (STAT_INPUT_LESS_THAN_MIN_VALUE);
+ }
+ if (P_word > SPINDLE_OVERRIDE_MAX) {
+ return (STAT_INPUT_EXCEEDS_MAX_VALUE);
+ }
+ spindle.sso_factor = P_word; // P word is valid, store it.
+ new_override = true;
+ }
}
+ if (cm.gmx.m48_enable) { // if master enable is ON
+ if (new_enable && (new_override || !spindle.sso_enable)) { // 3 cases to start a ramp
+ cm_start_spindle_override(SPINDLE_OVERRIDE_RAMP_TIME, spindle.sso_factor);
+ } else if (spindle.sso_enable && !new_enable) { // case to turn off the ramp
+ cm_end_spindle_override(SPINDLE_OVERRIDE_RAMP_TIME);
+ }
+ }
+ spindle.sso_enable = new_enable; // always update the enable state
return (STAT_OK);
}
-stat_t cm_spindle_override_factor(uint8_t flag) // M50.1
+void cm_start_spindle_override(const float ramp_time, const float override_factor)
{
- spindle.override_enable = flag;
- spindle.override_factor = cm.gn.parameter;
-// change spindle speed
- return (STAT_OK);
+ return;
}
-*/
+
+void cm_end_spindle_override(const float ramp_time)
+{
+ return;
+}
+
/****************************
* END OF SPINDLE FUNCTIONS *
****************************/
diff --git a/g2core/spindle.h b/g2core/spindle.h
index 33820ce8..9e26d585 100644
--- a/g2core/spindle.h
+++ b/g2core/spindle.h
@@ -60,8 +60,9 @@ typedef enum {
#define SPINDLE_OVERRIDE_ENABLE false
#define SPINDLE_OVERRIDE_FACTOR 1.00
-#define SPINDLE_OVERRIDE_MIN 0.05 // 5%
-#define SPINDLE_OVERRIDE_MAX 2.00 // 200%
+#define SPINDLE_OVERRIDE_MIN 0.05 // 5%
+#define SPINDLE_OVERRIDE_MAX 2.00 // 200%
+#define SPINDLE_OVERRIDE_RAMP_TIME 1 // change speed in seconds
/*
* Spindle control structure
@@ -99,8 +100,9 @@ void cm_spindle_off_immediate(void);
void cm_spindle_optional_pause(bool option); // stop spindle based on system options selected
void cm_spindle_resume(float dwell_seconds); // restart spindle after pause based on previous state
-// stat_t cm_spindle_override_enable(uint8_t flag); // M51
-// stat_t cm_spindle_override_factor(uint8_t flag); // M51.1
+stat_t cm_sso_control(const float P_word, const bool P_flag); // M51
+void cm_start_spindle_override(const float ramp_time, const float override_factor);
+void cm_end_spindle_override(const float ramp_time);
stat_t cm_set_dir(nvObj_t* nv);
stat_t cm_set_sso(nvObj_t* nv);