From 4e40bbcd1d3e78d802f5dd80902686082a6361d1 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Tue, 5 Jan 2016 23:22:44 -0800 Subject: [PATCH] More cleanup --- src/config_app.c | 3 +- src/gcode_parser.c | 703 ++++++++++++++++---------------- src/hardware.c | 39 +- src/hardware.h | 2 - src/persistence.c | 10 +- src/settings/settings_default.h | 15 +- src/status.c | 7 +- src/stepper.c | 14 +- src/text_parser.c | 8 +- src/util.c | 49 +-- 10 files changed, 398 insertions(+), 452 deletions(-) diff --git a/src/config_app.c b/src/config_app.c index 3c4e8ee..c33e060 100644 --- a/src/config_app.c +++ b/src/config_app.c @@ -100,6 +100,7 @@ const cfgItem_t cfgArray[] PROGMEM = { {"mst", "mst2", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0}, {"mst", "mst3", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0}, {"mst", "mst4", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0}, + {"mfl", "mfl1", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0}, {"mfl", "mfl2", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0}, {"mfl", "mfl3", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0}, @@ -672,7 +673,7 @@ uint8_t nv_index_lt_groups(index_t index) {return (index <= NV_INDEX_START_GROUP /* - * Det floating point number with G20/G21 units conversion + * Set floating point number with G20/G21 units conversion * * The number 'setted' will have been delivered in external units (inches or mm). * It is written to the target memory location in internal canonical units (mm). diff --git a/src/gcode_parser.c b/src/gcode_parser.c index 6d8ec23..7185d7f 100644 --- a/src/gcode_parser.c +++ b/src/gcode_parser.c @@ -16,7 +16,7 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "tinyg.h" // #1 +#include "tinyg.h" // #1 #include "config.h" // #2 #include "controller.h" #include "gcode_parser.h" @@ -24,8 +24,8 @@ #include "spindle.h" #include "util.h" -struct gcodeParserSingleton { // struct to manage globals - uint8_t modals[MODAL_GROUP_COUNT];// collects modal groups in a block +struct gcodeParserSingleton { // struct to manage globals + uint8_t modals[MODAL_GROUP_COUNT]; // collects modal groups in a block }; struct gcodeParserSingleton gp; // local helper functions and macros @@ -40,36 +40,33 @@ static stat_t _execute_gcode_block(); // Execute the gcode block #define SET_NON_MODAL(parm,val) ({cm.gn.parm=val; cm.gf.parm=1; break;}) #define EXEC_FUNC(f,v) if((uint8_t)cm.gf.v != false) { status = f(cm.gn.v);} -/* - * gc_gcode_parser() - parse a block (line) of gcode - * - * Top level of gcode parser. Normalizes block and looks for special cases - */ -stat_t gc_gcode_parser(char_t *block) -{ - char_t *str = block; // gcode command or 0 string - char_t none = 0; - char_t *com = &none; // gcode comment or 0 string - char_t *msg = &none; // gcode message or 0 string - uint8_t block_delete_flag; +/// Parse a block (line) of gcode +/// Top level of gcode parser. Normalizes block and looks for special cases +stat_t gc_gcode_parser(char_t *block) { + char_t *str = block; // gcode command or 0 string + char_t none = 0; + char_t *com = &none; // gcode comment or 0 string + char_t *msg = &none; // gcode message or 0 string + uint8_t block_delete_flag; - // don't process Gcode blocks if in alarmed state - if (cm.machine_state == MACHINE_ALARM) return STAT_MACHINE_ALARMED; + // don't process Gcode blocks if in alarmed state + if (cm.machine_state == MACHINE_ALARM) return STAT_MACHINE_ALARMED; - _normalize_gcode_block(str, &com, &msg, &block_delete_flag); + _normalize_gcode_block(str, &com, &msg, &block_delete_flag); - // Block delete omits the line if a / char is present in the first space - // For now this is unconditional and will always delete - if (block_delete_flag) return STAT_NOOP; + // Block delete omits the line if a / char is present in the first space + // For now this is unconditional and will always delete + if (block_delete_flag) return STAT_NOOP; - // queue a "(MSG" response - if (*msg) cm_message(msg); // queue the message + // queue a "(MSG" response + if (*msg) cm_message(msg); // queue the message - return _parse_gcode_block(block); + return _parse_gcode_block(block); } + /* - * _normalize_gcode_block() - normalize a block (line) of gcode in place + * Normalize a block (line) of gcode in place * * Normalization functions: * - convert all letters to upper case @@ -105,122 +102,111 @@ stat_t gc_gcode_parser(char_t *block) * - block_delete_flag is set true if block delete encountered, false otherwise */ -static void _normalize_gcode_block(char_t *str, char_t **com, char_t **msg, uint8_t *block_delete_flag) -{ - char_t *rd = str; // read pointer - char_t *wr = str; // write pointer - - // Preset comments and messages to 0 string - // Not required if com and msg already point to 0 on entry -// for (rd = str; *rd != 0; rd++) { if (*rd == 0) { *com = rd; *msg = rd; rd = str;} } - - // mark block deletes - if (*rd == '/') { *block_delete_flag = true; } - else { *block_delete_flag = false; } - - // normalize the command block & find the comment (if any) - for (; *wr != 0; rd++) { - if (*rd == 0) { *wr = 0; } - else if ((*rd == '(') || (*rd == ';')) { *wr = 0; *com = rd+1; } - else if ((isalnum((char)*rd)) || (strchr("-.", *rd))) { // all valid characters - *(wr++) = (char_t)toupper((char)*(rd)); - } - } +static void _normalize_gcode_block(char_t *str, char_t **com, char_t **msg, uint8_t *block_delete_flag) { + char_t *rd = str; // read pointer + char_t *wr = str; // write pointer - // Perform Octal stripping - remove invalid leading zeros in number strings - rd = str; - while (*rd != 0) { - if (*rd == '.') break; // don't strip past a decimal point - if ((!isdigit(*rd)) && (*(rd+1) == '0') && (isdigit(*(rd+2)))) { - wr = rd+1; - while (*wr != 0) { *wr = *(wr+1); wr++;} // copy forward w/overwrite - continue; - } - rd++; - } + // mark block deletes + if (*rd == '/') { *block_delete_flag = true; } + else { *block_delete_flag = false; } - // process comments and messages - if (**com != 0) { - rd = *com; - while (isspace(*rd)) { rd++; } // skip any leading spaces before "msg" - if ((tolower(*rd) == 'm') && (tolower(*(rd+1)) == 's') && (tolower(*(rd+2)) == 'g')) { - *msg = rd+3; - } - for (; *rd != 0; rd++) { - if (*rd == ')') *rd = 0; // 0 terminate on trailing parenthesis, if any - } + // normalize the command block & find the comment (if any) + for (; *wr != 0; rd++) { + if (*rd == 0) { *wr = 0; } + else if ((*rd == '(') || (*rd == ';')) { *wr = 0; *com = rd+1; } + else if ((isalnum((char)*rd)) || (strchr("-.", *rd))) { // all valid characters + *(wr++) = (char_t)toupper((char)*(rd)); } + } + + // Perform Octal stripping - remove invalid leading zeros in number strings + rd = str; + while (*rd != 0) { + if (*rd == '.') break; // don't strip past a decimal point + if ((!isdigit(*rd)) && (*(rd + 1) == '0') && (isdigit(*(rd + 2)))) { + wr = rd + 1; + while (*wr != 0) {*wr = *(wr + 1); wr++;} // copy forward w/overwrite + continue; + } + rd++; + } + + // process comments and messages + if (**com != 0) { + rd = *com; + while (isspace(*rd)) { rd++; } // skip any leading spaces before "msg" + if ((tolower(*rd) == 'm') && (tolower(*(rd+1)) == 's') && (tolower(*(rd+2)) == 'g')) + *msg = rd + 3; + + for (; *rd != 0; rd++) + if (*rd == ')') *rd = 0; // 0 terminate on trailing parenthesis, if any + } } + /* - * _get_next_gcode_word() - get gcode word consisting of a letter and a value + * Get gcode word consisting of a letter and a value * * This function requires the Gcode string to be normalized. * Normalization must remove any leading zeros or they will be converted to Octal * G0X... is not interpreted as hexadecimal. This is trapped. */ -static stat_t _get_next_gcode_word(char **pstr, char *letter, float *value) -{ - if (**pstr == 0) - return STAT_COMPLETE; // no more words to process - - // get letter part - if(isupper(**pstr) == false) - return STAT_INVALID_OR_MALFORMED_COMMAND; - *letter = **pstr; +static stat_t _get_next_gcode_word(char **pstr, char *letter, float *value) { + if (**pstr == 0) return STAT_COMPLETE; // no more words to process + + // get letter part + if(isupper(**pstr) == false) + return STAT_INVALID_OR_MALFORMED_COMMAND; + *letter = **pstr; + (*pstr)++; + + // X-axis-becomes-a-hexadecimal-number get-value case, e.g. G0X100 --> G255 + if ((**pstr == '0') && (*(*pstr+1) == 'X')) { + *value = 0; (*pstr)++; + return STAT_OK; // pointer points to X + } - // X-axis-becomes-a-hexadecimal-number get-value case, e.g. G0X100 --> G255 - if ((**pstr == '0') && (*(*pstr+1) == 'X')) { - *value = 0; - (*pstr)++; - return STAT_OK; // pointer points to X - } + // get-value general case + char *end; + *value = strtof(*pstr, &end); + if (end == *pstr) return STAT_BAD_NUMBER_FORMAT; // more robust test then checking for value=0; + *pstr = end; - // get-value general case - char *end; - *value = strtof(*pstr, &end); - if(end == *pstr) - return STAT_BAD_NUMBER_FORMAT; // more robust test then checking for value=0; - *pstr = end; - return STAT_OK; // pointer points to next character after the word + return STAT_OK; // pointer points to next character after the word } -/* - * _point() - isolate the decimal point value as an integer - */ -static uint8_t _point(float value) -{ - return (uint8_t)(value*10 - trunc(value)*10); // isolate the decimal point as an int + +/// Isolate the decimal point value as an integer +static uint8_t _point(float value) { + return (uint8_t)(value * 10 - trunc(value) * 10); // isolate the decimal point as an int } -/* - * _validate_gcode_block() - check for some gross Gcode block semantic violations - */ -static stat_t _validate_gcode_block() -{ - // Check for modal group violations. From NIST, section 3.4 "It is an error to put - // a G-code from group 1 and a G-code from group 0 on the same line if both of them - // use axis words. If an axis word-using G-code from group 1 is implicitly in effect - // on a line (by having been activated on an earlier line), and a group 0 G-code that - // uses axis words appears on the line, the activity of the group 1 G-code is suspended - // for that line. The axis word-using G-codes from group 0 are G10, G28, G30, and G92" - -// if ((gp.modals[MODAL_GROUP_G0] == true) && (gp.modals[MODAL_GROUP_G1] == true)) { -// return STAT_MODAL_GROUP_VIOLATION; -// } - - // look for commands that require an axis word to be present -// if ((gp.modals[MODAL_GROUP_G0] == true) || (gp.modals[MODAL_GROUP_G1] == true)) { -// if (_axis_changed() == false) -// return STAT_GCODE_AXIS_IS_MISSING; -// } - return STAT_OK; +/// Check for some gross Gcode block semantic violations +static stat_t _validate_gcode_block() { + // Check for modal group violations. From NIST, section 3.4 "It is an error to put + // a G-code from group 1 and a G-code from group 0 on the same line if both of them + // use axis words. If an axis word-using G-code from group 1 is implicitly in effect + // on a line (by having been activated on an earlier line), and a group 0 G-code that + // uses axis words appears on the line, the activity of the group 1 G-code is suspended + // for that line. The axis word-using G-codes from group 0 are G10, G28, G30, and G92" + + // if ((gp.modals[MODAL_GROUP_G0] == true) && (gp.modals[MODAL_GROUP_G1] == true)) { + // return STAT_MODAL_GROUP_VIOLATION; + // } + + // look for commands that require an axis word to be present + // if ((gp.modals[MODAL_GROUP_G0] == true) || (gp.modals[MODAL_GROUP_G1] == true)) { + // if (_axis_changed() == false) + // return STAT_GCODE_AXIS_IS_MISSING; + // } + return STAT_OK; } + /* - * _parse_gcode_block() - parses one line of 0 terminated G-Code. + * Parses one line of 0 terminated G-Code. * * All the parser does is load the state values in gn (next model state) and set flags * in gf (model state flags). The execute routine applies them. The buffer is assumed to @@ -229,169 +215,171 @@ static stat_t _validate_gcode_block() * A number of implicit things happen when the gn struct is zeroed: * - inverse feed rate mode is canceled - set back to units_per_minute mode */ -static stat_t _parse_gcode_block(char_t *buf) -{ - 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(&gp, 0, sizeof(gp)); // clear all parser values - memset(&cm.gf, 0, sizeof(GCodeInput_t)); // clear all next-state flags - memset(&cm.gn, 0, sizeof(GCodeInput_t)); // clear all next-state values - cm.gn.motion_mode = cm_get_motion_mode(MODEL); // get motion mode from previous block - - // extract commands and parameters - while((status = _get_next_gcode_word(&pstr, &letter, &value)) == STAT_OK) { - switch(letter) { - case 'G': - switch((uint8_t)value) { - case 0: SET_MODAL (MODAL_GROUP_G1, motion_mode, MOTION_MODE_STRAIGHT_TRAVERSE); - case 1: SET_MODAL (MODAL_GROUP_G1, motion_mode, MOTION_MODE_STRAIGHT_FEED); - case 2: SET_MODAL (MODAL_GROUP_G1, motion_mode, MOTION_MODE_CW_ARC); - case 3: SET_MODAL (MODAL_GROUP_G1, motion_mode, MOTION_MODE_CCW_ARC); - case 4: SET_NON_MODAL (next_action, NEXT_ACTION_DWELL); - case 10: SET_MODAL (MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_COORD_DATA); - case 17: SET_MODAL (MODAL_GROUP_G2, select_plane, CANON_PLANE_XY); - case 18: SET_MODAL (MODAL_GROUP_G2, select_plane, CANON_PLANE_XZ); - case 19: SET_MODAL (MODAL_GROUP_G2, select_plane, CANON_PLANE_YZ); - case 20: SET_MODAL (MODAL_GROUP_G6, units_mode, INCHES); - case 21: SET_MODAL (MODAL_GROUP_G6, units_mode, MILLIMETERS); - case 28: { - switch (_point(value)) { - case 0: SET_MODAL (MODAL_GROUP_G0, next_action, NEXT_ACTION_GOTO_G28_POSITION); - case 1: SET_MODAL (MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_G28_POSITION); - case 2: SET_NON_MODAL (next_action, NEXT_ACTION_SEARCH_HOME); - case 3: SET_NON_MODAL (next_action, NEXT_ACTION_SET_ABSOLUTE_ORIGIN); - case 4: SET_NON_MODAL (next_action, NEXT_ACTION_HOMING_NO_SET); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 30: { - switch (_point(value)) { - case 0: SET_MODAL (MODAL_GROUP_G0, next_action, NEXT_ACTION_GOTO_G30_POSITION); - case 1: SET_MODAL (MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_G30_POSITION); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 38: { - switch (_point(value)) { - case 2: SET_NON_MODAL (next_action, NEXT_ACTION_STRAIGHT_PROBE); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 40: break; // ignore cancel cutter radius compensation - case 49: break; // ignore cancel tool length offset comp. - case 53: SET_NON_MODAL (absolute_override, true); - case 54: SET_MODAL (MODAL_GROUP_G12, coord_system, G54); - case 55: SET_MODAL (MODAL_GROUP_G12, coord_system, G55); - case 56: SET_MODAL (MODAL_GROUP_G12, coord_system, G56); - case 57: SET_MODAL (MODAL_GROUP_G12, coord_system, G57); - case 58: SET_MODAL (MODAL_GROUP_G12, coord_system, G58); - case 59: SET_MODAL (MODAL_GROUP_G12, coord_system, G59); - case 61: { - switch (_point(value)) { - case 0: SET_MODAL (MODAL_GROUP_G13, path_control, PATH_EXACT_PATH); - case 1: SET_MODAL (MODAL_GROUP_G13, path_control, PATH_EXACT_STOP); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 64: SET_MODAL (MODAL_GROUP_G13,path_control, PATH_CONTINUOUS); - case 80: SET_MODAL (MODAL_GROUP_G1, motion_mode, MOTION_MODE_CANCEL_MOTION_MODE); -// case 90: SET_MODAL (MODAL_GROUP_G3, distance_mode, ABSOLUTE_MODE); -// case 91: SET_MODAL (MODAL_GROUP_G3, distance_mode, INCREMENTAL_MODE); - case 90: { - switch (_point(value)) { - case 0: SET_MODAL (MODAL_GROUP_G3, distance_mode, ABSOLUTE_MODE); - case 1: SET_MODAL (MODAL_GROUP_G3, arc_distance_mode, ABSOLUTE_MODE); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 91: { - switch (_point(value)) { - case 0: SET_MODAL (MODAL_GROUP_G3, distance_mode, INCREMENTAL_MODE); - case 1: SET_MODAL (MODAL_GROUP_G3, arc_distance_mode, INCREMENTAL_MODE); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 92: { - switch (_point(value)) { - case 0: SET_MODAL (MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_ORIGIN_OFFSETS); - case 1: SET_NON_MODAL (next_action, NEXT_ACTION_RESET_ORIGIN_OFFSETS); - case 2: SET_NON_MODAL (next_action, NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS); - case 3: SET_NON_MODAL (next_action, NEXT_ACTION_RESUME_ORIGIN_OFFSETS); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - } - case 93: SET_MODAL (MODAL_GROUP_G5, feed_rate_mode, INVERSE_TIME_MODE); - case 94: SET_MODAL (MODAL_GROUP_G5, feed_rate_mode, UNITS_PER_MINUTE_MODE); -// case 95: SET_MODAL (MODAL_GROUP_G5, feed_rate_mode, UNITS_PER_REVOLUTION_MODE); - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; - } - break; - - case 'M': - switch((uint8_t)value) { - case 0: case 1: case 60: - SET_MODAL (MODAL_GROUP_M4, program_flow, PROGRAM_STOP); - case 2: case 30: - SET_MODAL (MODAL_GROUP_M4, program_flow, PROGRAM_END); - case 3: SET_MODAL (MODAL_GROUP_M7, spindle_mode, SPINDLE_CW); - case 4: SET_MODAL (MODAL_GROUP_M7, spindle_mode, SPINDLE_CCW); - case 5: SET_MODAL (MODAL_GROUP_M7, spindle_mode, SPINDLE_OFF); - case 6: SET_NON_MODAL (tool_change, true); - case 7: SET_MODAL (MODAL_GROUP_M8, mist_coolant, true); - case 8: SET_MODAL (MODAL_GROUP_M8, flood_coolant, true); - case 9: SET_MODAL (MODAL_GROUP_M8, flood_coolant, false); - case 48: SET_MODAL (MODAL_GROUP_M9, override_enables, true); - case 49: SET_MODAL (MODAL_GROUP_M9, override_enables, false); - case 50: SET_MODAL (MODAL_GROUP_M9, feed_rate_override_enable, true); // conditionally true - case 51: SET_MODAL (MODAL_GROUP_M9, spindle_override_enable, true); // conditionally true - default: status = STAT_MCODE_COMMAND_UNSUPPORTED; - } - 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, rotations - case 'S': SET_NON_MODAL (spindle_speed, 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); - case 'A': SET_NON_MODAL (target[AXIS_A], value); - case 'B': SET_NON_MODAL (target[AXIS_B], value); - case 'C': SET_NON_MODAL (target[AXIS_C], value); - // case 'U': SET_NON_MODAL (target[AXIS_U], value); // reserved - // case 'V': SET_NON_MODAL (target[AXIS_V], value); // reserved - // case 'W': SET_NON_MODAL (target[AXIS_W], value); // reserved - case 'I': SET_NON_MODAL (arc_offset[0], value); - case 'J': SET_NON_MODAL (arc_offset[1], value); - case 'K': SET_NON_MODAL (arc_offset[2], value); - case 'R': SET_NON_MODAL (arc_radius, value); - case 'N': SET_NON_MODAL (linenum,(uint32_t)value); // line number - case 'L': break; // not used for anything - default: status = STAT_GCODE_COMMAND_UNSUPPORTED; +static stat_t _parse_gcode_block(char_t *buf) { + 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(&gp, 0, sizeof(gp)); // clear all parser values + memset(&cm.gf, 0, sizeof(GCodeInput_t)); // clear all next-state flags + memset(&cm.gn, 0, sizeof(GCodeInput_t)); // clear all next-state values + cm.gn.motion_mode = cm_get_motion_mode(MODEL); // get motion mode from previous block + + // extract commands and parameters + while((status = _get_next_gcode_word(&pstr, &letter, &value)) == STAT_OK) { + switch(letter) { + case 'G': + switch((uint8_t)value) { + case 0: SET_MODAL(MODAL_GROUP_G1, motion_mode, MOTION_MODE_STRAIGHT_TRAVERSE); + case 1: SET_MODAL(MODAL_GROUP_G1, motion_mode, MOTION_MODE_STRAIGHT_FEED); + case 2: SET_MODAL(MODAL_GROUP_G1, motion_mode, MOTION_MODE_CW_ARC); + case 3: SET_MODAL(MODAL_GROUP_G1, motion_mode, MOTION_MODE_CCW_ARC); + case 4: SET_NON_MODAL(next_action, NEXT_ACTION_DWELL); + case 10: SET_MODAL(MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_COORD_DATA); + case 17: SET_MODAL(MODAL_GROUP_G2, select_plane, CANON_PLANE_XY); + case 18: SET_MODAL(MODAL_GROUP_G2, select_plane, CANON_PLANE_XZ); + case 19: SET_MODAL(MODAL_GROUP_G2, select_plane, CANON_PLANE_YZ); + case 20: SET_MODAL(MODAL_GROUP_G6, units_mode, INCHES); + case 21: SET_MODAL(MODAL_GROUP_G6, units_mode, MILLIMETERS); + case 28: + switch (_point(value)) { + case 0: SET_MODAL(MODAL_GROUP_G0, next_action, NEXT_ACTION_GOTO_G28_POSITION); + case 1: SET_MODAL(MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_G28_POSITION); + case 2: SET_NON_MODAL(next_action, NEXT_ACTION_SEARCH_HOME); + case 3: SET_NON_MODAL(next_action, NEXT_ACTION_SET_ABSOLUTE_ORIGIN); + case 4: SET_NON_MODAL(next_action, NEXT_ACTION_HOMING_NO_SET); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; } - if(status != STAT_OK) break; + break; + + case 30: + switch (_point(value)) { + case 0: SET_MODAL(MODAL_GROUP_G0, next_action, NEXT_ACTION_GOTO_G30_POSITION); + case 1: SET_MODAL(MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_G30_POSITION); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 38: + switch (_point(value)) { + case 2: SET_NON_MODAL(next_action, NEXT_ACTION_STRAIGHT_PROBE); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 40: break; // ignore cancel cutter radius compensation + case 49: break; // ignore cancel tool length offset comp. + case 53: SET_NON_MODAL(absolute_override, true); + case 54: SET_MODAL(MODAL_GROUP_G12, coord_system, G54); + case 55: SET_MODAL(MODAL_GROUP_G12, coord_system, G55); + case 56: SET_MODAL(MODAL_GROUP_G12, coord_system, G56); + case 57: SET_MODAL(MODAL_GROUP_G12, coord_system, G57); + case 58: SET_MODAL(MODAL_GROUP_G12, coord_system, G58); + case 59: SET_MODAL(MODAL_GROUP_G12, coord_system, G59); + case 61: + switch (_point(value)) { + case 0: SET_MODAL(MODAL_GROUP_G13, path_control, PATH_EXACT_PATH); + case 1: SET_MODAL(MODAL_GROUP_G13, path_control, PATH_EXACT_STOP); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 64: SET_MODAL(MODAL_GROUP_G13,path_control, PATH_CONTINUOUS); + case 80: SET_MODAL(MODAL_GROUP_G1, motion_mode, MOTION_MODE_CANCEL_MOTION_MODE); + // case 90: SET_MODAL(MODAL_GROUP_G3, distance_mode, ABSOLUTE_MODE); + // case 91: SET_MODAL(MODAL_GROUP_G3, distance_mode, INCREMENTAL_MODE); + case 90: + switch (_point(value)) { + case 0: SET_MODAL(MODAL_GROUP_G3, distance_mode, ABSOLUTE_MODE); + case 1: SET_MODAL(MODAL_GROUP_G3, arc_distance_mode, ABSOLUTE_MODE); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 91: + switch (_point(value)) { + case 0: SET_MODAL(MODAL_GROUP_G3, distance_mode, INCREMENTAL_MODE); + case 1: SET_MODAL(MODAL_GROUP_G3, arc_distance_mode, INCREMENTAL_MODE); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 92: + switch (_point(value)) { + case 0: SET_MODAL(MODAL_GROUP_G0, next_action, NEXT_ACTION_SET_ORIGIN_OFFSETS); + case 1: SET_NON_MODAL(next_action, NEXT_ACTION_RESET_ORIGIN_OFFSETS); + case 2: SET_NON_MODAL(next_action, NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS); + case 3: SET_NON_MODAL(next_action, NEXT_ACTION_RESUME_ORIGIN_OFFSETS); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 93: SET_MODAL(MODAL_GROUP_G5, feed_rate_mode, INVERSE_TIME_MODE); + case 94: SET_MODAL(MODAL_GROUP_G5, feed_rate_mode, UNITS_PER_MINUTE_MODE); + // case 95: SET_MODAL(MODAL_GROUP_G5, feed_rate_mode, UNITS_PER_REVOLUTION_MODE); + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; + } + break; + + case 'M': + switch ((uint8_t)value) { + case 0: case 1: case 60: + SET_MODAL(MODAL_GROUP_M4, program_flow, PROGRAM_STOP); + case 2: case 30: + SET_MODAL(MODAL_GROUP_M4, program_flow, PROGRAM_END); + case 3: SET_MODAL(MODAL_GROUP_M7, spindle_mode, SPINDLE_CW); + case 4: SET_MODAL(MODAL_GROUP_M7, spindle_mode, SPINDLE_CCW); + case 5: SET_MODAL(MODAL_GROUP_M7, spindle_mode, SPINDLE_OFF); + case 6: SET_NON_MODAL(tool_change, true); + case 7: SET_MODAL(MODAL_GROUP_M8, mist_coolant, true); + case 8: SET_MODAL(MODAL_GROUP_M8, flood_coolant, true); + case 9: SET_MODAL(MODAL_GROUP_M8, flood_coolant, false); + case 48: SET_MODAL(MODAL_GROUP_M9, override_enables, true); + case 49: SET_MODAL(MODAL_GROUP_M9, override_enables, false); + case 50: SET_MODAL(MODAL_GROUP_M9, feed_rate_override_enable, true); // conditionally true + case 51: SET_MODAL(MODAL_GROUP_M9, spindle_override_enable, true); // conditionally true + default: status = STAT_MCODE_COMMAND_UNSUPPORTED; + } + 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, rotations + case 'S': SET_NON_MODAL(spindle_speed, 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); + case 'A': SET_NON_MODAL(target[AXIS_A], value); + case 'B': SET_NON_MODAL(target[AXIS_B], value); + case 'C': SET_NON_MODAL(target[AXIS_C], value); + // case 'U': SET_NON_MODAL(target[AXIS_U], value); // reserved + // case 'V': SET_NON_MODAL(target[AXIS_V], value); // reserved + // case 'W': SET_NON_MODAL(target[AXIS_W], value); // reserved + case 'I': SET_NON_MODAL(arc_offset[0], value); + case 'J': SET_NON_MODAL(arc_offset[1], value); + case 'K': SET_NON_MODAL(arc_offset[2], value); + case 'R': SET_NON_MODAL(arc_radius, value); + case 'N': SET_NON_MODAL(linenum,(uint32_t)value); // line number + case 'L': break; // not used for anything + default: status = STAT_GCODE_COMMAND_UNSUPPORTED; } - if ((status != STAT_OK) && (status != STAT_COMPLETE)) return status; - ritorno(_validate_gcode_block()); - return _execute_gcode_block(); // if successful execute the block + if (status != STAT_OK) break; + } + + if ((status != STAT_OK) && (status != STAT_COMPLETE)) return status; + ritorno(_validate_gcode_block()); + + return _execute_gcode_block(); // if successful execute the block } + /* - * _execute_gcode_block() - execute parsed block + * Execute parsed block * * Conditionally (based on whether a flag is set in gf) call the canonical - * machining functions in order of execution as per RS274NGC_3 table 8 + * machining functions in order of execution as per RS274NGC_3 table 8 * (below, with modifications): * * 0. record the line number @@ -425,98 +413,89 @@ static stat_t _parse_gcode_block(char_t *buf) * Values in gn are in original units and should not be unit converted prior * to calling the canonical functions (which do the unit conversions) */ - -static stat_t _execute_gcode_block() -{ - stat_t status = STAT_OK; - - cm_set_model_linenum(cm.gn.linenum); - EXEC_FUNC(cm_set_feed_rate_mode, feed_rate_mode); - EXEC_FUNC(cm_set_feed_rate, feed_rate); - EXEC_FUNC(cm_feed_rate_override_factor, feed_rate_override_factor); - EXEC_FUNC(cm_traverse_override_factor, traverse_override_factor); - EXEC_FUNC(cm_set_spindle_speed, spindle_speed); - EXEC_FUNC(cm_spindle_override_factor, spindle_override_factor); - EXEC_FUNC(cm_select_tool, tool_select); // tool_select is where it's written - EXEC_FUNC(cm_change_tool, tool_change); - EXEC_FUNC(cm_spindle_control, spindle_mode); // spindle on or off - EXEC_FUNC(cm_mist_coolant_control, mist_coolant); - EXEC_FUNC(cm_flood_coolant_control, flood_coolant); // also disables mist coolant if 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); - - if (cm.gn.next_action == NEXT_ACTION_DWELL) { // G4 - dwell - ritorno(cm_dwell(cm.gn.parameter)); // return if error, otherwise complete the block +static stat_t _execute_gcode_block() { + stat_t status = STAT_OK; + + cm_set_model_linenum(cm.gn.linenum); + EXEC_FUNC(cm_set_feed_rate_mode, feed_rate_mode); + EXEC_FUNC(cm_set_feed_rate, feed_rate); + EXEC_FUNC(cm_feed_rate_override_factor, feed_rate_override_factor); + EXEC_FUNC(cm_traverse_override_factor, traverse_override_factor); + EXEC_FUNC(cm_set_spindle_speed, spindle_speed); + EXEC_FUNC(cm_spindle_override_factor, spindle_override_factor); + EXEC_FUNC(cm_select_tool, tool_select); // tool_select is where it's written + EXEC_FUNC(cm_change_tool, tool_change); + EXEC_FUNC(cm_spindle_control, spindle_mode); // spindle on or off + EXEC_FUNC(cm_mist_coolant_control, mist_coolant); + EXEC_FUNC(cm_flood_coolant_control, flood_coolant); // also disables mist coolant if 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); + + if (cm.gn.next_action == NEXT_ACTION_DWELL) // G4 - dwell + ritorno(cm_dwell(cm.gn.parameter)); // return if error, otherwise complete the block + + EXEC_FUNC(cm_select_plane, select_plane); + EXEC_FUNC(cm_set_units_mode, units_mode); + //--> cutter radius compensation goes here + //--> cutter length compensation goes here + EXEC_FUNC(cm_set_coord_system, coord_system); + EXEC_FUNC(cm_set_path_control, path_control); + EXEC_FUNC(cm_set_distance_mode, distance_mode); + //--> 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 + + 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_STRAIGHT_PROBE: status = cm_straight_probe(cm.gn.target, cm.gf.target); break; // G38.2 + + case NEXT_ACTION_SET_COORD_DATA: status = cm_set_coord_offsets(cm.gn.parameter, 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; + case NEXT_ACTION_RESET_ORIGIN_OFFSETS: status = cm_reset_origin_offsets(); break; + case NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS: status = cm_suspend_origin_offsets(); break; + case NEXT_ACTION_RESUME_ORIGIN_OFFSETS: status = cm_resume_origin_offsets(); break; + + case NEXT_ACTION_DEFAULT: + cm_set_absolute_override(MODEL, cm.gn.absolute_override); // apply override setting to gm struct + switch (cm.gn.motion_mode) { + case MOTION_MODE_CANCEL_MOTION_MODE: cm.gm.motion_mode = cm.gn.motion_mode; break; + case MOTION_MODE_STRAIGHT_TRAVERSE: status = cm_straight_traverse(cm.gn.target, cm.gf.target); break; + case MOTION_MODE_STRAIGHT_FEED: status = cm_straight_feed(cm.gn.target, cm.gf.target); break; + case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: + // gf.radius sets radius mode if radius was collected in gn + status = cm_arc_feed(cm.gn.target, cm.gf.target, cm.gn.arc_offset[0], cm.gn.arc_offset[1], + cm.gn.arc_offset[2], cm.gn.arc_radius, cm.gn.motion_mode); + break; } - EXEC_FUNC(cm_select_plane, select_plane); - EXEC_FUNC(cm_set_units_mode, units_mode); - //--> cutter radius compensation goes here - //--> cutter length compensation goes here - EXEC_FUNC(cm_set_coord_system, coord_system); - EXEC_FUNC(cm_set_path_control, path_control); - EXEC_FUNC(cm_set_distance_mode, distance_mode); - //--> 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 - - 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_STRAIGHT_PROBE: { status = cm_straight_probe(cm.gn.target, cm.gf.target); break;} // G38.2 - - case NEXT_ACTION_SET_COORD_DATA: { status = cm_set_coord_offsets(cm.gn.parameter, 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;} - case NEXT_ACTION_RESET_ORIGIN_OFFSETS: { status = cm_reset_origin_offsets(); break;} - case NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS: { status = cm_suspend_origin_offsets(); break;} - case NEXT_ACTION_RESUME_ORIGIN_OFFSETS: { status = cm_resume_origin_offsets(); break;} - - case NEXT_ACTION_DEFAULT: { - cm_set_absolute_override(MODEL, cm.gn.absolute_override); // apply override setting to gm struct - switch (cm.gn.motion_mode) { - case MOTION_MODE_CANCEL_MOTION_MODE: { cm.gm.motion_mode = cm.gn.motion_mode; break;} - case MOTION_MODE_STRAIGHT_TRAVERSE: { status = cm_straight_traverse(cm.gn.target, cm.gf.target); break;} - case MOTION_MODE_STRAIGHT_FEED: { status = cm_straight_feed(cm.gn.target, cm.gf.target); break;} - case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: - // gf.radius sets radius mode if radius was collected in gn - { status = cm_arc_feed(cm.gn.target, cm.gf.target, cm.gn.arc_offset[0], cm.gn.arc_offset[1], - cm.gn.arc_offset[2], cm.gn.arc_radius, cm.gn.motion_mode); break;} - } - } - } - cm_set_absolute_override(MODEL, false); // un-set absolute override once the move is planned - - // do the program stops and ends : M0, M1, M2, M30, M60 - if (cm.gf.program_flow == true) { - if (cm.gn.program_flow == PROGRAM_STOP) { - cm_program_stop(); - } else { - cm_program_end(); - } - } - return status; + } + cm_set_absolute_override(MODEL, false); // un-set absolute override once the move is planned + + // do the program stops and ends : M0, M1, M2, M30, M60 + if (cm.gf.program_flow == true) { + if (cm.gn.program_flow == PROGRAM_STOP) cm_program_stop(); + else cm_program_end(); + } + + return status; } -/*********************************************************************************** - * CONFIGURATION AND INTERFACE FUNCTIONS - * Functions to get and set variables from the cfgArray table - ***********************************************************************************/ +stat_t gc_get_gc(nvObj_t *nv) { + ritorno(nv_copy_string(nv, cs.saved_buf)); + nv->valuetype = TYPE_STRING; -stat_t gc_get_gc(nvObj_t *nv) -{ - ritorno(nv_copy_string(nv, cs.saved_buf)); - nv->valuetype = TYPE_STRING; - return STAT_OK; + return STAT_OK; } -stat_t gc_run_gc(nvObj_t *nv) -{ - return gc_gcode_parser(*nv->stringp); + +stat_t gc_run_gc(nvObj_t *nv) { + return gc_gcode_parser(*nv->stringp); } diff --git a/src/hardware.c b/src/hardware.c index af312f0..730961c 100644 --- a/src/hardware.c +++ b/src/hardware.c @@ -25,7 +25,7 @@ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include // used for software reset +#include // used for software reset #include "tinyg.h" // #1 #include "config.h" // #2 @@ -65,7 +65,7 @@ void hardware_init() { /* - * _get_id() - get a human readable signature + * Get a human readable signature * * Produce a unique deviceID based on the factory calibration data. * Format is: 123456-ABC @@ -93,7 +93,7 @@ static void _get_id(char_t *id) { char printable[33] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; uint8_t i; - NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc; // Load NVM Command register to read the calibration row + NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc; // Load NVM Command register to read the calibration row for (i = 0; i < 6; i++) id[i] = pgm_read_byte(LOTNUM0 + i); @@ -104,38 +104,29 @@ static void _get_id(char_t *id) { id[i++] = printable[(pgm_read_byte(COORDY0) & 0x1F)]; id[i] = 0; - NVM_CMD = NVM_CMD_NO_OPERATION_gc; // Clean up NVM Command register + NVM_CMD = NVM_CMD_NO_OPERATION_gc; // Clean up NVM Command register } -/* - * Hardware Reset Handlers - * - * hw_request_hard_reset() - * hw_hard_reset() - hard reset using watchdog timer - * hw_hard_reset_handler() - controller's rest handler - */ void hw_request_hard_reset() {cs.hard_reset_requested = true;} +/// Hard reset using watchdog timer void hw_hard_reset() { // software hard reset using the watchdog timer wdt_enable(WDTO_15MS); - while (true); // loops for about 15ms then resets + while (true); // loops for about 15ms then resets } +/// Controller's rest handler stat_t hw_hard_reset_handler() { if (cs.hard_reset_requested == false) return STAT_NOOP; hw_hard_reset(); // hard reset - identical to hitting RESET button return STAT_EAGAIN; } -/* - * Bootloader Handlers - * - * hw_request_bootloader() - * hw_request_bootloader_handler() - executes a software reset using CCPWrite - */ + +/// Executes a software reset using CCPWrite void hw_request_bootloader() {cs.bootloader_requested = true;} @@ -144,13 +135,13 @@ stat_t hw_bootloader_handler() { return STAT_NOOP; cli(); - CCPWrite(&RST.CTRL, RST_SWRST_bm); // fire a software reset + CCPWrite(&RST.CTRL, RST_SWRST_bm); // fire a software reset return STAT_EAGAIN; // never gets here but keeps the compiler happy } -/// hw_get_id() - get device ID (signature) +/// Get device ID (signature) stat_t hw_get_id(nvObj_t *nv) { char_t tmp[SYS_ID_LEN]; _get_id(tmp); @@ -160,21 +151,21 @@ stat_t hw_get_id(nvObj_t *nv) { } -/// hw_run_boot() - invoke boot form the cfgArray +/// Invoke boot form the cfgArray stat_t hw_run_boot(nvObj_t *nv) { hw_request_bootloader(); return STAT_OK; } -/// hw_set_hv() - set hardware version number +/// Set hardware version number stat_t hw_set_hv(nvObj_t *nv) { if (nv->value > TINYG_HARDWARE_VERSION_MAX) return STAT_INPUT_EXCEEDS_MAX_VALUE; set_flt(nv); // record the hardware version - _port_bindings(nv->value); // reset port bindings - switch_init(); // re-initialize the GPIO ports + _port_bindings(nv->value); // reset port bindings + switch_init(); // re-initialize the GPIO ports return STAT_OK; } diff --git a/src/hardware.h b/src/hardware.h index 24a6ae3..c80a2ee 100644 --- a/src/hardware.h +++ b/src/hardware.h @@ -163,7 +163,6 @@ enum cfgPortBits { // motor control port bit positions #define FREQUENCY_DWELL (float)10000 // Dwell count frequency in hz. #define LOAD_TIMER_PERIOD 100 // cycles you have to shut off SW interrupt #define EXEC_TIMER_PERIOD 100 // cycles you have to shut off SW interrupt -#define EXEC_TIMER_PERIOD_LONG 100 // cycles you have to shut off SW interrupt #define STEP_TIMER_TYPE TC0_struct // stepper subsybstem uses all the TC0's #define STEP_TIMER_DISABLE 0 // turn timer off (clock = 0 Hz) @@ -208,7 +207,6 @@ enum cfgPortBits { // motor control port bit positions are not assigned to the designated function - ur unpredicatable results will occur. */ - typedef struct { PORT_t *st_port[MOTORS]; // bindings for stepper motor ports (stepper.c) PORT_t *sw_port[MOTORS]; // bindings for switch ports (GPIO2) diff --git a/src/persistence.c b/src/persistence.c index 9f05d92..9aebe47 100644 --- a/src/persistence.c +++ b/src/persistence.c @@ -41,12 +41,9 @@ void persistence_init() { } -/************************************************************************************ - * read_persistent_value() - return value (as float) by index - * write_persistent_value() - write to NVM by index, but only if the value has changed - * - * It's the responsibility of the caller to make sure the index does not exceed range - */ +// It's the responsibility of the caller to make sure the index does not exceed range + +/// return value (as float) by index stat_t read_persistent_value(nvObj_t *nv) { nvm.address = nvm.profile_base + (nv->index * NVM_VALUE_LEN); EEPROM_ReadBytes(nvm.address, nvm.byte_array, NVM_VALUE_LEN); @@ -55,6 +52,7 @@ stat_t read_persistent_value(nvObj_t *nv) { } +/// write to NVM by index, but only if the value has changed stat_t write_persistent_value(nvObj_t *nv) { if (cm.cycle_state != CYCLE_OFF) return rpt_exception(STAT_FILE_NOT_OPEN); // can't write when machine is moving diff --git a/src/settings/settings_default.h b/src/settings/settings_default.h index 32cbd0c..6c9b44d 100644 --- a/src/settings/settings_default.h +++ b/src/settings/settings_default.h @@ -45,11 +45,14 @@ #define JUNCTION_DEVIATION 0.05 // default value, in mm #define JUNCTION_ACCELERATION 100000 // centripetal acceleration around corners + // Motor settings +#define MOTOR_MICROSTEPS 8 + #define M1_MOTOR_MAP AXIS_X // 1ma #define M1_STEP_ANGLE 1.8 // 1sa #define M1_TRAVEL_PER_REV 1.25 // 1tr -#define M1_MICROSTEPS 8 // 1mi 1,2,4,8 +#define M1_MICROSTEPS MOTOR_MICROSTEPS // 1mi #define M1_POLARITY 0 // 1po 0=normal, 1=reversed #define M1_POWER_MODE MOTOR_POWER_MODE // 1pm standard #define M1_POWER_LEVEL MOTOR_POWER_LEVEL // 1mp @@ -57,7 +60,7 @@ #define M2_MOTOR_MAP AXIS_Y #define M2_STEP_ANGLE 1.8 #define M2_TRAVEL_PER_REV 1.25 -#define M2_MICROSTEPS 256 +#define M2_MICROSTEPS MOTOR_MICROSTEPS #define M2_POLARITY 0 #define M2_POWER_MODE MOTOR_POWER_MODE #define M2_POWER_LEVEL MOTOR_POWER_LEVEL @@ -65,7 +68,7 @@ #define M3_MOTOR_MAP AXIS_Z #define M3_STEP_ANGLE 1.8 #define M3_TRAVEL_PER_REV 1.25 -#define M3_MICROSTEPS 256 +#define M3_MICROSTEPS MOTOR_MICROSTEPS #define M3_POLARITY 0 #define M3_POWER_MODE MOTOR_POWER_MODE #define M3_POWER_LEVEL MOTOR_POWER_LEVEL @@ -73,7 +76,7 @@ #define M4_MOTOR_MAP AXIS_A #define M4_STEP_ANGLE 1.8 #define M4_TRAVEL_PER_REV 360 // degrees moved per motor rev -#define M4_MICROSTEPS 256 +#define M4_MICROSTEPS MOTOR_MICROSTEPS #define M4_POLARITY 0 #define M4_POWER_MODE MOTOR_POWER_MODE #define M4_POWER_LEVEL MOTOR_POWER_LEVEL @@ -81,7 +84,7 @@ #define M5_MOTOR_MAP AXIS_B #define M5_STEP_ANGLE 1.8 #define M5_TRAVEL_PER_REV 360 // degrees moved per motor rev -#define M5_MICROSTEPS 8 +#define M5_MICROSTEPS MOTOR_MICROSTEPS #define M5_POLARITY 0 #define M5_POWER_MODE MOTOR_POWER_MODE #define M5_POWER_LEVEL MOTOR_POWER_LEVEL @@ -89,7 +92,7 @@ #define M6_MOTOR_MAP AXIS_C #define M6_STEP_ANGLE 1.8 #define M6_TRAVEL_PER_REV 360 // degrees moved per motor rev -#define M6_MICROSTEPS 256 +#define M6_MICROSTEPS MOTOR_MICROSTEPS #define M6_POLARITY 0 #define M6_POWER_MODE MOTOR_POWER_MODE #define M6_POWER_LEVEL MOTOR_POWER_LEVEL diff --git a/src/status.c b/src/status.c index 30dedb6..985032e 100644 --- a/src/status.c +++ b/src/status.c @@ -23,19 +23,13 @@ #include /**** Status Messages *************************************************************** - * get_status_message() - return the status message - * * See tinyg.h for status codes. These strings must align with the status codes in tinyg.h * The number of elements in the indexing array must match the # of strings - * - * Reference for putting display strings and string arrays in AVR program memory: - * http://www.cs.mun.ca/~paul/cs4723/material/atmel/avr-libc-user-manual-1.6.5/pgmspace.html */ stat_t status_code; // allocate a variable for the ritorno macro char global_string_buf[MESSAGE_LEN]; // allocate a string for global message use -/*** Status message strings ***/ static const char stat_00[] PROGMEM = "OK"; static const char stat_01[] PROGMEM = "Error"; @@ -341,6 +335,7 @@ static const char *const stat_msg[] PROGMEM = { }; +/// Return the status message char *get_status_message(stat_t status) { return (char *)GET_TEXT_ITEM(stat_msg, status); } diff --git a/src/stepper.c b/src/stepper.c index 44075e9..5c65f80 100644 --- a/src/stepper.c +++ b/src/stepper.c @@ -278,35 +278,29 @@ stat_t st_motor_power_callback() { // called by controller */ ISR(TIMER_DDA_ISR_vect) { if ((st_run.mot[MOTOR_1].substep_accumulator += st_run.mot[MOTOR_1].substep_increment) > 0) { - PORT_MOTOR_1_VPORT.OUT ^= STEP_BIT_bm; // turn step bit on + PORT_MOTOR_1_VPORT.OUT ^= STEP_BIT_bm; // toggle step line st_run.mot[MOTOR_1].substep_accumulator -= st_run.dda_ticks_X_substeps; INCREMENT_ENCODER(MOTOR_1); } if ((st_run.mot[MOTOR_2].substep_accumulator += st_run.mot[MOTOR_2].substep_increment) > 0) { - PORT_MOTOR_2_VPORT.OUT |= STEP_BIT_bm; + PORT_MOTOR_2_VPORT.OUT ^= STEP_BIT_bm; st_run.mot[MOTOR_2].substep_accumulator -= st_run.dda_ticks_X_substeps; INCREMENT_ENCODER(MOTOR_2); } if ((st_run.mot[MOTOR_3].substep_accumulator += st_run.mot[MOTOR_3].substep_increment) > 0) { - PORT_MOTOR_3_VPORT.OUT |= STEP_BIT_bm; + PORT_MOTOR_3_VPORT.OUT ^= STEP_BIT_bm; st_run.mot[MOTOR_3].substep_accumulator -= st_run.dda_ticks_X_substeps; INCREMENT_ENCODER(MOTOR_3); } if ((st_run.mot[MOTOR_4].substep_accumulator += st_run.mot[MOTOR_4].substep_increment) > 0) { - PORT_MOTOR_4_VPORT.OUT |= STEP_BIT_bm; + PORT_MOTOR_4_VPORT.OUT ^= STEP_BIT_bm; st_run.mot[MOTOR_4].substep_accumulator -= st_run.dda_ticks_X_substeps; INCREMENT_ENCODER(MOTOR_4); } - // Turn step bits off - pulse stretching for using external drivers. - //PORT_MOTOR_1_VPORT.OUT &= ~STEP_BIT_bm; // ~ 5 uSec pulse width - PORT_MOTOR_2_VPORT.OUT &= ~STEP_BIT_bm; // ~ 4 uSec - PORT_MOTOR_3_VPORT.OUT &= ~STEP_BIT_bm; // ~ 3 uSec - PORT_MOTOR_4_VPORT.OUT &= ~STEP_BIT_bm; // ~ 2 uSec - if (--st_run.dda_ticks_downcount != 0) return; TIMER_DDA.CTRLA = STEP_TIMER_DISABLE; // disable DDA timer diff --git a/src/text_parser.c b/src/text_parser.c index d9cf2ad..ea43c1d 100644 --- a/src/text_parser.c +++ b/src/text_parser.c @@ -88,6 +88,7 @@ stat_t text_parser(char_t *str) { status = nv_set(nv); // set (or run) single value if (status == STAT_OK) nv_persist(nv); // conditionally persist depending on flags in array } + nv_print_list(status, TEXT_MULTILINE_FORMATTED, JSON_RESPONSE_FORMAT); // print the results return status; } @@ -109,9 +110,10 @@ static stat_t _text_parser_kernal(char_t *str, nvObj_t *nv) { // parse fields into the nv struct nv->valuetype = TYPE_0; - if ((rd = strpbrk(str, separators)) == 0) { // no value part + if ((rd = strpbrk(str, separators)) == 0) // no value part strncpy(nv->token, str, TOKEN_LEN); - } else { + + else { *rd = 0; // terminate at end of name strncpy(nv->token, str, TOKEN_LEN); str = ++rd; @@ -120,7 +122,7 @@ static stat_t _text_parser_kernal(char_t *str, nvObj_t *nv) { } // validate and post-process the token - if ((nv->index = nv_get_index((const char_t *)"", nv->token)) == NO_MATCH) // get index or fail it + if ((nv->index = nv_get_index("", nv->token)) == NO_MATCH) // get index or fail it return STAT_UNRECOGNIZED_NAME; strcpy_P(nv->group, cfgArray[nv->index].group); // capture the group string if there is one diff --git a/src/util.c b/src/util.c index 4836f84..62270e9 100644 --- a/src/util.c +++ b/src/util.c @@ -35,17 +35,10 @@ #include "xmega/xmega_rtc.h" -/**** Vector utilities **** - * copy_vector() - copy vector of arbitrary length - * vector_equal() - test if vectors are equal - * get_axis_vector_length() - return the length of an axis vector - * set_vector() - load values into vector form - * set_vector_by_axis() - load a single value into a zero vector - */ - float vector[AXES]; // statically allocated global for vector utilities +/// Test if vectors are equal uint8_t vector_equal(const float a[], const float b[]) { if ((fp_EQ(a[AXIS_X], b[AXIS_X])) && (fp_EQ(a[AXIS_Y], b[AXIS_Y])) && @@ -60,6 +53,7 @@ uint8_t vector_equal(const float a[], const float b[]) { } +/// Return the length of an axis vector float get_axis_vector_length(const float a[], const float b[]) { return sqrt(square(a[AXIS_X] - b[AXIS_X] + square(a[AXIS_Y] - b[AXIS_Y]) + @@ -70,6 +64,7 @@ float get_axis_vector_length(const float a[], const float b[]) { } +/// Load values into vector form float *set_vector(float x, float y, float z, float a, float b, float c) { vector[AXIS_X] = x; vector[AXIS_Y] = y; @@ -81,6 +76,7 @@ float *set_vector(float x, float y, float z, float a, float b, float c) { } +/// load a single value into a zero vector float *set_vector_by_axis(float value, uint8_t axis) { clear_vector(vector); switch (axis) { @@ -106,7 +102,7 @@ float *set_vector_by_axis(float value, uint8_t axis) { * Implementation tip: Order the min and max values from most to least likely in the calling args * * (*) Macro min4 is about 20uSec, inline function version is closer to 10 uSec (Xmega 32 MHz) - * #define min3(a,b,c) (min(min(a,b),c)) + * #define min3(a,b,c) (min(min(a,b),c)) * #define min4(a,b,c,d) (min(min(a,b),min(c,d))) * #define max3(a,b,c) (max(max(a,b),c)) * #define max4(a,b,c,d) (max(max(a,b),max(c,d))) @@ -145,19 +141,13 @@ float max4(float x1, float x2, float x3, float x4) { } -/**** String utilities **** - * strcpy_U() - strcpy workalike to get around initial 0 for blank string - possibly wrong - * isnumber() - isdigit that also accepts plus, minus, and decimal point - * escape_string() - add escapes to a string - currently for quotes only - */ +/// isdigit that also accepts plus, minus, and decimal point uint8_t isnumber(char_t c) { - if (c == '.') return true; - if (c == '-') return true; - if (c == '+') return true; - return isdigit(c); + return c == '.' || c == '-' || c == '+' || isdigit(c); } +/// Add escapes to a string - currently for quotes only char_t *escape_string(char_t *dst, char_t *src) { char_t c; char_t *start_dst = dst; @@ -172,7 +162,7 @@ char_t *escape_string(char_t *dst, char_t *src) { /* - * pstr2str() - return an AVR style progmem string as a RAM string. + * Return an AVR style progmem string as a RAM string. * * This function copies a string from FLASH to a pre-allocated RAM buffer - * see main.c for allocation and max length. @@ -184,7 +174,7 @@ char_t *pstr2str(const char *pgm_string) { /* - * fntoa() - return ASCII string given a float and a decimal precision value + * Return ASCII string given a float and a decimal precision value * * Returns length of string, less the terminating 0 character */ @@ -193,24 +183,19 @@ char_t fntoa(char_t *str, float n, uint8_t precision) { if (isnan(n)) { strcpy(str, "nan"); return 3; + } - } else if (isinf(n)) { + if (isinf(n)) { strcpy(str, "inf"); return 3; + } - } else if (precision == 0 ) {return (char_t)sprintf((char *)str, "%0.0f", (double)n); - } else if (precision == 1 ) {return (char_t)sprintf((char *)str, "%0.1f", (double)n); - } else if (precision == 2 ) {return (char_t)sprintf((char *)str, "%0.2f", (double)n); - } else if (precision == 3 ) {return (char_t)sprintf((char *)str, "%0.3f", (double)n); - } else if (precision == 4 ) {return (char_t)sprintf((char *)str, "%0.4f", (double)n); - } else if (precision == 5 ) {return (char_t)sprintf((char *)str, "%0.5f", (double)n); - } else if (precision == 6 ) {return (char_t)sprintf((char *)str, "%0.6f", (double)n); - } else if (precision == 7 ) {return (char_t)sprintf((char *)str, "%0.7f", (double)n); - } else return (char_t)sprintf((char *)str, "%f", (double)n); + return (char_t)sprintf((char *)str, "%0.*f", (int)precision, (double)n); } + /* - * compute_checksum() - calculate the checksum for a string + * Calculate the checksum for a string * * Stops calculation on null termination or length value if non-zero. * @@ -232,7 +217,7 @@ uint16_t compute_checksum(char_t const *string, const uint16_t length) { } -/// SysTickTimer_getValue() - this is a hack to get around some compatibility problems +/// This is a hack to get around some compatibility problems uint32_t SysTickTimer_getValue() { return rtc.sys_ticks; } -- 2.27.0