From 665475b57dba4eb819cbd0ef9fe069675bd19ffe Mon Sep 17 00:00:00 2001 From: Alden Hart Date: Thu, 12 Jan 2017 10:54:16 -0500 Subject: [PATCH] Isolated Gcode parser --- g2core/canonical_machine.cpp | 88 +++++++----- g2core/canonical_machine.h | 115 ++-------------- g2core/cycle_homing.cpp | 78 ++++++----- g2core/g2core.cppproj | 16 +-- g2core/gcode_parser.cpp | 254 +++++++++++++++++++++++++---------- g2core/gcode_parser.h | 8 +- g2core/planner.cpp | 10 ++ g2core/planner.h | 2 + g2core/spindle.cpp | 52 ++++--- g2core/spindle.h | 10 +- 10 files changed, 361 insertions(+), 272 deletions(-) mode change 100755 => 100644 g2core/gcode_parser.h 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);