From fbcbb269736f6dcc18f9302e98928ff1b37987aa Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Sat, 2 Jan 2016 19:31:55 -0800 Subject: [PATCH] More cleanup, removed MICROSTEP line settings --- src/canonical_machine.c | 375 ++++++------ src/canonical_machine.h | 1015 +++++++++++++++---------------- src/config.c | 32 +- src/encoder.c | 2 +- src/gcode_parser.c | 8 +- src/gcode_parser.h | 5 +- src/hardware.c | 2 +- src/hardware.h | 16 +- src/help.c | 10 +- src/json_parser.c | 4 +- src/persistence.c | 2 +- src/plan_exec.c | 48 +- src/plan_line.c | 2 +- src/plan_zoid.c | 2 +- src/planner.c | 6 +- src/report.c | 8 +- src/spindle.c | 2 +- src/stepper.c | 1274 +++++++++++++++++++-------------------- src/stepper.h | 329 +++++----- src/tinyg.h | 2 +- 20 files changed, 1529 insertions(+), 1615 deletions(-) diff --git a/src/canonical_machine.c b/src/canonical_machine.c index 34cbb2c..cc82c0f 100644 --- a/src/canonical_machine.c +++ b/src/canonical_machine.c @@ -27,7 +27,7 @@ */ /* - * This code is a loose implementation of Kramer, Proctor and Messina's canonical + * This code is a loose implementation of Kramer, Proctor and Messina's canonical * machining functions as described in the NIST RS274/NGC v3 * * The canonical machine is the layer between the Gcode parser and the motion control @@ -131,15 +131,16 @@ static int8_t _get_axis_type(const index_t index); * cm_set_motion_state() - adjusts active model pointer as well */ uint8_t cm_get_combined_state() { - if (cm.cycle_state == CYCLE_OFF) { cm.combined_state = cm.machine_state;} - else if (cm.cycle_state == CYCLE_PROBE) { cm.combined_state = COMBINED_PROBE;} - else if (cm.cycle_state == CYCLE_HOMING) { cm.combined_state = COMBINED_HOMING;} - else if (cm.cycle_state == CYCLE_JOG) { cm.combined_state = COMBINED_JOG;} + if (cm.cycle_state == CYCLE_OFF) cm.combined_state = cm.machine_state; + else if (cm.cycle_state == CYCLE_PROBE) cm.combined_state = COMBINED_PROBE; + else if (cm.cycle_state == CYCLE_HOMING) cm.combined_state = COMBINED_HOMING; + else if (cm.cycle_state == CYCLE_JOG) cm.combined_state = COMBINED_JOG; else { if (cm.motion_state == MOTION_RUN) cm.combined_state = COMBINED_RUN; if (cm.motion_state == MOTION_HOLD) cm.combined_state = COMBINED_HOLD; } - if (cm.machine_state == MACHINE_SHUTDOWN) { cm.combined_state = COMBINED_SHUTDOWN;} + + if (cm.machine_state == MACHINE_SHUTDOWN) cm.combined_state = COMBINED_SHUTDOWN; return cm.combined_state; } @@ -150,41 +151,43 @@ uint8_t cm_get_motion_state() {return cm.motion_state;} uint8_t cm_get_hold_state() {return cm.hold_state;} uint8_t cm_get_homing_state() {return cm.homing_state;} + void cm_set_motion_state(uint8_t motion_state) { cm.motion_state = motion_state; switch (motion_state) { - case (MOTION_STOP): { ACTIVE_MODEL = MODEL; break; } - case (MOTION_RUN): { ACTIVE_MODEL = RUNTIME; break; } - case (MOTION_HOLD): { ACTIVE_MODEL = RUNTIME; break; } + case (MOTION_STOP): ACTIVE_MODEL = MODEL; break; + case (MOTION_RUN): ACTIVE_MODEL = RUNTIME; break; + case (MOTION_HOLD): ACTIVE_MODEL = RUNTIME; break; } } -/* These getters and setters will work on any gm model with inputs: - * MODEL (GCodeState_t *)&cm.gm // absolute pointer from canonical machine gm model - * PLANNER (GCodeState_t *)&bf->gm // relative to buffer *bf is currently pointing to - * RUNTIME (GCodeState_t *)&mr.gm // absolute pointer from runtime mm struct - * ACTIVE_MODEL cm.am // active model pointer is maintained by state management + +/* These getters and setters will work on any gm model with inputs: + * MODEL (GCodeState_t *)&cm.gm // absolute pointer from canonical machine gm model + * PLANNER (GCodeState_t *)&bf->gm // relative to buffer *bf is currently pointing to + * RUNTIME (GCodeState_t *)&mr.gm // absolute pointer from runtime mm struct + * ACTIVE_MODEL cm.am // active model pointer is maintained by state management */ -uint32_t cm_get_linenum(GCodeState_t *gcode_state) { return gcode_state->linenum;} -uint8_t cm_get_motion_mode(GCodeState_t *gcode_state) { return gcode_state->motion_mode;} -uint8_t cm_get_coord_system(GCodeState_t *gcode_state) { return gcode_state->coord_system;} -uint8_t cm_get_units_mode(GCodeState_t *gcode_state) { return gcode_state->units_mode;} -uint8_t cm_get_select_plane(GCodeState_t *gcode_state) { return gcode_state->select_plane;} -uint8_t cm_get_path_control(GCodeState_t *gcode_state) { return gcode_state->path_control;} -uint8_t cm_get_distance_mode(GCodeState_t *gcode_state) { return gcode_state->distance_mode;} -uint8_t cm_get_feed_rate_mode(GCodeState_t *gcode_state) { return gcode_state->feed_rate_mode;} -uint8_t cm_get_tool(GCodeState_t *gcode_state) { return gcode_state->tool;} -uint8_t cm_get_spindle_mode(GCodeState_t *gcode_state) { return gcode_state->spindle_mode;} -uint8_t cm_get_block_delete_switch() { return cm.gmx.block_delete_switch;} -uint8_t cm_get_runtime_busy() { return mp_get_runtime_busy();} - -float cm_get_feed_rate(GCodeState_t *gcode_state) { return gcode_state->feed_rate;} - -void cm_set_motion_mode(GCodeState_t *gcode_state, uint8_t motion_mode) { gcode_state->motion_mode = motion_mode;} -void cm_set_spindle_mode(GCodeState_t *gcode_state, uint8_t spindle_mode) { gcode_state->spindle_mode = spindle_mode;} -void cm_set_spindle_speed_parameter(GCodeState_t *gcode_state, float speed) { gcode_state->spindle_speed = speed;} -void cm_set_tool_number(GCodeState_t *gcode_state, uint8_t tool) { gcode_state->tool = tool;} +uint32_t cm_get_linenum(GCodeState_t *gcode_state) {return gcode_state->linenum;} +uint8_t cm_get_motion_mode(GCodeState_t *gcode_state) {return gcode_state->motion_mode;} +uint8_t cm_get_coord_system(GCodeState_t *gcode_state) {return gcode_state->coord_system;} +uint8_t cm_get_units_mode(GCodeState_t *gcode_state) {return gcode_state->units_mode;} +uint8_t cm_get_select_plane(GCodeState_t *gcode_state) {return gcode_state->select_plane;} +uint8_t cm_get_path_control(GCodeState_t *gcode_state) {return gcode_state->path_control;} +uint8_t cm_get_distance_mode(GCodeState_t *gcode_state) {return gcode_state->distance_mode;} +uint8_t cm_get_feed_rate_mode(GCodeState_t *gcode_state) {return gcode_state->feed_rate_mode;} +uint8_t cm_get_tool(GCodeState_t *gcode_state) {return gcode_state->tool;} +uint8_t cm_get_spindle_mode(GCodeState_t *gcode_state) {return gcode_state->spindle_mode;} +uint8_t cm_get_block_delete_switch() {return cm.gmx.block_delete_switch;} +uint8_t cm_get_runtime_busy() {return mp_get_runtime_busy();} + +float cm_get_feed_rate(GCodeState_t *gcode_state) {return gcode_state->feed_rate;} + +void cm_set_motion_mode(GCodeState_t *gcode_state, uint8_t motion_mode) {gcode_state->motion_mode = motion_mode;} +void cm_set_spindle_mode(GCodeState_t *gcode_state, uint8_t spindle_mode) {gcode_state->spindle_mode = spindle_mode;} +void cm_set_spindle_speed_parameter(GCodeState_t *gcode_state, float speed) {gcode_state->spindle_speed = speed;} +void cm_set_tool_number(GCodeState_t *gcode_state, uint8_t tool) {gcode_state->tool = tool;} void cm_set_absolute_override(GCodeState_t *gcode_state, uint8_t absolute_override) { gcode_state->absolute_override = absolute_override; @@ -347,7 +350,7 @@ void cm_update_model_position_from_runtime() {copy_vector(cm.gmx.position, mr.gm */ stat_t cm_deferred_write_callback() { if ((cm.cycle_state == CYCLE_OFF) && (cm.deferred_write_flag == true)) { - if (!usart_rx_empty()) return STAT_OK; // don't write back if serial RX is not empty + if (!usart_rx_empty()) return STAT_OK; // don't write back if serial RX is not empty cm.deferred_write_flag = false; nvObj_t nv; for (uint8_t i=1; i<=COORDS; i++) @@ -355,7 +358,7 @@ stat_t cm_deferred_write_callback() { sprintf((char *)nv.token, "g%2d%c", 53+i, ("xyzabc")[j]); nv.index = nv_get_index((const char_t *)"", nv.token); nv.value = cm.offset[i][j]; - nv_persist(&nv); // Note: only writes values that have changed + nv_persist(&nv); // Note: only writes values that have changed } } @@ -373,9 +376,9 @@ stat_t cm_deferred_write_callback() { * - computation and application of axis modes as so: * * DISABLED - Incoming value is ignored. Target value is not changed - * ENABLED - Convert axis values to canonical format and store as target + * ENABLED - Convert axis values to canonical format and store as target * INHIBITED - Same processing as ENABLED, but axis will not actually be run - * RADIUS - ABC axis value is provided in Gcode block in linear units + * RADIUS - ABC axis value is provided in Gcode block in linear units * - Target is set to degrees based on axis' Radius value * - Radius mode is only processed for ABC axes. Application to XYZ is ignored. * @@ -388,7 +391,7 @@ stat_t cm_deferred_write_callback() { // ALDEN: This shows up in avr-gcc 4.7.0 and avr-libc 1.8.0 static float _calc_ABC(uint8_t axis, float target[], float flag[]) { if ((cm.a[axis].axis_mode == AXIS_STANDARD) || (cm.a[axis].axis_mode == AXIS_INHIBITED)) - return(target[axis]); // no mm conversion - it's in degrees + return target[axis]; // no mm conversion - it's in degrees return _to_millimeters(target[axis]) * 360 / (2 * M_PI * cm.a[axis].radius); } @@ -465,13 +468,12 @@ stat_t cm_test_soft_limits(float target[]) { /// canonical_machine_init() - Config init cfg_init() must have been run beforehand void canonical_machine_init() { // If you can assume all memory has been zeroed by a hard reset you don't need this code: - // memset(&cm, 0, sizeof(cm)); // do not reset canonicalMachineSingleton once it's been initialized - memset(&cm.gm, 0, sizeof(GCodeState_t)); // clear all values, pointers and status + 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(GCodeInput_t)); - canonical_machine_init_assertions(); // establish assertions - ACTIVE_MODEL = MODEL; // setup initial Gcode model pointer + canonical_machine_init_assertions(); // establish assertions + ACTIVE_MODEL = MODEL; // setup initial Gcode model pointer // set gcode defaults cm_set_units_mode(cm.units_mode); @@ -479,7 +481,7 @@ void canonical_machine_init() { cm_select_plane(cm.select_plane); cm_set_path_control(cm.path_control); cm_set_distance_mode(cm.distance_mode); - cm_set_feed_rate_mode(UNITS_PER_MINUTE_MODE);// always the default + cm_set_feed_rate_mode(UNITS_PER_MINUTE_MODE); // always the default cm.gmx.block_delete_switch = true; @@ -505,7 +507,6 @@ void canonical_machine_init() { * canonical_machine_init_assertions() * canonical_machine_test_assertions() - test assertions, return error code if violation exists */ - void canonical_machine_init_assertions() { cm.magic_start = MAGICNUM; cm.magic_end = MAGICNUM; @@ -527,11 +528,11 @@ stat_t canonical_machine_test_assertions() { /* * cm_soft_alarm() - alarm state; send an exception report and stop processing input - * cm_clear() - clear soft alarm + * cm_clear() - clear soft alarm * cm_hard_alarm() - alarm state; send an exception report and shut down machine */ stat_t cm_soft_alarm(stat_t status) { - rpt_exception(status); // send alarm message + rpt_exception(status); // send alarm message cm.machine_state = MACHINE_ALARM; return status; // NB: More efficient than inlining rpt_exception() call. } @@ -548,7 +549,7 @@ stat_t cm_clear(nvObj_t *nv) { // clear soft alarm stat_t cm_hard_alarm(stat_t status) { // stop the motors and the spindle - stepper_init(); // hard stop + stepper_init(); // hard stop cm_spindle_control(SPINDLE_OFF); rpt_exception(status); // send shutdown message cm.machine_state = MACHINE_SHUTDOWN; @@ -577,12 +578,12 @@ stat_t cm_select_plane(uint8_t plane) { stat_t cm_set_units_mode(uint8_t mode) { cm.gm.units_mode = mode; // 0 = inches, 1 = mm. - return(STAT_OK); + return STAT_OK; } stat_t cm_set_distance_mode(uint8_t mode) { - cm.gm.distance_mode = mode; // 0 = absolute mode, 1 = incremental + cm.gm.distance_mode = mode; // 0 = absolute mode, 1 = incremental return STAT_OK; } @@ -622,19 +623,19 @@ stat_t cm_set_coord_system(uint8_t coord_system) { cm.gm.coord_system = coord_system; float value[AXES] = { (float)coord_system,0,0,0,0,0 }; // pass coordinate system in value[0] element - mp_queue_command(_exec_offset, value, value); // second vector (flags) is not used, so fake it + mp_queue_command(_exec_offset, value, value); // second vector (flags) is not used, so fake it return STAT_OK; } static void _exec_offset(float *value, float *flag) { - uint8_t coord_system = ((uint8_t)value[0]); // coordinate system is passed in value[0] element + uint8_t coord_system = ((uint8_t)value[0]); // coordinate system is passed in value[0] element float offsets[AXES]; for (uint8_t axis = AXIS_X; axis < AXES; axis++) offsets[axis] = cm.offset[coord_system][axis] + (cm.gmx.origin_offset[axis] * cm.gmx.origin_offset_enable); mp_set_runtime_work_offset(offsets); - cm_set_work_offsets(MODEL); // set work offsets in the Gcode model + cm_set_work_offsets(MODEL); // set work offsets in the Gcode model } @@ -645,7 +646,7 @@ static void _exec_offset(float *value, float *flag) { * This is useful for setting origins for homing, probing, and other operations. * * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !!!!! DO NOT CALL THIS FUNCTION WHILE IN A MACHINING CYCLE !!!!! + * !!!!! DO NOT CALL THIS FUNCTION WHILE IN A MACHINING CYCLE !!!!! * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * More specifically, do not call this function if there are any moves in the planner or @@ -685,9 +686,9 @@ stat_t cm_set_absolute_origin(float origin[], float flag[]) { for (uint8_t axis = AXIS_X; axis < AXES; axis++) if (fp_TRUE(flag[axis])) { value[axis] = _to_millimeters(origin[axis]); - cm.gmx.position[axis] = value[axis]; // set model position + cm.gmx.position[axis] = value[axis]; // set model position cm.gm.target[axis] = value[axis]; // reset model target - mp_set_planner_position(axis, value[axis]); // set mm position + mp_set_planner_position(axis, value[axis]); // set mm position } mp_queue_command(_exec_absolute_origin, value, flag); @@ -708,9 +709,9 @@ static void _exec_absolute_origin(float *value, float *flag) { /* - * cm_set_origin_offsets() - G92 - * cm_reset_origin_offsets() - G92.1 - * cm_suspend_origin_offsets() - G92.2 + * cm_set_origin_offsets() - G92 + * cm_reset_origin_offsets() - G92.1 + * cm_suspend_origin_offsets() - G92.2 * cm_resume_origin_offsets() - G92.3 * * G92's behave according to NIST 3.5.18 & LinuxCNC G92 @@ -726,7 +727,7 @@ stat_t cm_set_origin_offsets(float offset[], float flag[]) { // now pass the offset to the callback - setting the coordinate system also applies the offsets float value[AXES] = { (float)cm.gm.coord_system,0,0,0,0,0 }; // pass coordinate system in value[0] element - mp_queue_command(_exec_offset, value, value); // second vector is not used + mp_queue_command(_exec_offset, value, value); // second vector is not used return STAT_OK; } @@ -765,10 +766,8 @@ stat_t cm_resume_origin_offsets() { /***************************** * Free Space Motion (4.3.4) * *****************************/ -/* - * cm_straight_traverse() - G0 linear rapid - */ +/// G0 linear rapid stat_t cm_straight_traverse(float target[], float flags[]) { cm.gm.motion_mode = MOTION_MODE_STRAIGHT_TRAVERSE; cm_set_model_target(target, flags); @@ -779,8 +778,8 @@ stat_t cm_straight_traverse(float target[], float flags[]) { // prep and plan the move cm_set_work_offsets(&cm.gm); // capture the fully resolved offsets to the state - cm_cycle_start(); // required for homing & other cycles - mp_aline(&cm.gm); // send the move to the planner + cm_cycle_start(); // required for homing & other cycles + mp_aline(&cm.gm); // send the move to the planner cm_finalize_move(); return STAT_OK; } @@ -800,10 +799,10 @@ stat_t cm_set_g28_position() { stat_t cm_goto_g28_position(float target[], float flags[]) { cm_set_absolute_override(MODEL, true); - cm_straight_traverse(target, flags); // move through intermediate point, or skip - while (mp_get_planner_buffers_available() == 0); // make sure you have an available buffer - float f[] = {1,1,1,1,1,1}; - return cm_straight_traverse(cm.gmx.g28_position, f);// execute actual stored move + cm_straight_traverse(target, flags); // move through intermediate point, or skip + while (mp_get_planner_buffers_available() == 0); // make sure you have an available buffer + float f[] = {1, 1, 1, 1, 1, 1}; + return cm_straight_traverse(cm.gmx.g28_position, f); // execute actual stored move } @@ -815,10 +814,10 @@ stat_t cm_set_g30_position() { stat_t cm_goto_g30_position(float target[], float flags[]) { cm_set_absolute_override(MODEL, true); - cm_straight_traverse(target, flags); // move through intermediate point, or skip - while (mp_get_planner_buffers_available() == 0); // make sure you have an available buffer - float f[] = {1,1,1,1,1,1}; - return cm_straight_traverse(cm.gmx.g30_position, f);// execute actual stored move + cm_straight_traverse(target, flags); // move through intermediate point, or skip + while (mp_get_planner_buffers_available() == 0); // make sure you have an available buffer + float f[] = {1, 1, 1, 1, 1, 1}; + return cm_straight_traverse(cm.gmx.g30_position, f); // execute actual stored move } @@ -842,8 +841,8 @@ stat_t cm_set_feed_rate(float feed_rate) { /* * cm_set_feed_rate_mode() - G93, G94 (affects MODEL only) * - * INVERSE_TIME_MODE = 0, // G93 - * UNITS_PER_MINUTE_MODE, // G94 + * INVERSE_TIME_MODE = 0, // G93 + * UNITS_PER_MINUTE_MODE, // G94 * UNITS_PER_REVOLUTION_MODE // G95 (unimplemented) */ stat_t cm_set_feed_rate_mode(uint8_t mode) { @@ -852,9 +851,7 @@ stat_t cm_set_feed_rate_mode(uint8_t mode) { } -/* - * cm_set_path_control() - G61, G61.1, G64 (affects MODEL only) - */ +/// G61, G61.1, G64 (affects MODEL only) stat_t cm_set_path_control(uint8_t mode) { cm.gm.path_control = mode; return STAT_OK; @@ -868,9 +865,8 @@ stat_t cm_set_path_control(uint8_t mode) { * cm_arc_feed() - SEE plan_arc.c(pp) */ -/* - * cm_dwell() - G4, P parameter (seconds) - */ + +/// G4, P parameter (seconds) stat_t cm_dwell(float seconds) { cm.gm.parameter = seconds; mp_dwell(seconds); @@ -878,9 +874,7 @@ stat_t cm_dwell(float seconds) { } -/* - * cm_straight_feed() - G1 - */ +/// G1 stat_t cm_straight_feed(float target[], float flags[]) { // trap zero feed rate condition if ((cm.gm.feed_rate_mode != INVERSE_TIME_MODE) && (fp_ZERO(cm.gm.feed_rate))) @@ -895,8 +889,8 @@ stat_t cm_straight_feed(float target[], float flags[]) { // prep and plan the move cm_set_work_offsets(&cm.gm); // capture the fully resolved offsets to the state - cm_cycle_start(); // required for homing & other cycles - status = mp_aline(&cm.gm); // send the move to the planner + cm_cycle_start(); // required for homing & other cycles + status = mp_aline(&cm.gm); // send the move to the planner cm_finalize_move(); return status; } @@ -912,16 +906,16 @@ stat_t cm_straight_feed(float target[], float flags[]) { **************************/ /* * cm_select_tool() - T parameter - * _exec_select_tool() - execution callback + * _exec_select_tool() - execution callback * * cm_change_tool() - M6 (This might become a complete tool change cycle) - * _exec_change_tool() - execution callback + * _exec_change_tool() - execution callback * * Note: These functions don't actually do anything for now, and there's a bug * where T and M in different blocks don;t work correctly */ stat_t cm_select_tool(uint8_t tool_select) { - float value[AXES] = { (float)tool_select,0,0,0,0,0 }; + float value[AXES] = {(float)tool_select, 0, 0, 0, 0, 0}; mp_queue_command(_exec_select_tool, value, value); return STAT_OK; } @@ -933,7 +927,7 @@ static void _exec_select_tool(float *value, float *flag) { stat_t cm_change_tool(uint8_t tool_change) { - float value[AXES] = { (float)cm.gm.tool_select,0,0,0,0,0 }; + float value[AXES] = {(float)cm.gm.tool_select, 0, 0, 0, 0, 0}; mp_queue_command(_exec_change_tool, value, value); return STAT_OK; } @@ -952,7 +946,7 @@ static void _exec_change_tool(float *value, float *flag) { * cm_flood_coolant_control() - M8, M9 */ stat_t cm_mist_coolant_control(uint8_t mist_coolant) { - float value[AXES] = { (float)mist_coolant,0,0,0,0,0 }; + float value[AXES] = {(float)mist_coolant, 0, 0, 0, 0, 0}; mp_queue_command(_exec_mist_coolant_control, value, value); return STAT_OK; } @@ -961,14 +955,13 @@ stat_t cm_mist_coolant_control(uint8_t mist_coolant) { static void _exec_mist_coolant_control(float *value, float *flag) { cm.gm.mist_coolant = (uint8_t)value[0]; - if (cm.gm.mist_coolant == true) - gpio_set_bit_on(MIST_COOLANT_BIT); // if - gpio_set_bit_off(MIST_COOLANT_BIT); // else + if (cm.gm.mist_coolant == true) gpio_set_bit_on(MIST_COOLANT_BIT); + else gpio_set_bit_off(MIST_COOLANT_BIT); } stat_t cm_flood_coolant_control(uint8_t flood_coolant) { - float value[AXES] = { (float)flood_coolant,0,0,0,0,0 }; + float value[AXES] = {(float)flood_coolant, 0, 0, 0, 0, 0}; mp_queue_command(_exec_flood_coolant_control, value, value); return STAT_OK; } @@ -998,7 +991,7 @@ static void _exec_flood_coolant_control(float *value, float *flag) { * Override enables are kind of a mess in Gcode. This is an attempt to sort them out. * See http://www.linuxcnc.org/docs/2.4/html/gcode_main.html#sec:M50:-Feed-Override */ -stat_t cm_override_enables(uint8_t flag) { // M48, M49 +stat_t cm_override_enables(uint8_t flag) { // M48, M49 cm.gmx.feed_rate_override_enable = flag; cm.gmx.traverse_override_enable = flag; cm.gmx.spindle_override_enable = flag; @@ -1006,7 +999,7 @@ stat_t cm_override_enables(uint8_t flag) { // M48, M49 } -stat_t cm_feed_rate_override_enable(uint8_t flag) { // M50 +stat_t cm_feed_rate_override_enable(uint8_t flag) { // M50 if (fp_TRUE(cm.gf.parameter) && fp_ZERO(cm.gn.parameter)) cm.gmx.feed_rate_override_enable = false; else cm.gmx.feed_rate_override_enable = true; @@ -1015,14 +1008,14 @@ stat_t cm_feed_rate_override_enable(uint8_t flag) { // M50 } -stat_t cm_feed_rate_override_factor(uint8_t flag) { // M50.1 +stat_t cm_feed_rate_override_factor(uint8_t flag) { // M50.1 cm.gmx.feed_rate_override_enable = flag; cm.gmx.feed_rate_override_factor = cm.gn.parameter; return STAT_OK; } -stat_t cm_traverse_override_enable(uint8_t flag) { // M50.2 +stat_t cm_traverse_override_enable(uint8_t flag) { // M50.2 if (fp_TRUE(cm.gf.parameter) && fp_ZERO(cm.gn.parameter)) cm.gmx.traverse_override_enable = false; else cm.gmx.traverse_override_enable = true; @@ -1031,7 +1024,7 @@ stat_t cm_traverse_override_enable(uint8_t flag) { // M50.2 } -stat_t cm_traverse_override_factor(uint8_t flag) { // M51 +stat_t cm_traverse_override_factor(uint8_t flag) { // M51 cm.gmx.traverse_override_enable = flag; cm.gmx.traverse_override_factor = cm.gn.parameter; return STAT_OK; @@ -1073,12 +1066,12 @@ void cm_message(char_t *message) { * It is extended beyond the NIST spec to handle various situations. * * _exec_program_finalize() - * cm_cycle_start() (no Gcode) Do a cycle start right now - * cm_cycle_end() (no Gcode) Do a cycle end right now - * cm_feedhold() (no Gcode) Initiate a feedhold right now - * cm_program_stop() (M0, M60) Queue a program stop - * cm_optional_program_stop() (M1) - * cm_program_end() (M2, M30) + * cm_cycle_start() (no Gcode) Do a cycle start right now + * cm_cycle_end() (no Gcode) Do a cycle end right now + * cm_feedhold() (no Gcode) Initiate a feedhold right now + * cm_program_stop() (M0, M60) Queue a program stop + * cm_optional_program_stop() (M1) + * cm_program_end() (M2, M30) * cm_machine_ready() puts machine into a READY state * * cm_program_stop and cm_optional_program_stop are synchronous Gcode @@ -1108,15 +1101,15 @@ void cm_message(char_t *message) { * * A queue flush request received during motion should be ignored but not reset * A queue flush request received during a feedhold should be deferred until - * the feedhold enters a HOLD state (i.e. until deceleration is complete) + * the feedhold enters a HOLD state (i.e. until deceleration is complete) * A queue flush request received during a motion stop should be honored * * A cycle start request received during motion should be ignored and reset * A cycle start request received during a feedhold should be deferred until - * the feedhold enters a HOLD state (i.e. until deceleration is complete) - * If a queue flush request is also present the queue flush should be done first + * the feedhold enters a HOLD state (i.e. until deceleration is complete) + * If a queue flush request is also present the queue flush should be done first * A cycle start request received during a motion stop should be honored and - * should start to run anything in the planner queue + * should start to run anything in the planner queue */ void cm_request_feedhold() {cm.feedhold_requested = true;} @@ -1128,8 +1121,9 @@ stat_t cm_feedhold_sequencing_callback() { if (cm.feedhold_requested == true) { if ((cm.motion_state == MOTION_RUN) && (cm.hold_state == FEEDHOLD_OFF)) { cm_set_motion_state(MOTION_HOLD); - cm.hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution + cm.hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution } + cm.feedhold_requested = false; } @@ -1142,7 +1136,7 @@ stat_t cm_feedhold_sequencing_callback() { } } - bool feedhold_processing = // added feedhold processing lockout from omco fork + bool feedhold_processing = // added feedhold processing lockout from omco fork cm.hold_state == FEEDHOLD_SYNC || cm.hold_state == FEEDHOLD_PLAN || cm.hold_state == FEEDHOLD_DECEL; @@ -1167,11 +1161,11 @@ stat_t cm_queue_flush() { rx_request_rx_report(); // Note: The following uses low-level mp calls for absolute position. - // It could also use cm_get_absolute_position(RUNTIME, axis); + // It could also use cm_get_absolute_position(RUNTIME, axis); for (uint8_t axis = AXIS_X; axis < AXES; axis++) cm_set_position(axis, mp_get_runtime_absolute_position(axis)); // set mm from mr - float value[AXES] = { (float)MACHINE_PROGRAM_STOP, 0,0,0,0,0 }; + float value[AXES] = {(float)MACHINE_PROGRAM_STOP, 0,0,0,0,0}; _exec_program_finalize(value, value); // finalize now, not later return STAT_OK; @@ -1185,8 +1179,8 @@ stat_t cm_queue_flush() { * cm_cycle_start() * cm_cycle_end() * cm_program_stop() - M0 - * cm_optional_program_stop() - M1 - * cm_program_end() - M2, M30 + * cm_optional_program_stop() - M1 + * cm_program_end() - M2, M30 * * cm_program_end() implements M2 and M30 * The END behaviors are defined by NIST 3.6.1 are: @@ -1206,7 +1200,7 @@ stat_t cm_queue_flush() { * 2. Selected plane is set to default plane ($gpl) (instead of setting it to G54) * 3. Distance mode is set to MODE_ABSOLUTE (like G90) * 4. Feed rate mode is set to UNITS_PER_MINUTE (like G94) - * 5. Not implemented + * 5. Not implemented * 6. Not implemented * 7. The spindle is stopped (like M5) * 8. Motion mode is canceled like G80 (not set to G1) @@ -1217,34 +1211,34 @@ static void _exec_program_finalize(float *value, float *flag) { cm.machine_state = (uint8_t)value[0]; cm_set_motion_state(MOTION_STOP); if (cm.cycle_state == CYCLE_MACHINING) - cm.cycle_state = CYCLE_OFF; // don't end cycle if homing, probing, etc. + cm.cycle_state = CYCLE_OFF; // don't end cycle if homing, probing, etc. - cm.hold_state = FEEDHOLD_OFF; // end feedhold (if in feed hold) - cm.cycle_start_requested = false; // cancel any pending cycle start request - mp_zero_segment_velocity(); // for reporting purposes + cm.hold_state = FEEDHOLD_OFF; // end feedhold (if in feed hold) + cm.cycle_start_requested = false; // cancel any pending cycle start request + mp_zero_segment_velocity(); // for reporting purposes // perform the following resets if it's a program END if (cm.machine_state == MACHINE_PROGRAM_END) { - cm_reset_origin_offsets(); // G92.1 - we do G91.1 instead of G92.2 + cm_reset_origin_offsets(); // G92.1 - we do G91.1 instead of G92.2 cm_set_coord_system(cm.coord_system); // reset to default coordinate system cm_select_plane(cm.select_plane); // reset to default arc plane cm_set_distance_mode(cm.distance_mode); - cm_spindle_control(SPINDLE_OFF); // M5 - cm_flood_coolant_control(false); // M9 + cm_spindle_control(SPINDLE_OFF); // M5 + cm_flood_coolant_control(false); // M9 cm_set_feed_rate_mode(UNITS_PER_MINUTE_MODE); // G94 cm_set_motion_mode(MODEL, MOTION_MODE_CANCEL_MOTION_MODE); } - sr_request_status_report(SR_IMMEDIATE_REQUEST); // request a final status report (not unfiltered) + sr_request_status_report(SR_IMMEDIATE_REQUEST); // request a final status report (not unfiltered) } void cm_cycle_start() { cm.machine_state = MACHINE_CYCLE; - if (cm.cycle_state == CYCLE_OFF) { // don't (re)start homing, probe or other canned cycles + if (cm.cycle_state == CYCLE_OFF) { // don't (re)start homing, probe or other canned cycles cm.cycle_state = CYCLE_MACHINING; - qr_init_queue_report(); // clear queue reporting buffer counts + qr_init_queue_report(); // clear queue reporting buffer counts } } @@ -1282,18 +1276,18 @@ void cm_program_end() { static const char msg_units0[] PROGMEM = " in"; // used by generic print functions static const char msg_units1[] PROGMEM = " mm"; static const char msg_units2[] PROGMEM = " deg"; -static const char *const msg_units[] PROGMEM = { msg_units0, msg_units1, msg_units2 }; +static const char *const msg_units[] PROGMEM = {msg_units0, msg_units1, msg_units2}; #define DEGREE_INDEX 2 static const char msg_am00[] PROGMEM = "[disabled]"; static const char msg_am01[] PROGMEM = "[standard]"; static const char msg_am02[] PROGMEM = "[inhibited]"; static const char msg_am03[] PROGMEM = "[radius]"; -static const char *const msg_am[] PROGMEM = { msg_am00, msg_am01, msg_am02, msg_am03}; +static const char *const msg_am[] PROGMEM = {msg_am00, msg_am01, msg_am02, msg_am03}; static const char msg_g20[] PROGMEM = "G20 - inches mode"; static const char msg_g21[] PROGMEM = "G21 - millimeter mode"; -static const char *const msg_unit[] PROGMEM = { msg_g20, msg_g21 }; +static const char *const msg_unit[] PROGMEM = {msg_g20, msg_g21}; static const char msg_stat0[] PROGMEM = "Initializing"; // combined state (stat) uses this array static const char msg_stat1[] PROGMEM = "Ready"; @@ -1307,9 +1301,11 @@ static const char msg_stat8[] PROGMEM = "Cycle"; static const char msg_stat9[] PROGMEM = "Homing"; static const char msg_stat10[] PROGMEM = "Jog"; static const char msg_stat11[] PROGMEM = "Shutdown"; -static const char *const msg_stat[] PROGMEM = { msg_stat0, msg_stat1, msg_stat2, msg_stat3, - msg_stat4, msg_stat5, msg_stat6, msg_stat7, - msg_stat8, msg_stat9, msg_stat10, msg_stat11 }; +static const char *const msg_stat[] PROGMEM = { + msg_stat0, msg_stat1, msg_stat2, msg_stat3, + msg_stat4, msg_stat5, msg_stat6, msg_stat7, + msg_stat8, msg_stat9, msg_stat10, msg_stat11 +}; static const char msg_macs0[] PROGMEM = "Initializing"; static const char msg_macs1[] PROGMEM = "Ready"; @@ -1318,20 +1314,22 @@ static const char msg_macs3[] PROGMEM = "Stop"; static const char msg_macs4[] PROGMEM = "End"; static const char msg_macs5[] PROGMEM = "Cycle"; static const char msg_macs6[] PROGMEM = "Shutdown"; -static const char *const msg_macs[] PROGMEM = { msg_macs0, msg_macs1, msg_macs2, msg_macs3, - msg_macs4, msg_macs5, msg_macs6 }; +static const char *const msg_macs[] PROGMEM = { + msg_macs0, msg_macs1, msg_macs2, msg_macs3, + msg_macs4, msg_macs5, msg_macs6 +}; static const char msg_cycs0[] PROGMEM = "Off"; static const char msg_cycs1[] PROGMEM = "Machining"; static const char msg_cycs2[] PROGMEM = "Probe"; static const char msg_cycs3[] PROGMEM = "Homing"; static const char msg_cycs4[] PROGMEM = "Jog"; -static const char *const msg_cycs[] PROGMEM = { msg_cycs0, msg_cycs1, msg_cycs2, msg_cycs3, msg_cycs4 }; +static const char *const msg_cycs[] PROGMEM = {msg_cycs0, msg_cycs1, msg_cycs2, msg_cycs3, msg_cycs4}; static const char msg_mots0[] PROGMEM = "Stop"; static const char msg_mots1[] PROGMEM = "Run"; static const char msg_mots2[] PROGMEM = "Hold"; -static const char *const msg_mots[] PROGMEM = { msg_mots0, msg_mots1, msg_mots2 }; +static const char *const msg_mots[] PROGMEM = {msg_mots0, msg_mots1, msg_mots2}; static const char msg_hold0[] PROGMEM = "Off"; static const char msg_hold1[] PROGMEM = "Sync"; @@ -1339,13 +1337,12 @@ static const char msg_hold2[] PROGMEM = "Plan"; static const char msg_hold3[] PROGMEM = "Decel"; static const char msg_hold4[] PROGMEM = "Hold"; static const char msg_hold5[] PROGMEM = "End Hold"; -static const char *const msg_hold[] PROGMEM = { msg_hold0, msg_hold1, msg_hold2, msg_hold3, - msg_hold4, msg_hold5 }; +static const char *const msg_hold[] PROGMEM = {msg_hold0, msg_hold1, msg_hold2, msg_hold3, msg_hold4, msg_hold5}; static const char msg_home0[] PROGMEM = "Not Homed"; static const char msg_home1[] PROGMEM = "Homed"; static const char msg_home2[] PROGMEM = "Homing"; -static const char *const msg_home[] PROGMEM = { msg_home0, msg_home1, msg_home2 }; +static const char *const msg_home[] PROGMEM = {msg_home0, msg_home1, msg_home2}; static const char msg_g53[] PROGMEM = "G53 - machine coordinate system"; static const char msg_g54[] PROGMEM = "G54 - coordinate system 1"; @@ -1354,33 +1351,33 @@ static const char msg_g56[] PROGMEM = "G56 - coordinate system 3"; static const char msg_g57[] PROGMEM = "G57 - coordinate system 4"; static const char msg_g58[] PROGMEM = "G58 - coordinate system 5"; static const char msg_g59[] PROGMEM = "G59 - coordinate system 6"; -static const char *const msg_coor[] PROGMEM = { msg_g53, msg_g54, msg_g55, msg_g56, msg_g57, msg_g58, msg_g59 }; +static const char *const msg_coor[] PROGMEM = {msg_g53, msg_g54, msg_g55, msg_g56, msg_g57, msg_g58, msg_g59}; static const char msg_g00[] PROGMEM = "G0 - linear traverse (seek)"; static const char msg_g01[] PROGMEM = "G1 - linear feed"; static const char msg_g02[] PROGMEM = "G2 - clockwise arc feed"; static const char msg_g03[] PROGMEM = "G3 - counter clockwise arc feed"; static const char msg_g80[] PROGMEM = "G80 - cancel motion mode (none active)"; -static const char *const msg_momo[] PROGMEM = { msg_g00, msg_g01, msg_g02, msg_g03, msg_g80 }; +static const char *const msg_momo[] PROGMEM = {msg_g00, msg_g01, msg_g02, msg_g03, msg_g80}; static const char msg_g17[] PROGMEM = "G17 - XY plane"; static const char msg_g18[] PROGMEM = "G18 - XZ plane"; static const char msg_g19[] PROGMEM = "G19 - YZ plane"; -static const char *const msg_plan[] PROGMEM = { msg_g17, msg_g18, msg_g19 }; +static const char *const msg_plan[] PROGMEM = {msg_g17, msg_g18, msg_g19}; static const char msg_g61[] PROGMEM = "G61 - exact path mode"; static const char msg_g6a[] PROGMEM = "G61.1 - exact stop mode"; static const char msg_g64[] PROGMEM = "G64 - continuous mode"; -static const char *const msg_path[] PROGMEM = { msg_g61, msg_g6a, msg_g64 }; +static const char *const msg_path[] PROGMEM = {msg_g61, msg_g6a, msg_g64}; static const char msg_g90[] PROGMEM = "G90 - absolute distance mode"; static const char msg_g91[] PROGMEM = "G91 - incremental distance mode"; -static const char *const msg_dist[] PROGMEM = { msg_g90, msg_g91 }; +static const char *const msg_dist[] PROGMEM = {msg_g90, msg_g91}; static const char msg_g93[] PROGMEM = "G93 - inverse time mode"; static const char msg_g94[] PROGMEM = "G94 - units-per-minute mode (i.e. feedrate mode)"; static const char msg_g95[] PROGMEM = "G95 - units-per-revolution mode"; -static const char *const msg_frmo[] PROGMEM = { msg_g93, msg_g94, msg_g95 }; +static const char *const msg_frmo[] PROGMEM = {msg_g93, msg_g94, msg_g95}; #else @@ -1402,12 +1399,7 @@ static const char *const msg_frmo[] PROGMEM = { msg_g93, msg_g94, msg_g95 }; #endif // __TEXT_MODE -/***** AXIS HELPERS ***************************************************************** - * cm_get_axis_char() - return ASCII char for axis given the axis number - * _get_axis() - return axis number or -1 if NA - * _get_axis_type() - return 0 -f axis is linear, 1 if rotary, -1 if NA - */ - +/// return ASCII char for axis given the axis number char_t cm_get_axis_char(const int8_t axis) { char_t axis_char[] = "XYZABC"; if ((axis < 0) || (axis > AXES)) return ' '; @@ -1415,14 +1407,15 @@ char_t cm_get_axis_char(const int8_t axis) { } +/// return axis number or -1 if NA static int8_t _get_axis(const index_t index) { char_t *ptr; char_t tmp[TOKEN_LEN+1]; char_t axes[] = {"xyzabc"}; - strncpy_P(tmp, cfgArray[index].token, TOKEN_LEN); // kind of a hack. Looks for an axis + strncpy_P(tmp, cfgArray[index].token, TOKEN_LEN); // kind of a hack. Looks for an axis if ((ptr = strchr(axes, tmp[0])) == 0) { // character in the 0 and 3 positions - if ((ptr = strchr(axes, tmp[3])) == 0) // to accommodate 'xam' and 'g54x' styles + if ((ptr = strchr(axes, tmp[3])) == 0) // to accommodate 'xam' and 'g54x' styles return -1; } @@ -1430,6 +1423,7 @@ static int8_t _get_axis(const index_t index) { } +/// return 0 -f axis is linear, 1 if rotary, -1 if NA static int8_t _get_axis_type(const index_t index) { int8_t axis = _get_axis(index); if (axis >= AXIS_A) return 1; @@ -1472,24 +1466,24 @@ static int8_t _get_axis_type(const index_t index) { stat_t _get_msg_helper(nvObj_t *nv, const char *const msg_array[], uint8_t value) { nv->value = (float)value; nv->valuetype = TYPE_INTEGER; - return(nv_copy_string(nv, (const char_t *)GET_TEXT_ITEM(msg_array, value))); + return nv_copy_string(nv, (const char_t *)GET_TEXT_ITEM(msg_array, value)); } -stat_t cm_get_stat(nvObj_t *nv) {return(_get_msg_helper(nv, msg_stat, cm_get_combined_state()));} -stat_t cm_get_macs(nvObj_t *nv) {return(_get_msg_helper(nv, msg_macs, cm_get_machine_state()));} -stat_t cm_get_cycs(nvObj_t *nv) {return(_get_msg_helper(nv, msg_cycs, cm_get_cycle_state()));} -stat_t cm_get_mots(nvObj_t *nv) {return(_get_msg_helper(nv, msg_mots, cm_get_motion_state()));} -stat_t cm_get_hold(nvObj_t *nv) {return(_get_msg_helper(nv, msg_hold, cm_get_hold_state()));} -stat_t cm_get_home(nvObj_t *nv) {return(_get_msg_helper(nv, msg_home, cm_get_homing_state()));} +stat_t cm_get_stat(nvObj_t *nv) {return _get_msg_helper(nv, msg_stat, cm_get_combined_state());} +stat_t cm_get_macs(nvObj_t *nv) {return _get_msg_helper(nv, msg_macs, cm_get_machine_state());} +stat_t cm_get_cycs(nvObj_t *nv) {return _get_msg_helper(nv, msg_cycs, cm_get_cycle_state());} +stat_t cm_get_mots(nvObj_t *nv) {return _get_msg_helper(nv, msg_mots, cm_get_motion_state());} +stat_t cm_get_hold(nvObj_t *nv) {return _get_msg_helper(nv, msg_hold, cm_get_hold_state());} +stat_t cm_get_home(nvObj_t *nv) {return _get_msg_helper(nv, msg_home, cm_get_homing_state());} -stat_t cm_get_unit(nvObj_t *nv) {return(_get_msg_helper(nv, msg_unit, cm_get_units_mode(ACTIVE_MODEL)));} -stat_t cm_get_coor(nvObj_t *nv) {return(_get_msg_helper(nv, msg_coor, cm_get_coord_system(ACTIVE_MODEL)));} -stat_t cm_get_momo(nvObj_t *nv) {return(_get_msg_helper(nv, msg_momo, cm_get_motion_mode(ACTIVE_MODEL)));} -stat_t cm_get_plan(nvObj_t *nv) {return(_get_msg_helper(nv, msg_plan, cm_get_select_plane(ACTIVE_MODEL)));} -stat_t cm_get_path(nvObj_t *nv) {return(_get_msg_helper(nv, msg_path, cm_get_path_control(ACTIVE_MODEL)));} -stat_t cm_get_dist(nvObj_t *nv) {return(_get_msg_helper(nv, msg_dist, cm_get_distance_mode(ACTIVE_MODEL)));} -stat_t cm_get_frmo(nvObj_t *nv) {return(_get_msg_helper(nv, msg_frmo, cm_get_feed_rate_mode(ACTIVE_MODEL)));} +stat_t cm_get_unit(nvObj_t *nv) {return _get_msg_helper(nv, msg_unit, cm_get_units_mode(ACTIVE_MODEL));} +stat_t cm_get_coor(nvObj_t *nv) {return _get_msg_helper(nv, msg_coor, cm_get_coord_system(ACTIVE_MODEL));} +stat_t cm_get_momo(nvObj_t *nv) {return _get_msg_helper(nv, msg_momo, cm_get_motion_mode(ACTIVE_MODEL));} +stat_t cm_get_plan(nvObj_t *nv) {return _get_msg_helper(nv, msg_plan, cm_get_select_plane(ACTIVE_MODEL));} +stat_t cm_get_path(nvObj_t *nv) {return _get_msg_helper(nv, msg_path, cm_get_path_control(ACTIVE_MODEL));} +stat_t cm_get_dist(nvObj_t *nv) {return _get_msg_helper(nv, msg_dist, cm_get_distance_mode(ACTIVE_MODEL));} +stat_t cm_get_frmo(nvObj_t *nv) {return _get_msg_helper(nv, msg_frmo, cm_get_feed_rate_mode(ACTIVE_MODEL));} stat_t cm_get_toolv(nvObj_t *nv) { @@ -1567,7 +1561,7 @@ stat_t cm_get_ofs(nvObj_t *nv) { */ stat_t cm_get_am(nvObj_t *nv) { get_ui8(nv); - return(_get_msg_helper(nv, msg_am, nv->value)); + return _get_msg_helper(nv, msg_am, nv->value); } @@ -1577,7 +1571,7 @@ stat_t cm_set_am(nvObj_t *nv) { // axis mode } else if (nv->value > AXIS_MODE_MAX_ROTARY) return STAT_INPUT_EXCEEDS_MAX_VALUE; set_ui8(nv); - return(STAT_OK); + return STAT_OK; } /**** Jerk functions @@ -1612,14 +1606,14 @@ stat_t cm_set_xjm(nvObj_t *nv) { if (nv->value > JERK_MULTIPLIER) nv->value /= JERK_MULTIPLIER; set_flu(nv); cm_set_axis_jerk(_get_axis(nv->index), nv->value); - return(STAT_OK); + return STAT_OK; } stat_t cm_set_xjh(nvObj_t *nv) { if (nv->value > JERK_MULTIPLIER) nv->value /= JERK_MULTIPLIER; set_flu(nv); - return(STAT_OK); + return STAT_OK; } /* @@ -1702,15 +1696,9 @@ stat_t cm_run_joga(nvObj_t *nv) { return STAT_OK; } -/*********************************************************************************** - * TEXT MODE SUPPORT - * Functions to print variables from the cfgArray table - ***********************************************************************************/ - #ifdef __TEXT_MODE -/* model state print functions */ - +// model state print functions const char fmt_vel[] PROGMEM = "Velocity:%17.3f%s/min\n"; const char fmt_feed[] PROGMEM = "Feed rate:%16.3f%s/min\n"; const char fmt_line[] PROGMEM = "Line number:%10.0f\n"; @@ -1779,32 +1767,7 @@ void cm_print_ml(nvObj_t *nv) {text_print_flt_units(nv, fmt_ml, GET_UNITS(ACTIVE void cm_print_ma(nvObj_t *nv) {text_print_flt_units(nv, fmt_ma, GET_UNITS(ACTIVE_MODEL));} void cm_print_ms(nvObj_t *nv) {text_print_flt_units(nv, fmt_ms, GET_UNITS(ACTIVE_MODEL));} -/* - * axis print functions - * - * _print_axis_ui8() - helper to print an integer value with no units - * _print_axis_flt() - helper to print a floating point linear value in prevailing units - * _print_pos_helper() - * - * cm_print_am() - * cm_print_fr() - * cm_print_vm() - * cm_print_tm() - * cm_print_tn() - * cm_print_jm() - * cm_print_jh() - * cm_print_jd() - * cm_print_ra() - * cm_print_sn() - * cm_print_sx() - * cm_print_lv() - * cm_print_lb() - * cm_print_zb() - * - * cm_print_pos() - print position with unit displays for MM or Inches - * cm_print_mpo() - print position with fixed unit display - always in Degrees or MM - */ - +// axis print functions static const char fmt_Xam[] PROGMEM = "[%s%s] %s axis mode%18d %s\n"; static const char fmt_Xfr[] PROGMEM = "[%s%s] %s feedrate maximum%11.0f%s/min\n"; static const char fmt_Xvm[] PROGMEM = "[%s%s] %s velocity maximum%11.0f%s/min\n"; @@ -1824,11 +1787,13 @@ static const char fmt_cofs[] PROGMEM = "[%s%s] %s %s offset%20.3f%s\n"; static const char fmt_cpos[] PROGMEM = "[%s%s] %s %s position%18.3f%s\n"; +/// helper to print an integer value with no units static void _print_axis_ui8(nvObj_t *nv, const char *format) { fprintf_P(stderr, format, nv->group, nv->token, nv->group, (uint8_t)nv->value); } +/// helper to print a floating point linear value in prevailing units static void _print_axis_flt(nvObj_t *nv, const char *format) { char *units; if (_get_axis_type(nv->index) == 0) // linear @@ -1849,6 +1814,7 @@ static void _print_axis_coord_flt(nvObj_t *nv, const char *format) { } +/// print position with unit displays for MM or Inches static void _print_pos(nvObj_t *nv, const char *format, uint8_t units) { char axes[] = {"XYZABC"}; uint8_t axis = _get_axis(nv->index); @@ -1882,6 +1848,7 @@ void cm_print_cofs(nvObj_t *nv) {_print_axis_coord_flt(nv, fmt_cofs);} void cm_print_cpos(nvObj_t *nv) {_print_axis_coord_flt(nv, fmt_cpos);} void cm_print_pos(nvObj_t *nv) {_print_pos(nv, fmt_pos, cm_get_units_mode(MODEL));} +/// print position with fixed unit display - always in Degrees or MM void cm_print_mpo(nvObj_t *nv) {_print_pos(nv, fmt_mpo, MILLIMETERS);} void cm_print_ofs(nvObj_t *nv) {_print_pos(nv, fmt_ofs, MILLIMETERS);} diff --git a/src/canonical_machine.h b/src/canonical_machine.h index 529a6cb..ff076c0 100644 --- a/src/canonical_machine.h +++ b/src/canonical_machine.h @@ -33,10 +33,8 @@ #include "config.h" -/* Defines, Macros, and Assorted Parameters */ - -#define MODEL (GCodeState_t *)&cm.gm // absolute pointer from canonical machine gm model -#define PLANNER (GCodeState_t *)&bf->gm // relative to buffer *bf is currently pointing to +#define MODEL (GCodeState_t *)&cm.gm // absolute pointer from canonical machine gm model +#define PLANNER (GCodeState_t *)&bf->gm // relative to buffer *bf is currently pointing to #define RUNTIME (GCodeState_t *)&mr.gm // absolute pointer from runtime mm struct #define ACTIVE_MODEL cm.am // active model pointer is maintained by state management @@ -45,6 +43,7 @@ #define JOGGING_START_VELOCITY ((float)10.0) #define DISABLE_SOFT_LIMIT (-1000000) + /***************************************************************************** * GCODE MODEL - The following GCodeModel/GCodeInput structs are used: * @@ -60,7 +59,7 @@ * machine and do not need to be passed further down. * * - gn is used by the gcode interpreter and is re-initialized for each - * gcode block.It accepts data in the new gcode block in the formats + * gcode block.It accepts data in the new gcode block in the formats * present in the block (pre-normalized forms). During initialization * some state elements are necessarily restored from gm. * @@ -75,197 +74,192 @@ * G92 offsets. cfg has the power-on / reset gcode default values, but gm has * the operating state for the values (which may have changed). */ -typedef struct GCodeState { // Gcode model state - used by model, planning and runtime - uint32_t linenum; // Gcode block line number - uint8_t motion_mode; // Group1: G0, G1, G2, G3, G38.2, G80, G81, - // G82, G83 G84, G85, G86, G87, G88, G89 - float target[AXES]; // XYZABC where the move should go - float work_offset[AXES]; // offset from the work coordinate system (for reporting only) - - float move_time; // optimal time for move given axis constraints - float minimum_time; // minimum time possible for move given axis constraints - float feed_rate; // F - normalized to millimeters/minute or in inverse time mode - - float spindle_speed; // in RPM - float parameter; // P - parameter used for dwell time in seconds, G10 coord select... - - 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 absolute_override; // G53 TRUE = move using machine coordinates - this block only (G53) - 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; // G91.1 0=use absolute coords(G90), 1=incremental movement - uint8_t tool; // M6 tool change - moves "tool_select" to "tool" - uint8_t tool_select; // T value - T sets this value - 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_mode; // 0=OFF (M5), 1=CW (M3), 2=CCW (M4) - +typedef struct GCodeState { // Gcode model state - used by model, planning and runtime + uint32_t linenum; // Gcode block line number + uint8_t motion_mode; // Group1: G0, G1, G2, G3, G38.2, G80, G81, + // G82, G83 G84, G85, G86, G87, G88, G89 + float target[AXES]; // XYZABC where the move should go + float work_offset[AXES]; // offset from the work coordinate system (for reporting only) + + float move_time; // optimal time for move given axis constraints + float minimum_time; // minimum time possible for move given axis constraints + float feed_rate; // F - normalized to millimeters/minute or in inverse time mode + + float spindle_speed; // in RPM + float parameter; // P - parameter used for dwell time in seconds, G10 coord select... + + 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 absolute_override; // G53 TRUE = move using machine coordinates - this block only (G53) + 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; // G91.1 0=use absolute coords(G90), 1=incremental movement + uint8_t tool; // M6 tool change - moves "tool_select" to "tool" + uint8_t tool_select; // T value - T sets this value + 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_mode; // 0=OFF (M5), 1=CW (M3), 2=CCW (M4) } GCodeState_t; -typedef struct GCodeStateExtended { // Gcode dynamic state extensions - used by model and arcs - uint16_t magic_start; // magic number to test memory integrity - uint8_t next_action; // handles G modal group 1 moves & non-modals - uint8_t program_flow; // used only by the gcode_parser - float position[AXES]; // XYZABC model position (Note: not used in gn or gf) - float origin_offset[AXES]; // XYZABC G92 offsets (Note: not used in gn or gf) - float g28_position[AXES]; // XYZABC stored machine position for G28 - float g30_position[AXES]; // XYZABC stored machine position for G30 +typedef struct GCodeStateExtended { // Gcode dynamic state extensions - used by model and arcs + uint16_t magic_start; // magic number to test memory integrity + uint8_t next_action; // handles G modal group 1 moves & non-modals + uint8_t program_flow; // used only by the gcode_parser - float feed_rate_override_factor; // 1.0000 x F feed rate. Go up or down from there - float traverse_override_factor; // 1.0000 x traverse rate. Go down from there - uint8_t feed_rate_override_enable; // TRUE = overrides enabled (M48), F=(M49) - uint8_t traverse_override_enable; // TRUE = traverse override enabled - uint8_t l_word; // L word - used by G10s + float position[AXES]; // XYZABC model position (Note: not used in gn or gf) + float origin_offset[AXES]; // XYZABC G92 offsets (Note: not used in gn or gf) + float g28_position[AXES]; // XYZABC stored machine position for G28 + float g30_position[AXES]; // XYZABC stored machine position for G30 - uint8_t origin_offset_enable; // G92 offsets enabled/disabled. 0=disabled, 1=enabled - uint8_t block_delete_switch; // set true to enable block deletes (true is default) + float feed_rate_override_factor; // 1.0000 x F feed rate. Go up or down from there + float traverse_override_factor; // 1.0000 x traverse rate. Go down from there + uint8_t feed_rate_override_enable; // TRUE = overrides enabled (M48), F=(M49) + uint8_t traverse_override_enable; // TRUE = traverse override enabled + uint8_t l_word; // L word - used by G10s - float spindle_override_factor; // 1.0000 x S spindle speed. Go up or down from there - uint8_t spindle_override_enable; // TRUE = override enabled + uint8_t origin_offset_enable; // G92 offsets enabled/disabled. 0=disabled, 1=enabled + uint8_t block_delete_switch; // set true to enable block deletes (true is default) -// unimplemented gcode parameters -// float cutter_radius; // D - cutter radius compensation (0 is off) -// float cutter_length; // H - cutter length compensation (0 is off) + float spindle_override_factor; // 1.0000 x S spindle speed. Go up or down from there + uint8_t spindle_override_enable; // TRUE = override enabled - uint16_t magic_end; + // unimplemented gcode parameters + // float cutter_radius; // D - cutter radius compensation (0 is off) + // float cutter_length; // H - cutter length compensation (0 is off) + uint16_t magic_end; } GCodeStateX_t; -typedef struct GCodeInput { // Gcode model inputs - meaning depends on context - uint8_t next_action; // handles G modal group 1 moves & non-modals - uint8_t 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 or autoincrement in the model - - float target[AXES]; // XYZABC where the move should go - - float feed_rate; // F - normalized to millimeters/minute - float feed_rate_override_factor; // 1.0000 x F feed rate. Go up or down from there - float traverse_override_factor; // 1.0000 x traverse rate. Go down from there - uint8_t feed_rate_mode; // See cmFeedRateMode for settings - uint8_t feed_rate_override_enable; // TRUE = overrides enabled (M48), F=(M49) - uint8_t traverse_override_enable; // TRUE = traverse override enabled - uint8_t override_enables; // enables for feed and spoindle (GN/GF only) - uint8_t l_word; // L word - used by G10s - - 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 absolute_override; // G53 TRUE = move using machine coordinates - this block only (G53) - uint8_t origin_offset_mode; // G92...TRUE=in origin offset mode - 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; // G91.1 0=use absolute coords(G90), 1=incremental movement - - 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_mode; // 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 - - 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 - -// unimplemented gcode parameters -// float cutter_radius; // D - cutter radius compensation (0 is off) -// float cutter_length; // H - cutter length compensation (0 is off) +typedef struct GCodeInput { // Gcode model inputs - meaning depends on context + uint8_t next_action; // handles G modal group 1 moves & non-modals + uint8_t 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 or autoincrement in the model + + float target[AXES]; // XYZABC where the move should go + + float feed_rate; // F - normalized to millimeters/minute + float feed_rate_override_factor; // 1.0000 x F feed rate. Go up or down from there + float traverse_override_factor; // 1.0000 x traverse rate. Go down from there + uint8_t feed_rate_mode; // See cmFeedRateMode for settings + uint8_t feed_rate_override_enable; // TRUE = overrides enabled (M48), F=(M49) + uint8_t traverse_override_enable; // TRUE = traverse override enabled + uint8_t override_enables; // enables for feed and spoindle (GN/GF only) + uint8_t l_word; // L word - used by G10s + + 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 absolute_override; // G53 TRUE = move using machine coordinates - this block only (G53) + uint8_t origin_offset_mode; // G92...TRUE=in origin offset mode + 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; // G91.1 0=use absolute coords(G90), 1=incremental movement + + 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_mode; // 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 + + 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 + + // unimplemented gcode parameters + // float cutter_radius; // D - cutter radius compensation (0 is off) + // float cutter_length; // H - cutter length compensation (0 is off) } GCodeInput_t; -/***************************************************************************** - * CANONICAL MACHINE STRUCTURES - */ typedef struct cmAxis { - uint8_t axis_mode; // see tgAxisMode in gcode.h - float feedrate_max; // max velocity in mm/min or deg/min - float velocity_max; // max velocity in mm/min or deg/min - float travel_max; // max work envelope for soft limits - float travel_min; // min work envelope for soft limits - float jerk_max; // max jerk (Jm) in mm/min^3 divided by 1 million - float jerk_homing; // homing jerk (Jh) in mm/min^3 divided by 1 million - float recip_jerk; // stored reciprocal of current jerk value - has the million in it - float junction_dev; // aka cornering delta - float radius; // radius in mm for rotary axis modes - float search_velocity; // homing search velocity - float latch_velocity; // homing latch velocity - float latch_backoff; // backoff from switches prior to homing latch movement - float zero_backoff; // backoff from switches for machine zero + uint8_t axis_mode; // see tgAxisMode in gcode.h + float feedrate_max; // max velocity in mm/min or deg/min + float velocity_max; // max velocity in mm/min or deg/min + float travel_max; // max work envelope for soft limits + float travel_min; // min work envelope for soft limits + float jerk_max; // max jerk (Jm) in mm/min^3 divided by 1 million + float jerk_homing; // homing jerk (Jh) in mm/min^3 divided by 1 million + float recip_jerk; // stored reciprocal of current jerk value - has the million in it + float junction_dev; // aka cornering delta + float radius; // radius in mm for rotary axis modes + float search_velocity; // homing search velocity + float latch_velocity; // homing latch velocity + float latch_backoff; // backoff from switches prior to homing latch movement + float zero_backoff; // backoff from switches for machine zero } cfgAxis_t; -typedef struct cmSingleton { // struct to manage cm globals and cycles - magic_t magic_start; // magic number to test memory integrity - - /**** Config variables (PUBLIC) ****/ - - // system group settings - float junction_acceleration; // centripetal acceleration max for cornering - float chordal_tolerance; // arc chordal accuracy setting in mm - uint8_t soft_limit_enable; - - // hidden system settings - float min_segment_len; // line drawing resolution in mm - float arc_segment_len; // arc drawing resolution in mm - float estd_segment_usec; // approximate segment time in microseconds - - // gcode power-on default settings - defaults are not the same as the gm state - uint8_t coord_system; // G10 active coordinate system default - uint8_t select_plane; // G17,G18,G19 reset default - uint8_t units_mode; // G20,G21 reset default - uint8_t path_control; // G61,G61.1,G64 reset default - uint8_t distance_mode; // G90,G91 reset default - - // coordinate systems and offsets - float offset[COORDS+1][AXES]; // persistent coordinate offsets: absolute (G53) + G54,G55,G56,G57,G58,G59 - - // settings for axes X,Y,Z,A B,C - cfgAxis_t a[AXES]; - - /**** Runtime variables (PRIVATE) ****/ - - uint8_t combined_state; // stat: combination of states for display purposes - uint8_t machine_state; // macs: machine/cycle/motion is the actual machine state - uint8_t cycle_state; // cycs - uint8_t motion_state; // momo - uint8_t hold_state; // hold: feedhold sub-state machine - uint8_t homing_state; // home: homing cycle sub-state machine - uint8_t homed[AXES]; // individual axis homing flags - - uint8_t probe_state; // 1==success, 0==failed - float probe_results[AXES]; // probing results - - uint8_t g28_flag; // true = complete a G28 move - uint8_t g30_flag; // true = complete a G30 move - uint8_t deferred_write_flag; // G10 data has changed (e.g. offsets) - flag to persist them - uint8_t feedhold_requested; // feedhold character has been received - uint8_t queue_flush_requested; // queue flush character has been received - uint8_t cycle_start_requested; // cycle start character has been received (flag to end feedhold) - float jogging_dest; // jogging direction as a relative move from current position - struct GCodeState *am; // active Gcode model is maintained by state management - - /**** Model states ****/ - GCodeState_t gm; // core gcode model state - GCodeStateX_t gmx; // extended gcode model state - GCodeInput_t gn; // gcode input values - transient - GCodeInput_t gf; // gcode input flags - transient - - magic_t magic_end; + +typedef struct cmSingleton { // struct to manage cm globals and cycles + magic_t magic_start; // magic number to test memory integrity + + // Public + // system group settings + float junction_acceleration; // centripetal acceleration max for cornering + float chordal_tolerance; // arc chordal accuracy setting in mm + uint8_t soft_limit_enable; + + // hidden system settings + float min_segment_len; // line drawing resolution in mm + float arc_segment_len; // arc drawing resolution in mm + float estd_segment_usec; // approximate segment time in microseconds + + // gcode power-on default settings - defaults are not the same as the gm state + uint8_t coord_system; // G10 active coordinate system default + uint8_t select_plane; // G17,G18,G19 reset default + uint8_t units_mode; // G20,G21 reset default + uint8_t path_control; // G61,G61.1,G64 reset default + uint8_t distance_mode; // G90,G91 reset default + + // coordinate systems and offsets + float offset[COORDS+1][AXES]; // persistent coordinate offsets: absolute (G53) + G54,G55,G56,G57,G58,G59 + + // settings for axes X,Y,Z,A B,C + cfgAxis_t a[AXES]; + + // Private + uint8_t combined_state; // stat: combination of states for display purposes + uint8_t machine_state; // macs: machine/cycle/motion is the actual machine state + uint8_t cycle_state; // cycs + uint8_t motion_state; // momo + uint8_t hold_state; // hold: feedhold sub-state machine + uint8_t homing_state; // home: homing cycle sub-state machine + uint8_t homed[AXES]; // individual axis homing flags + + uint8_t probe_state; // 1==success, 0==failed + float probe_results[AXES]; // probing results + + uint8_t g28_flag; // true = complete a G28 move + uint8_t g30_flag; // true = complete a G30 move + uint8_t deferred_write_flag; // G10 data has changed (e.g. offsets) - flag to persist them + uint8_t feedhold_requested; // feedhold character has been received + uint8_t queue_flush_requested; // queue flush character has been received + uint8_t cycle_start_requested; // cycle start character has been received (flag to end feedhold) + float jogging_dest; // jogging direction as a relative move from current position + struct GCodeState *am; // active Gcode model is maintained by state management + + // Model states + GCodeState_t gm; // core gcode model state + GCodeStateX_t gmx; // extended gcode model state + GCodeInput_t gn; // gcode input values - transient + GCodeInput_t gf; // gcode input flags - transient + + magic_t magic_end; } cmSingleton_t; -/**** Externs - See canonical_machine.c for allocation ****/ -extern cmSingleton_t cm; // canonical machine controller singleton +extern cmSingleton_t cm; // canonical machine controller singleton + /***************************************************************************** * MACHINE STATE MODEL @@ -277,236 +271,251 @@ extern cmSingleton_t cm; // canonical machine controller singleto */ /* Allowed states and combined states * - * MACHINE STATE CYCLE STATE MOTION_STATE COMBINED_STATE (FYI) - * ------------- ------------ ------------- -------------------- - * MACHINE_UNINIT na na (U) - * MACHINE_READY CYCLE_OFF MOTION_STOP (ROS) RESET-OFF-STOP - * MACHINE_PROG_STOP CYCLE_OFF MOTION_STOP (SOS) STOP-OFF-STOP - * MACHINE_PROG_END CYCLE_OFF MOTION_STOP (EOS) END-OFF-STOP + * MACHINE STATE CYCLE STATE MOTION_STATE COMBINED_STATE (FYI) + * ------------- ------------ ------------- -------------------- + * MACHINE_UNINIT na na (U) + * MACHINE_READY CYCLE_OFF MOTION_STOP (ROS) RESET-OFF-STOP + * MACHINE_PROG_STOP CYCLE_OFF MOTION_STOP (SOS) STOP-OFF-STOP + * MACHINE_PROG_END CYCLE_OFF MOTION_STOP (EOS) END-OFF-STOP * - * MACHINE_CYCLE CYCLE_STARTED MOTION_STOP (CSS) CYCLE-START-STOP - * MACHINE_CYCLE CYCLE_STARTED MOTION_RUN (CSR) CYCLE-START-RUN - * MACHINE_CYCLE CYCLE_STARTED MOTION_HOLD (CSH) CYCLE-START-HOLD - * MACHINE_CYCLE CYCLE_STARTED MOTION_END_HOLD (CSE) CYCLE-START-END_HOLD + * MACHINE_CYCLE CYCLE_STARTED MOTION_STOP (CSS) CYCLE-START-STOP + * MACHINE_CYCLE CYCLE_STARTED MOTION_RUN (CSR) CYCLE-START-RUN + * MACHINE_CYCLE CYCLE_STARTED MOTION_HOLD (CSH) CYCLE-START-HOLD + * MACHINE_CYCLE CYCLE_STARTED MOTION_END_HOLD (CSE) CYCLE-START-END_HOLD * - * MACHINE_CYCLE CYCLE_HOMING MOTION_STOP (CHS) CYCLE-HOMING-STOP + * MACHINE_CYCLE CYCLE_HOMING MOTION_STOP (CHS) CYCLE-HOMING-STOP * MACHINE_CYCLE CYCLE_HOMING MOTION_RUN (CHR) CYCLE-HOMING-RUN - * MACHINE_CYCLE CYCLE_HOMING MOTION_HOLD (CHH) CYCLE-HOMING-HOLD - * MACHINE_CYCLE CYCLE_HOMING MOTION_END_HOLD (CHE) CYCLE-HOMING-END_HOLD + * MACHINE_CYCLE CYCLE_HOMING MOTION_HOLD (CHH) CYCLE-HOMING-HOLD + * MACHINE_CYCLE CYCLE_HOMING MOTION_END_HOLD (CHE) CYCLE-HOMING-END_HOLD */ // *** Note: check config printout strings align with all the state variables // ### LAYER 8 CRITICAL REGION ### // ### DO NOT CHANGE THESE ENUMERATIONS WITHOUT COMMUNITY INPUT ### -enum cmCombinedState { // check alignment with messages in config.c / msg_stat strings - COMBINED_INITIALIZING = 0, // [0] machine is initializing - COMBINED_READY, // [1] machine is ready for use. Also used to force STOP state for null moves - COMBINED_ALARM, // [2] machine in soft alarm state - COMBINED_PROGRAM_STOP, // [3] program stop or no more blocks - COMBINED_PROGRAM_END, // [4] program end - COMBINED_RUN, // [5] motion is running - COMBINED_HOLD, // [6] motion is holding - COMBINED_PROBE, // [7] probe cycle active - COMBINED_CYCLE, // [8] machine is running (cycling) - COMBINED_HOMING, // [9] homing is treated as a cycle - COMBINED_JOG, // [10] jogging is treated as a cycle - COMBINED_SHUTDOWN, // [11] machine in hard alarm state (shutdown) +enum cmCombinedState { // check alignment with messages in config.c / msg_stat strings + COMBINED_INITIALIZING = 0, // [0] machine is initializing + COMBINED_READY, // [1] machine is ready for use. Also used to force STOP state for null moves + COMBINED_ALARM, // [2] machine in soft alarm state + COMBINED_PROGRAM_STOP, // [3] program stop or no more blocks + COMBINED_PROGRAM_END, // [4] program end + COMBINED_RUN, // [5] motion is running + COMBINED_HOLD, // [6] motion is holding + COMBINED_PROBE, // [7] probe cycle active + COMBINED_CYCLE, // [8] machine is running (cycling) + COMBINED_HOMING, // [9] homing is treated as a cycle + COMBINED_JOG, // [10] jogging is treated as a cycle + COMBINED_SHUTDOWN, // [11] machine in hard alarm state (shutdown) }; //### END CRITICAL REGION ### + enum cmMachineState { - MACHINE_INITIALIZING = 0, // machine is initializing - MACHINE_READY, // machine is ready for use - MACHINE_ALARM, // machine in soft alarm state - MACHINE_PROGRAM_STOP, // program stop or no more blocks - MACHINE_PROGRAM_END, // program end - MACHINE_CYCLE, // machine is running (cycling) - MACHINE_SHUTDOWN, // machine in hard alarm state (shutdown) + MACHINE_INITIALIZING = 0, // machine is initializing + MACHINE_READY, // machine is ready for use + MACHINE_ALARM, // machine in soft alarm state + MACHINE_PROGRAM_STOP, // program stop or no more blocks + MACHINE_PROGRAM_END, // program end + MACHINE_CYCLE, // machine is running (cycling) + MACHINE_SHUTDOWN, // machine in hard alarm state (shutdown) }; + enum cmCycleState { - CYCLE_OFF = 0, // machine is idle - CYCLE_MACHINING, // in normal machining cycle - CYCLE_PROBE, // in probe cycle - CYCLE_HOMING, // homing is treated as a specialized cycle - CYCLE_JOG // jogging is treated as a specialized cycle + CYCLE_OFF = 0, // machine is idle + CYCLE_MACHINING, // in normal machining cycle + CYCLE_PROBE, // in probe cycle + CYCLE_HOMING, // homing is treated as a specialized cycle + CYCLE_JOG // jogging is treated as a specialized cycle }; + enum cmMotionState { - MOTION_STOP = 0, // motion has stopped - MOTION_RUN, // machine is in motion - MOTION_HOLD // feedhold in progress + MOTION_STOP = 0, // motion has stopped + MOTION_RUN, // machine is in motion + MOTION_HOLD // feedhold in progress }; -enum cmFeedholdState { // feedhold_state machine - FEEDHOLD_OFF = 0, // no feedhold in effect - FEEDHOLD_SYNC, // start hold - sync to latest aline segment - FEEDHOLD_PLAN, // replan blocks for feedhold - FEEDHOLD_DECEL, // decelerate to hold point - FEEDHOLD_HOLD, // holding - FEEDHOLD_END_HOLD // end hold (transient state to OFF) + +enum cmFeedholdState { // feedhold_state machine + FEEDHOLD_OFF = 0, // no feedhold in effect + FEEDHOLD_SYNC, // start hold - sync to latest aline segment + FEEDHOLD_PLAN, // replan blocks for feedhold + FEEDHOLD_DECEL, // decelerate to hold point + FEEDHOLD_HOLD, // holding + FEEDHOLD_END_HOLD // end hold (transient state to OFF) }; + enum cmHomingState { // applies to cm.homing_state - HOMING_NOT_HOMED = 0, // machine is not homed (0=false) - HOMING_HOMED = 1, // machine is homed (1=true) - HOMING_WAITING // machine waiting to be homed + HOMING_NOT_HOMED = 0, // machine is not homed (0=false) + HOMING_HOMED = 1, // machine is homed (1=true) + HOMING_WAITING // machine waiting to be homed }; -enum cmProbeState { // applies to cm.probe_state - PROBE_FAILED = 0, // probe reached endpoint without triggering - PROBE_SUCCEEDED = 1, // probe was triggered, cm.probe_results has position - PROBE_WAITING // probe is waiting to be started + +enum cmProbeState { // applies to cm.probe_state + PROBE_FAILED = 0, // probe reached endpoint without triggering + PROBE_SUCCEEDED = 1, // probe was triggered, cm.probe_results has position + PROBE_WAITING // probe is waiting to be started }; + /* The difference between NextAction and MotionMode is that NextAction is * used by the current block, and may carry non-modal commands, whereas * MotionMode persists across blocks (as G modal group 1) */ - -enum cmNextAction { // these are in order to optimized CASE statement - NEXT_ACTION_DEFAULT = 0, // Must be zero (invokes motion modes) - NEXT_ACTION_SEARCH_HOME, // G28.2 homing cycle - NEXT_ACTION_SET_ABSOLUTE_ORIGIN, // G28.3 origin set - NEXT_ACTION_HOMING_NO_SET, // G28.4 homing cycle with no coordinate setting - NEXT_ACTION_SET_G28_POSITION, // G28.1 set position in abs coordinates - NEXT_ACTION_GOTO_G28_POSITION, // G28 go to machine position - NEXT_ACTION_SET_G30_POSITION, // G30.1 - NEXT_ACTION_GOTO_G30_POSITION, // G30 - NEXT_ACTION_SET_COORD_DATA, // G10 - NEXT_ACTION_SET_ORIGIN_OFFSETS, // G92 - NEXT_ACTION_RESET_ORIGIN_OFFSETS, // G92.1 - NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS, // G92.2 - NEXT_ACTION_RESUME_ORIGIN_OFFSETS, // G92.3 - NEXT_ACTION_DWELL, // G4 - NEXT_ACTION_STRAIGHT_PROBE // G38.2 +enum cmNextAction { // these are in order to optimized CASE statement + NEXT_ACTION_DEFAULT = 0, // Must be zero (invokes motion modes) + NEXT_ACTION_SEARCH_HOME, // G28.2 homing cycle + NEXT_ACTION_SET_ABSOLUTE_ORIGIN, // G28.3 origin set + NEXT_ACTION_HOMING_NO_SET, // G28.4 homing cycle with no coordinate setting + NEXT_ACTION_SET_G28_POSITION, // G28.1 set position in abs coordinates + NEXT_ACTION_GOTO_G28_POSITION, // G28 go to machine position + NEXT_ACTION_SET_G30_POSITION, // G30.1 + NEXT_ACTION_GOTO_G30_POSITION, // G30 + NEXT_ACTION_SET_COORD_DATA, // G10 + NEXT_ACTION_SET_ORIGIN_OFFSETS, // G92 + NEXT_ACTION_RESET_ORIGIN_OFFSETS, // G92.1 + NEXT_ACTION_SUSPEND_ORIGIN_OFFSETS, // G92.2 + NEXT_ACTION_RESUME_ORIGIN_OFFSETS, // G92.3 + NEXT_ACTION_DWELL, // G4 + NEXT_ACTION_STRAIGHT_PROBE // G38.2 }; -enum cmMotionMode { // G Modal Group 1 - MOTION_MODE_STRAIGHT_TRAVERSE=0, // G0 - straight traverse - MOTION_MODE_STRAIGHT_FEED, // G1 - straight feed - MOTION_MODE_CW_ARC, // G2 - clockwise arc feed - MOTION_MODE_CCW_ARC, // G3 - counter-clockwise arc feed - MOTION_MODE_CANCEL_MOTION_MODE, // G80 - MOTION_MODE_STRAIGHT_PROBE, // G38.2 - MOTION_MODE_CANNED_CYCLE_81, // G81 - drilling - MOTION_MODE_CANNED_CYCLE_82, // G82 - drilling with dwell - MOTION_MODE_CANNED_CYCLE_83, // G83 - peck drilling - MOTION_MODE_CANNED_CYCLE_84, // G84 - right hand tapping - MOTION_MODE_CANNED_CYCLE_85, // G85 - boring, no dwell, feed out - MOTION_MODE_CANNED_CYCLE_86, // G86 - boring, spindle stop, rapid out - MOTION_MODE_CANNED_CYCLE_87, // G87 - back boring - MOTION_MODE_CANNED_CYCLE_88, // G88 - boring, spindle stop, manual out - MOTION_MODE_CANNED_CYCLE_89 // G89 - boring, dwell, feed out + +enum cmMotionMode { // G Modal Group 1 + MOTION_MODE_STRAIGHT_TRAVERSE = 0, // G0 - straight traverse + MOTION_MODE_STRAIGHT_FEED, // G1 - straight feed + MOTION_MODE_CW_ARC, // G2 - clockwise arc feed + MOTION_MODE_CCW_ARC, // G3 - counter-clockwise arc feed + MOTION_MODE_CANCEL_MOTION_MODE, // G80 + MOTION_MODE_STRAIGHT_PROBE, // G38.2 + MOTION_MODE_CANNED_CYCLE_81, // G81 - drilling + MOTION_MODE_CANNED_CYCLE_82, // G82 - drilling with dwell + MOTION_MODE_CANNED_CYCLE_83, // G83 - peck drilling + MOTION_MODE_CANNED_CYCLE_84, // G84 - right hand tapping + MOTION_MODE_CANNED_CYCLE_85, // G85 - boring, no dwell, feed out + MOTION_MODE_CANNED_CYCLE_86, // G86 - boring, spindle stop, rapid out + MOTION_MODE_CANNED_CYCLE_87, // G87 - back boring + MOTION_MODE_CANNED_CYCLE_88, // G88 - boring, spindle stop, manual out + MOTION_MODE_CANNED_CYCLE_89 // G89 - boring, dwell, feed out }; -enum cmModalGroup { // Used for detecting gcode errors. See NIST section 3.4 - MODAL_GROUP_G0 = 0, // {G10,G28,G28.1,G92} non-modal axis commands (note 1) - MODAL_GROUP_G1, // {G0,G1,G2,G3,G80} motion - MODAL_GROUP_G2, // {G17,G18,G19} plane selection - MODAL_GROUP_G3, // {G90,G91} distance mode - MODAL_GROUP_G5, // {G93,G94} feed rate mode - MODAL_GROUP_G6, // {G20,G21} units - MODAL_GROUP_G7, // {G40,G41,G42} cutter radius compensation - MODAL_GROUP_G8, // {G43,G49} tool length offset - MODAL_GROUP_G9, // {G98,G99} return mode in canned cycles - MODAL_GROUP_G12, // {G54,G55,G56,G57,G58,G59} coordinate system selection - MODAL_GROUP_G13, // {G61,G61.1,G64} path control mode - MODAL_GROUP_M4, // {M0,M1,M2,M30,M60} stopping - MODAL_GROUP_M6, // {M6} tool change - MODAL_GROUP_M7, // {M3,M4,M5} spindle turning - MODAL_GROUP_M8, // {M7,M8,M9} coolant (M7 & M8 may be active together) - MODAL_GROUP_M9 // {M48,M49} speed/feed override switches + +enum cmModalGroup { // Used for detecting gcode errors. See NIST section 3.4 + MODAL_GROUP_G0 = 0, // {G10,G28,G28.1,G92} non-modal axis commands (note 1) + MODAL_GROUP_G1, // {G0,G1,G2,G3,G80} motion + MODAL_GROUP_G2, // {G17,G18,G19} plane selection + MODAL_GROUP_G3, // {G90,G91} distance mode + MODAL_GROUP_G5, // {G93,G94} feed rate mode + MODAL_GROUP_G6, // {G20,G21} units + MODAL_GROUP_G7, // {G40,G41,G42} cutter radius compensation + MODAL_GROUP_G8, // {G43,G49} tool length offset + MODAL_GROUP_G9, // {G98,G99} return mode in canned cycles + MODAL_GROUP_G12, // {G54,G55,G56,G57,G58,G59} coordinate system selection + MODAL_GROUP_G13, // {G61,G61.1,G64} path control mode + MODAL_GROUP_M4, // {M0,M1,M2,M30,M60} stopping + MODAL_GROUP_M6, // {M6} tool change + MODAL_GROUP_M7, // {M3,M4,M5} spindle turning + MODAL_GROUP_M8, // {M7,M8,M9} coolant (M7 & M8 may be active together) + MODAL_GROUP_M9 // {M48,M49} speed/feed override switches }; -#define MODAL_GROUP_COUNT (MODAL_GROUP_M9+1) + +#define MODAL_GROUP_COUNT (MODAL_GROUP_M9 + 1) + // Note 1: Our G0 omits G4,G30,G53,G92.1,G92.2,G92.3 as these have no axis components to error check -enum cmCanonicalPlane { // canonical plane - translates to: - // axis_0 axis_1 axis_2 - CANON_PLANE_XY = 0, // G17 X Y Z - CANON_PLANE_XZ, // G18 X Z Y - CANON_PLANE_YZ // G19 Y Z X +enum cmCanonicalPlane { // canonical plane - translates to: + // axis_0 axis_1 axis_2 + CANON_PLANE_XY = 0, // G17 X Y Z + CANON_PLANE_XZ, // G18 X Z Y + CANON_PLANE_YZ // G19 Y Z X }; + enum cmUnitsMode { - INCHES = 0, // G20 - MILLIMETERS, // G21 - DEGREES // ABC axes (this value used for displays only) + INCHES = 0, // G20 + MILLIMETERS, // G21 + DEGREES // ABC axes (this value used for displays only) }; + enum cmCoordSystem { - ABSOLUTE_COORDS = 0, // machine coordinate system - G54, // G54 coordinate system - G55, // G55 coordinate system - G56, // G56 coordinate system - G57, // G57 coordinate system - G58, // G58 coordinate system - G59 // G59 coordinate system + ABSOLUTE_COORDS = 0, // machine coordinate system + G54, // G54 coordinate system + G55, // G55 coordinate system + G56, // G56 coordinate system + G57, // G57 coordinate system + G58, // G58 coordinate system + G59 // G59 coordinate system }; -#define COORD_SYSTEM_MAX G59 // set this manually to the last one -enum cmPathControlMode { // G Modal Group 13 - PATH_EXACT_PATH = 0, // G61 - hits corners but does not stop if it does not need to. - PATH_EXACT_STOP, // G61.1 - stops at all corners - PATH_CONTINUOUS // G64 and typically the default mode +#define COORD_SYSTEM_MAX G59 // set this manually to the last one + +enum cmPathControlMode { // G Modal Group 13 + PATH_EXACT_PATH = 0, // G61 - hits corners but does not stop if it does not need to. + PATH_EXACT_STOP, // G61.1 - stops at all corners + PATH_CONTINUOUS // G64 and typically the default mode }; + enum cmDistanceMode { - ABSOLUTE_MODE = 0, // G90 - INCREMENTAL_MODE // G91 + ABSOLUTE_MODE = 0, // G90 + INCREMENTAL_MODE // G91 }; + enum cmFeedRateMode { - INVERSE_TIME_MODE = 0, // G93 - UNITS_PER_MINUTE_MODE, // G94 - UNITS_PER_REVOLUTION_MODE // G95 (unimplemented) + INVERSE_TIME_MODE = 0, // G93 + UNITS_PER_MINUTE_MODE, // G94 + UNITS_PER_REVOLUTION_MODE // G95 (unimplemented) }; + enum cmOriginOffset { - ORIGIN_OFFSET_SET=0, // G92 - set origin offsets - ORIGIN_OFFSET_CANCEL, // G92.1 - zero out origin offsets - ORIGIN_OFFSET_SUSPEND, // G92.2 - do not apply offsets, but preserve the values - ORIGIN_OFFSET_RESUME // G92.3 - resume application of the suspended offsets + ORIGIN_OFFSET_SET = 0, // G92 - set origin offsets + ORIGIN_OFFSET_CANCEL, // G92.1 - zero out origin offsets + ORIGIN_OFFSET_SUSPEND, // G92.2 - do not apply offsets, but preserve the values + ORIGIN_OFFSET_RESUME // G92.3 - resume application of the suspended offsets }; + enum cmProgramFlow { - PROGRAM_STOP = 0, - PROGRAM_END + PROGRAM_STOP = 0, + PROGRAM_END }; -enum cmSpindleState { // spindle state settings (See hardware.h for bit settings) - SPINDLE_OFF = 0, - SPINDLE_CW, - SPINDLE_CCW + +enum cmSpindleState { // spindle state settings (See hardware.h for bit settings) + SPINDLE_OFF = 0, + SPINDLE_CW, + SPINDLE_CCW }; -enum cmCoolantState { // mist and flood coolant states - COOLANT_OFF = 0, // all coolant off - COOLANT_ON, // request coolant on or indicates both coolants are on - COOLANT_MIST, // indicates mist coolant on - COOLANT_FLOOD // indicates flood coolant on + +enum cmCoolantState { // mist and flood coolant states + COOLANT_OFF = 0, // all coolant off + COOLANT_ON, // request coolant on or indicates both coolants are on + COOLANT_MIST, // indicates mist coolant on + COOLANT_FLOOD // indicates flood coolant on }; -enum cmDirection { // used for spindle and arc dir - DIRECTION_CW = 0, - DIRECTION_CCW + +enum cmDirection { // used for spindle and arc dir + DIRECTION_CW = 0, + DIRECTION_CCW }; -enum cmAxisMode { // axis modes (ordered: see _cm_get_feed_time()) - AXIS_DISABLED = 0, // kill axis - AXIS_STANDARD, // axis in coordinated motion w/standard behaviors - AXIS_INHIBITED, // axis is computed but not activated - AXIS_RADIUS // rotary axis calibrated to circumference -}; // ordering must be preserved. See cm_set_move_times() +enum cmAxisMode { // axis modes (ordered: see _cm_get_feed_time()) + AXIS_DISABLED = 0, // kill axis + AXIS_STANDARD, // axis in coordinated motion w/standard behaviors + AXIS_INHIBITED, // axis is computed but not activated + AXIS_RADIUS // rotary axis calibrated to circumference +}; // ordering must be preserved. See cm_set_move_times() + #define AXIS_MODE_MAX_LINEAR AXIS_INHIBITED #define AXIS_MODE_MAX_ROTARY AXIS_RADIUS -/***************************************************************************** - * FUNCTION PROTOTYPES - * Serves as a table of contents for the rather large canonical machine source file. - */ - -/*--- Internal functions and helpers ---*/ // Model state getters and setters uint8_t cm_get_combined_state(); @@ -530,7 +539,7 @@ uint8_t cm_get_distance_mode(GCodeState_t *gcode_state); uint8_t cm_get_feed_rate_mode(GCodeState_t *gcode_state); uint8_t cm_get_tool(GCodeState_t *gcode_state); uint8_t cm_get_spindle_mode(GCodeState_t *gcode_state); -uint8_t cm_get_block_delete_switch(); +uint8_t cm_get_block_delete_switch(); uint8_t cm_get_runtime_busy(); float cm_get_feed_rate(GCodeState_t *gcode_state); @@ -555,7 +564,7 @@ stat_t cm_deferred_write_callback(); void cm_set_model_target(float target[], float flag[]); stat_t cm_test_soft_limits(float target[]); -/*--- Canonical machining functions (loosely) defined by NIST [organized by NIST Gcode doc] ---*/ +// Canonical machining functions (loosely) defined by NIST [organized by NIST Gcode doc] // Initialization and termination (4.3.2) void canonical_machine_init(); @@ -567,58 +576,58 @@ stat_t cm_soft_alarm(stat_t status); // enter soft al stat_t cm_clear(nvObj_t *nv); // Representation (4.3.3) -stat_t cm_select_plane(uint8_t plane); // G17, G18, G19 -stat_t cm_set_units_mode(uint8_t mode); // G20, G21 -stat_t cm_set_distance_mode(uint8_t mode); // G90, G91 +stat_t cm_select_plane(uint8_t plane); // G17, G18, G19 +stat_t cm_set_units_mode(uint8_t mode); // G20, G21 +stat_t cm_set_distance_mode(uint8_t mode); // G90, G91 stat_t cm_set_coord_offsets(uint8_t coord_system, float offset[], float flag[]); // G10 L2 -void cm_set_position(uint8_t axis, float position); // set absolute position - single axis +void cm_set_position(uint8_t axis, float position); // set absolute position - single axis stat_t cm_set_absolute_origin(float origin[], float flag[]); // G28.3 void cm_set_axis_origin(uint8_t axis, const float position); // G28.3 planner callback -stat_t cm_set_coord_system(uint8_t coord_system); // G54 - G59 -stat_t cm_set_origin_offsets(float offset[], float flag[]); // G92 -stat_t cm_reset_origin_offsets(); // G92.1 -stat_t cm_suspend_origin_offsets(); // G92.2 -stat_t cm_resume_origin_offsets(); // G92.3 +stat_t cm_set_coord_system(uint8_t coord_system); // G54 - G59 +stat_t cm_set_origin_offsets(float offset[], float flag[]); // G92 +stat_t cm_reset_origin_offsets(); // G92.1 +stat_t cm_suspend_origin_offsets(); // G92.2 +stat_t cm_resume_origin_offsets(); // G92.3 // Free Space Motion (4.3.4) -stat_t cm_straight_traverse(float target[], float flags[]); // G0 -stat_t cm_set_g28_position(); // G28.1 +stat_t cm_straight_traverse(float target[], float flags[]); // G0 +stat_t cm_set_g28_position(); // G28.1 stat_t cm_goto_g28_position(float target[], float flags[]); // G28 -stat_t cm_set_g30_position(); // G30.1 -stat_t cm_goto_g30_position(float target[], float flags[]); // G30 +stat_t cm_set_g30_position(); // G30.1 +stat_t cm_goto_g30_position(float target[], float flags[]); // G30 // Machining Attributes (4.3.5) stat_t cm_set_feed_rate(float feed_rate); // F parameter -stat_t cm_set_feed_rate_mode(uint8_t mode); // G93, G94, (G95 unimplemented) +stat_t cm_set_feed_rate_mode(uint8_t mode); // G93, G94, (G95 unimplemented) stat_t cm_set_path_control(uint8_t mode); // G61, G61.1, G64 // Machining Functions (4.3.6) -stat_t cm_straight_feed(float target[], float flags[]); // G1 -stat_t cm_arc_feed( float target[], float flags[], // G2, G3 - float i, float j, float k, - float radius, uint8_t motion_mode); -stat_t cm_dwell(float seconds); // G4, P parameter +stat_t cm_straight_feed(float target[], float flags[]); // G1 +stat_t cm_arc_feed(float target[], float flags[], // G2, G3 + float i, float j, float k, + float radius, uint8_t motion_mode); +stat_t cm_dwell(float seconds); // G4, P parameter // Spindle Functions (4.3.7) // see spindle.h for spindle definitions - which would go right here // Tool Functions (4.3.8) -stat_t cm_select_tool(uint8_t tool); // T parameter -stat_t cm_change_tool(uint8_t tool); // M6 +stat_t cm_select_tool(uint8_t tool); // T parameter +stat_t cm_change_tool(uint8_t tool); // M6 // Miscellaneous Functions (4.3.9) -stat_t cm_mist_coolant_control(uint8_t mist_coolant); // M7 -stat_t cm_flood_coolant_control(uint8_t flood_coolant); // M8, M9 +stat_t cm_mist_coolant_control(uint8_t mist_coolant); // M7 +stat_t cm_flood_coolant_control(uint8_t flood_coolant); // M8, M9 -stat_t cm_override_enables(uint8_t flag); // M48, M49 -stat_t cm_feed_rate_override_enable(uint8_t flag); // M50 -stat_t cm_feed_rate_override_factor(uint8_t flag); // M50.1 -stat_t cm_traverse_override_enable(uint8_t flag); // M50.2 +stat_t cm_override_enables(uint8_t flag); // M48, M49 +stat_t cm_feed_rate_override_enable(uint8_t flag); // M50 +stat_t cm_feed_rate_override_factor(uint8_t flag); // M50.1 +stat_t cm_traverse_override_enable(uint8_t flag); // M50.2 stat_t cm_traverse_override_factor(uint8_t flag); // M50.3 stat_t cm_spindle_override_enable(uint8_t flag); // M51 -stat_t cm_spindle_override_factor(uint8_t flag); // M51.1 +stat_t cm_spindle_override_factor(uint8_t flag); // M51.1 void cm_message(char_t *message); // msg to console (e.g. Gcode comments) @@ -627,37 +636,37 @@ void cm_request_feedhold(); void cm_request_queue_flush(); void cm_request_cycle_start(); -stat_t cm_feedhold_sequencing_callback(); // process feedhold, cycle start and queue flush requests +stat_t cm_feedhold_sequencing_callback(); // process feedhold, cycle start and queue flush requests stat_t cm_queue_flush(); // flush serial and planner queues with coordinate resets -void cm_cycle_start(); // (no Gcode) -void cm_cycle_end(); // (no Gcode) -void cm_feedhold(); // (no Gcode) -void cm_program_stop(); // M0 -void cm_optional_program_stop(); // M1 -void cm_program_end(); // M2 +void cm_cycle_start(); // (no Gcode) +void cm_cycle_end(); // (no Gcode) +void cm_feedhold(); // (no Gcode) +void cm_program_stop(); // M0 +void cm_optional_program_stop(); // M1 +void cm_program_end(); // M2 /*--- Cycles ---*/ // Homing cycles -stat_t cm_homing_cycle_start(); // G28.2 -stat_t cm_homing_cycle_start_no_set(); // G28.4 -stat_t cm_homing_callback(); // G28.2/.4 main loop callback +stat_t cm_homing_cycle_start(); // G28.2 +stat_t cm_homing_cycle_start_no_set(); // G28.4 +stat_t cm_homing_callback(); // G28.2/.4 main loop callback // Probe cycles -stat_t cm_straight_probe(float target[], float flags[]); // G38.2 -stat_t cm_probe_callback(); // G38.2 main loop callback +stat_t cm_straight_probe(float target[], float flags[]); // G38.2 +stat_t cm_probe_callback(); // G38.2 main loop callback // Jogging cycle -stat_t cm_jogging_callback(); // jogging cycle main loop -stat_t cm_jogging_cycle_start(uint8_t axis); // {"jogx":-100.3} +stat_t cm_jogging_callback(); // jogging cycle main loop +stat_t cm_jogging_cycle_start(uint8_t axis); // {"jogx":-100.3} float cm_get_jogging_dest(); /*--- cfgArray interface functions ---*/ char_t cm_get_axis_char(const int8_t axis); -stat_t cm_get_mline(nvObj_t *nv); // get model line number +stat_t cm_get_mline(nvObj_t *nv); // get model line number stat_t cm_get_line(nvObj_t *nv); // get active (model or runtime) line number stat_t cm_get_stat(nvObj_t *nv); // get combined machine state as value and string stat_t cm_get_macs(nvObj_t *nv); // get raw machine state as value and string @@ -672,145 +681,143 @@ stat_t cm_get_plan(nvObj_t *nv); // get active plane... stat_t cm_get_path(nvObj_t *nv); // get patch control mode... stat_t cm_get_dist(nvObj_t *nv); // get distance mode... stat_t cm_get_frmo(nvObj_t *nv); // get feedrate mode... -stat_t cm_get_toolv(nvObj_t *nv); // get tool (value) -stat_t cm_get_pwr(nvObj_t *nv); // get motor power enable state +stat_t cm_get_toolv(nvObj_t *nv); // get tool (value) +stat_t cm_get_pwr(nvObj_t *nv); // get motor power enable state -stat_t cm_get_vel(nvObj_t *nv); // get runtime velocity... +stat_t cm_get_vel(nvObj_t *nv); // get runtime velocity... stat_t cm_get_feed(nvObj_t *nv); -stat_t cm_get_pos(nvObj_t *nv); // get runtime work position... -stat_t cm_get_mpo(nvObj_t *nv); // get runtime machine position... -stat_t cm_get_ofs(nvObj_t *nv); // get runtime work offset... +stat_t cm_get_pos(nvObj_t *nv); // get runtime work position... +stat_t cm_get_mpo(nvObj_t *nv); // get runtime machine position... +stat_t cm_get_ofs(nvObj_t *nv); // get runtime work offset... -stat_t cm_run_qf(nvObj_t *nv); // run queue flush +stat_t cm_run_qf(nvObj_t *nv); // run queue flush stat_t cm_run_home(nvObj_t *nv); // start homing cycle -stat_t cm_dam(nvObj_t *nv); // dump active model (debugging command) +stat_t cm_dam(nvObj_t *nv); // dump active model (debugging command) stat_t cm_run_jogx(nvObj_t *nv); // start jogging cycle for x stat_t cm_run_jogy(nvObj_t *nv); // start jogging cycle for y stat_t cm_run_jogz(nvObj_t *nv); // start jogging cycle for z stat_t cm_run_joga(nvObj_t *nv); // start jogging cycle for a -stat_t cm_get_am(nvObj_t *nv); // get axis mode -stat_t cm_set_am(nvObj_t *nv); // set axis mode -stat_t cm_set_xjm(nvObj_t *nv); // set jerk max with 1,000,000 correction -stat_t cm_set_xjh(nvObj_t *nv); // set jerk homing with 1,000,000 correction - -/*--- text_mode support functions ---*/ +stat_t cm_get_am(nvObj_t *nv); // get axis mode +stat_t cm_set_am(nvObj_t *nv); // set axis mode +stat_t cm_set_xjm(nvObj_t *nv); // set jerk max with 1,000,000 correction +stat_t cm_set_xjh(nvObj_t *nv); // set jerk homing with 1,000,000 correction #ifdef __TEXT_MODE - void cm_print_vel(nvObj_t *nv); // model state reporting - void cm_print_feed(nvObj_t *nv); - void cm_print_line(nvObj_t *nv); - void cm_print_stat(nvObj_t *nv); - void cm_print_macs(nvObj_t *nv); - void cm_print_cycs(nvObj_t *nv); - void cm_print_mots(nvObj_t *nv); - void cm_print_hold(nvObj_t *nv); - void cm_print_home(nvObj_t *nv); - void cm_print_unit(nvObj_t *nv); - void cm_print_coor(nvObj_t *nv); - void cm_print_momo(nvObj_t *nv); - void cm_print_plan(nvObj_t *nv); - void cm_print_path(nvObj_t *nv); - void cm_print_dist(nvObj_t *nv); - void cm_print_frmo(nvObj_t *nv); - void cm_print_tool(nvObj_t *nv); - - void cm_print_gpl(nvObj_t *nv); // Gcode defaults - void cm_print_gun(nvObj_t *nv); - void cm_print_gco(nvObj_t *nv); - void cm_print_gpa(nvObj_t *nv); - void cm_print_gdi(nvObj_t *nv); - - void cm_print_lin(nvObj_t *nv); // generic print for linear values - void cm_print_pos(nvObj_t *nv); // print runtime work position in prevailing units - void cm_print_mpo(nvObj_t *nv); // print runtime work position always in MM units - void cm_print_ofs(nvObj_t *nv); // print runtime work offset always in MM units - - void cm_print_ja(nvObj_t *nv); // global CM settings - void cm_print_ct(nvObj_t *nv); - void cm_print_sl(nvObj_t *nv); - void cm_print_ml(nvObj_t *nv); - void cm_print_ma(nvObj_t *nv); - void cm_print_ms(nvObj_t *nv); - void cm_print_st(nvObj_t *nv); - - void cm_print_am(nvObj_t *nv); // axis print functions - void cm_print_fr(nvObj_t *nv); - void cm_print_vm(nvObj_t *nv); - void cm_print_tm(nvObj_t *nv); - void cm_print_tn(nvObj_t *nv); - void cm_print_jm(nvObj_t *nv); - void cm_print_jh(nvObj_t *nv); - void cm_print_jd(nvObj_t *nv); - void cm_print_ra(nvObj_t *nv); - void cm_print_sn(nvObj_t *nv); - void cm_print_sx(nvObj_t *nv); - void cm_print_sv(nvObj_t *nv); - void cm_print_lv(nvObj_t *nv); - void cm_print_lb(nvObj_t *nv); - void cm_print_zb(nvObj_t *nv); - void cm_print_cofs(nvObj_t *nv); - void cm_print_cpos(nvObj_t *nv); +void cm_print_vel(nvObj_t *nv); // model state reporting +void cm_print_feed(nvObj_t *nv); +void cm_print_line(nvObj_t *nv); +void cm_print_stat(nvObj_t *nv); +void cm_print_macs(nvObj_t *nv); +void cm_print_cycs(nvObj_t *nv); +void cm_print_mots(nvObj_t *nv); +void cm_print_hold(nvObj_t *nv); +void cm_print_home(nvObj_t *nv); +void cm_print_unit(nvObj_t *nv); +void cm_print_coor(nvObj_t *nv); +void cm_print_momo(nvObj_t *nv); +void cm_print_plan(nvObj_t *nv); +void cm_print_path(nvObj_t *nv); +void cm_print_dist(nvObj_t *nv); +void cm_print_frmo(nvObj_t *nv); +void cm_print_tool(nvObj_t *nv); + +void cm_print_gpl(nvObj_t *nv); // Gcode defaults +void cm_print_gun(nvObj_t *nv); +void cm_print_gco(nvObj_t *nv); +void cm_print_gpa(nvObj_t *nv); +void cm_print_gdi(nvObj_t *nv); + +void cm_print_lin(nvObj_t *nv); // generic print for linear values +void cm_print_pos(nvObj_t *nv); // print runtime work position in prevailing units +void cm_print_mpo(nvObj_t *nv); // print runtime work position always in MM units +void cm_print_ofs(nvObj_t *nv); // print runtime work offset always in MM units + +void cm_print_ja(nvObj_t *nv); // global CM settings +void cm_print_ct(nvObj_t *nv); +void cm_print_sl(nvObj_t *nv); +void cm_print_ml(nvObj_t *nv); +void cm_print_ma(nvObj_t *nv); +void cm_print_ms(nvObj_t *nv); +void cm_print_st(nvObj_t *nv); + +void cm_print_am(nvObj_t *nv); // axis print functions +void cm_print_fr(nvObj_t *nv); +void cm_print_vm(nvObj_t *nv); +void cm_print_tm(nvObj_t *nv); +void cm_print_tn(nvObj_t *nv); +void cm_print_jm(nvObj_t *nv); +void cm_print_jh(nvObj_t *nv); +void cm_print_jd(nvObj_t *nv); +void cm_print_ra(nvObj_t *nv); +void cm_print_sn(nvObj_t *nv); +void cm_print_sx(nvObj_t *nv); +void cm_print_sv(nvObj_t *nv); +void cm_print_lv(nvObj_t *nv); +void cm_print_lb(nvObj_t *nv); +void cm_print_zb(nvObj_t *nv); +void cm_print_cofs(nvObj_t *nv); +void cm_print_cpos(nvObj_t *nv); #else // __TEXT_MODE - #define cm_print_vel tx_print_stub // model state reporting - #define cm_print_feed tx_print_stub - #define cm_print_line tx_print_stub - #define cm_print_stat tx_print_stub - #define cm_print_macs tx_print_stub - #define cm_print_cycs tx_print_stub - #define cm_print_mots tx_print_stub - #define cm_print_hold tx_print_stub - #define cm_print_home tx_print_stub - #define cm_print_unit tx_print_stub - #define cm_print_coor tx_print_stub - #define cm_print_momo tx_print_stub - #define cm_print_plan tx_print_stub - #define cm_print_path tx_print_stub - #define cm_print_dist tx_print_stub - #define cm_print_frmo tx_print_stub - #define cm_print_tool tx_print_stub - - #define cm_print_gpl tx_print_stub // Gcode defaults - #define cm_print_gun tx_print_stub - #define cm_print_gco tx_print_stub - #define cm_print_gpa tx_print_stub - #define cm_print_gdi tx_print_stub - - #define cm_print_lin tx_print_stub // generic print for linear values - #define cm_print_pos tx_print_stub // print runtime work position in prevailing units - #define cm_print_mpo tx_print_stub // print runtime work position always in MM uints - #define cm_print_ofs tx_print_stub // print runtime work offset always in MM uints - - #define cm_print_ja tx_print_stub // global CM settings - #define cm_print_ct tx_print_stub - #define cm_print_sl tx_print_stub - #define cm_print_ml tx_print_stub - #define cm_print_ma tx_print_stub - #define cm_print_ms tx_print_stub - #define cm_print_st tx_print_stub - - #define cm_print_am tx_print_stub // axis print functions - #define cm_print_fr tx_print_stub - #define cm_print_vm tx_print_stub - #define cm_print_tm tx_print_stub - #define cm_print_tn tx_print_stub - #define cm_print_jm tx_print_stub - #define cm_print_jh tx_print_stub - #define cm_print_jd tx_print_stub - #define cm_print_ra tx_print_stub - #define cm_print_sn tx_print_stub - #define cm_print_sx tx_print_stub - #define cm_print_sv tx_print_stub - #define cm_print_lv tx_print_stub - #define cm_print_lb tx_print_stub - #define cm_print_zb tx_print_stub - #define cm_print_cofs tx_print_stub - #define cm_print_cpos tx_print_stub +#define cm_print_vel tx_print_stub // model state reporting +#define cm_print_feed tx_print_stub +#define cm_print_line tx_print_stub +#define cm_print_stat tx_print_stub +#define cm_print_macs tx_print_stub +#define cm_print_cycs tx_print_stub +#define cm_print_mots tx_print_stub +#define cm_print_hold tx_print_stub +#define cm_print_home tx_print_stub +#define cm_print_unit tx_print_stub +#define cm_print_coor tx_print_stub +#define cm_print_momo tx_print_stub +#define cm_print_plan tx_print_stub +#define cm_print_path tx_print_stub +#define cm_print_dist tx_print_stub +#define cm_print_frmo tx_print_stub +#define cm_print_tool tx_print_stub + +#define cm_print_gpl tx_print_stub // Gcode defaults +#define cm_print_gun tx_print_stub +#define cm_print_gco tx_print_stub +#define cm_print_gpa tx_print_stub +#define cm_print_gdi tx_print_stub + +#define cm_print_lin tx_print_stub // generic print for linear values +#define cm_print_pos tx_print_stub // print runtime work position in prevailing units +#define cm_print_mpo tx_print_stub // print runtime work position always in MM uints +#define cm_print_ofs tx_print_stub // print runtime work offset always in MM uints + +#define cm_print_ja tx_print_stub // global CM settings +#define cm_print_ct tx_print_stub +#define cm_print_sl tx_print_stub +#define cm_print_ml tx_print_stub +#define cm_print_ma tx_print_stub +#define cm_print_ms tx_print_stub +#define cm_print_st tx_print_stub + +#define cm_print_am tx_print_stub // axis print functions +#define cm_print_fr tx_print_stub +#define cm_print_vm tx_print_stub +#define cm_print_tm tx_print_stub +#define cm_print_tn tx_print_stub +#define cm_print_jm tx_print_stub +#define cm_print_jh tx_print_stub +#define cm_print_jd tx_print_stub +#define cm_print_ra tx_print_stub +#define cm_print_sn tx_print_stub +#define cm_print_sx tx_print_stub +#define cm_print_sv tx_print_stub +#define cm_print_lv tx_print_stub +#define cm_print_lb tx_print_stub +#define cm_print_zb tx_print_stub +#define cm_print_cofs tx_print_stub +#define cm_print_cpos tx_print_stub #endif // __TEXT_MODE -#endif // End of include guard: CANONICAL_MACHINE_H_ONCE +#endif // CANONICAL_MACHINE_H_ONCE diff --git a/src/config.c b/src/config.c index b16e532..cb262bf 100644 --- a/src/config.c +++ b/src/config.c @@ -65,7 +65,7 @@ nvList_t nvl; */ stat_t nv_set(nvObj_t *nv) { if (nv->index >= nv_index_max()) - return(STAT_INTERNAL_RANGE_ERROR); + return STAT_INTERNAL_RANGE_ERROR; return ((fptrCmd)GET_TABLE_WORD(set))(nv); } @@ -83,8 +83,8 @@ void nv_print(nvObj_t *nv) { stat_t nv_persist(nvObj_t *nv) { // nv_persist() cannot be called from an interrupt on the AVR due to the AVR1008 EEPROM workaround - if (nv_index_lt_groups(nv->index) == false) return(STAT_INTERNAL_RANGE_ERROR); - if (GET_TABLE_BYTE(flags) & F_PERSIST) return(write_persistent_value(nv)); + if (nv_index_lt_groups(nv->index) == false) return STAT_INTERNAL_RANGE_ERROR; + if (GET_TABLE_BYTE(flags) & F_PERSIST) return write_persistent_value(nv); return STAT_OK; } @@ -148,7 +148,7 @@ static void _set_defa(nvObj_t *nv) { stat_t set_defaults(nvObj_t *nv) { // failsafe. nv->value must be true or no action occurs - if (fp_FALSE(nv->value)) return(help_defa(nv)); + if (fp_FALSE(nv->value)) return help_defa(nv); _set_defa(nv); // The values in nv are now garbage. Mark the nv as $defa so it displays nicely. @@ -240,7 +240,7 @@ stat_t set_nul(nvObj_t *nv) { return STAT_PARAMETER_IS_READ_ONLY; } stat_t set_ui8(nvObj_t *nv) { *((uint8_t *)GET_TABLE_WORD(target)) = nv->value; nv->valuetype = TYPE_INTEGER; - return(STAT_OK); + return STAT_OK; } @@ -265,7 +265,7 @@ stat_t set_0123(nvObj_t *nv) { stat_t set_int(nvObj_t *nv) { *((uint32_t *)GET_TABLE_WORD(target)) = (uint32_t)nv->value; nv->valuetype = TYPE_INTEGER; - return(STAT_OK); + return STAT_OK; } @@ -273,7 +273,7 @@ stat_t set_data(nvObj_t *nv) { uint32_t *v = (uint32_t*)&nv->value; *((uint32_t *)GET_TABLE_WORD(target)) = *v; nv->valuetype = TYPE_DATA; - return(STAT_OK); + return STAT_OK; } @@ -281,7 +281,7 @@ stat_t set_flt(nvObj_t *nv) { *((float *)GET_TABLE_WORD(target)) = nv->value; nv->precision = GET_TABLE_WORD(precision); nv->valuetype = TYPE_FLOAT; - return(STAT_OK); + return STAT_OK; } @@ -399,13 +399,13 @@ index_t nv_get_index(const char_t *group, const char_t *token) { for (i = 0; i < index_max; i++) { if ((c = GET_TOKEN_BYTE(token[0])) != str[0]) continue; // 1st character mismatch - if ((c = GET_TOKEN_BYTE(token[1])) == 0) {if (str[1] == 0) return(i);} // one character match + if ((c = GET_TOKEN_BYTE(token[1])) == 0) {if (str[1] == 0) return i;} // one character match if (c != str[1]) continue; // 2nd character mismatch - if ((c = GET_TOKEN_BYTE(token[2])) == 0) {if (str[2] == 0) return(i);} // two character match + if ((c = GET_TOKEN_BYTE(token[2])) == 0) {if (str[2] == 0) return i;} // two character match if (c != str[2]) continue; // 3rd character mismatch - if ((c = GET_TOKEN_BYTE(token[3])) == 0) {if (str[3] == 0) return(i);} // three character match + if ((c = GET_TOKEN_BYTE(token[3])) == 0) {if (str[3] == 0) return i;} // three character match if (c != str[3]) continue; // 4th character mismatch - if ((c = GET_TOKEN_BYTE(token[4])) == 0) {if (str[4] == 0) return(i);} // four character match + if ((c = GET_TOKEN_BYTE(token[4])) == 0) {if (str[4] == 0) return i;} // four character match if (c != str[4]) continue; // 5th character mismatch return i; // five character match } @@ -537,7 +537,7 @@ nvObj_t *nv_add_object(const char_t *token) { // add an object to the body usin nvObj_t *nv = nv_body; for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { - if ((nv = nv->nx) == 0) return(0); // not supposed to find a 0; here for safety + if ((nv = nv->nx) == 0) return 0; // not supposed to find a 0; here for safety continue; } @@ -555,7 +555,7 @@ nvObj_t *nv_add_integer(const char_t *token, const uint32_t value) { // add an i nvObj_t *nv = nv_body; for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { - if ((nv = nv->nx) == 0) return(0); // not supposed to find a 0; here for safety + if ((nv = nv->nx) == 0) return 0; // not supposed to find a 0; here for safety continue; } @@ -573,7 +573,7 @@ nvObj_t *nv_add_data(const char_t *token, const uint32_t value) { // add an inte nvObj_t *nv = nv_body; for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { - if ((nv = nv->nx) == 0) return(0); // not supposed to find a 0; here for safety + if ((nv = nv->nx) == 0) return 0; // not supposed to find a 0; here for safety continue; } @@ -591,7 +591,7 @@ nvObj_t *nv_add_float(const char_t *token, const float value) { // add a float o nvObj_t *nv = nv_body; for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { - if ((nv = nv->nx) == 0) return(0); // not supposed to find a 0; here for safety + if ((nv = nv->nx) == 0) return 0; // not supposed to find a 0; here for safety continue; } diff --git a/src/encoder.c b/src/encoder.c index df5dfb1..717fc89 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -87,5 +87,5 @@ void en_set_encoder_steps(uint8_t motor, float steps) float en_read_encoder(uint8_t motor) { - return((float)en.en[motor].encoder_steps); + return (float)en.en[motor].encoder_steps; } diff --git a/src/gcode_parser.c b/src/gcode_parser.c index 6bbfb13..6d8ec23 100644 --- a/src/gcode_parser.c +++ b/src/gcode_parser.c @@ -65,7 +65,7 @@ stat_t gc_gcode_parser(char_t *block) // queue a "(MSG" response if (*msg) cm_message(msg); // queue the message - return(_parse_gcode_block(block)); + return _parse_gcode_block(block); } /* @@ -181,7 +181,7 @@ static stat_t _get_next_gcode_word(char **pstr, char *letter, float *value) char *end; *value = strtof(*pstr, &end); if(end == *pstr) - return(STAT_BAD_NUMBER_FORMAT); // more robust test then checking for value=0; + 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 } @@ -191,7 +191,7 @@ static stat_t _get_next_gcode_word(char **pstr, char *letter, float *value) */ static uint8_t _point(float value) { - return((uint8_t)(value*10 - trunc(value)*10)); // isolate the decimal point as an int + return (uint8_t)(value*10 - trunc(value)*10); // isolate the decimal point as an int } /* @@ -518,5 +518,5 @@ stat_t gc_get_gc(nvObj_t *nv) stat_t gc_run_gc(nvObj_t *nv) { - return(gc_gcode_parser(*nv->stringp)); + return gc_gcode_parser(*nv->stringp); } diff --git a/src/gcode_parser.h b/src/gcode_parser.h index 0796fdb..44c5b3f 100644 --- a/src/gcode_parser.h +++ b/src/gcode_parser.h @@ -20,11 +20,8 @@ #ifndef GCODE_PARSER_H_ONCE #define GCODE_PARSER_H_ONCE -/* - * Global Scope Functions - */ stat_t gc_gcode_parser(char_t *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 // GCODE_PARSER_H_ONCE diff --git a/src/hardware.c b/src/hardware.c index 8827f67..af312f0 100644 --- a/src/hardware.c +++ b/src/hardware.c @@ -163,7 +163,7 @@ stat_t hw_get_id(nvObj_t *nv) { /// hw_run_boot() - invoke boot form the cfgArray stat_t hw_run_boot(nvObj_t *nv) { hw_request_bootloader(); - return(STAT_OK); + return STAT_OK; } diff --git a/src/hardware.h b/src/hardware.h index 9c40629..941418a 100644 --- a/src/hardware.h +++ b/src/hardware.h @@ -111,11 +111,11 @@ enum hwPlatform { * b0 (out) step (SET is step, CLR is rest) * b1 (out) direction (CLR = Clockwise) * b2 (out) motor enable (CLR = Enabled) - * b3 (out) microstep 0 - * b4 (out) microstep 1 + * b3 (out) chip select + * b4 (in) fault * b5 (out) output bit for GPIO port1 - * b6 (in) min limit switch on GPIO 2 (note: motor controls and GPIO2 port mappings are not the same) - * b7 (in) max limit switch on GPIO 2 (note: motor controls and GPIO2 port mappings are not the same) + * b6 (in) min limit switch on GPIO 2 (note: motor controls and GPIO2 port mappings are not the same) + * b7 (in) max limit switch on GPIO 2 (note: motor controls and GPIO2 port mappings are not the same) */ #define MOTOR_PORT_DIR_gm 0x3F // dir settings: lower 6 out, upper 2 in @@ -123,8 +123,8 @@ enum cfgPortBits { // motor control port bit positions STEP_BIT_bp = 0, // bit 0 DIRECTION_BIT_bp, // bit 1 MOTOR_ENABLE_BIT_bp, // bit 2 - MICROSTEP_BIT_0_bp, // bit 3 - MICROSTEP_BIT_1_bp, // bit 4 + CHIP_SELECT_BIT_bp, // bit 3 + FAULT_BIT_bp, // bit 4 GPIO1_OUT_BIT_bp, // bit 5 (4 gpio1 output bits; 1 from each axis) SW_MIN_BIT_bp, // bit 6 (4 input bits for homing/limit switches) SW_MAX_BIT_bp // bit 7 (4 input bits for homing/limit switches) @@ -133,8 +133,8 @@ enum cfgPortBits { // motor control port bit positions #define STEP_BIT_bm (1 << STEP_BIT_bp) #define DIRECTION_BIT_bm (1 << DIRECTION_BIT_bp) #define MOTOR_ENABLE_BIT_bm (1 << MOTOR_ENABLE_BIT_bp) -#define MICROSTEP_BIT_0_bm (1 << MICROSTEP_BIT_0_bp) -#define MICROSTEP_BIT_1_bm (1 << MICROSTEP_BIT_1_bp) +#define CHIP_SELECT_BIT_bm (1 << CHIP_SELECT_BIT_bp) +#define FAULT_BIT_bm (1 << FAULT_BIT_bp) #define GPIO1_OUT_BIT_bm (1 << GPIO1_OUT_BIT_bp) // spindle and coolant output bits #define SW_MIN_BIT_bm (1 << SW_MIN_BIT_bp) // minimum switch inputs #define SW_MAX_BIT_bm (1 << SW_MAX_BIT_bp) // maximum switch inputs diff --git a/src/help.c b/src/help.c index 01102af..bbec30e 100644 --- a/src/help.c +++ b/src/help.c @@ -69,7 +69,7 @@ These commands are active from the command line:\n\ _status_report_advisory(); _postscript(); rpt_print_system_ready_message(); -return(STAT_OK); +return STAT_OK; } /* @@ -102,7 +102,7 @@ For configuration details see: https://github.com/synthetos/TinyG/wiki/TinyG-Con ")); _status_report_advisory(); _postscript(); -return(STAT_OK); +return STAT_OK; } /* @@ -133,7 +133,7 @@ Tests start with a G0 X0 Y0 Z0 move\n\ Homing is the exception. No initial position or clearance is assumed\n\ ")); _postscript(); -return(STAT_OK); +return STAT_OK; } /* @@ -146,7 +146,7 @@ fprintf_P(stderr, PSTR("\ Enter $defa=1 to reset the system to the factory default values.\n\ This will overwrite any changes you have made.\n")); _postscript(); -return(STAT_OK); +return STAT_OK; } /* @@ -158,7 +158,7 @@ fprintf_P(stderr, PSTR("\n\n\n### TinyG BOOT LOADER Help ###\n")); fprintf_P(stderr, PSTR("\ Enter $boot=1 to enter the boot loader.\n")); _postscript(); -return(STAT_OK); +return STAT_OK; } #endif // __HELP_SCREENS diff --git a/src/json_parser.c b/src/json_parser.c index df53ebc..2427000 100644 --- a/src/json_parser.c +++ b/src/json_parser.c @@ -254,7 +254,7 @@ static stat_t _get_nv_pair(nvObj_t *nv, char_t **pstr, int8_t *depth) nv->valuetype = TYPE_PARENT; // *depth += 1; // nv_reset_nv() sets the next object's level so this is redundant (*pstr)++; - return(STAT_EAGAIN); // signal that there is more to parse + return STAT_EAGAIN; // signal that there is more to parse // strings } else if (**pstr == '\"') { // value is a string @@ -566,7 +566,7 @@ stat_t json_set_jv(nvObj_t *nv) if (nv->value >= JV_LINENUM) { js.echo_json_linenum = true;} if (nv->value >= JV_VERBOSE) { js.echo_json_gcode_block = true;} - return(STAT_OK); + return STAT_OK; } diff --git a/src/persistence.c b/src/persistence.c index 7a3f154..9f05d92 100644 --- a/src/persistence.c +++ b/src/persistence.c @@ -57,7 +57,7 @@ stat_t read_persistent_value(nvObj_t *nv) { 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 + return rpt_exception(STAT_FILE_NOT_OPEN); // can't write when machine is moving nvm.tmp_value = nv->value; ritorno(read_persistent_value(nv)); diff --git a/src/plan_exec.c b/src/plan_exec.c index 39f8ca6..edf44bc 100644 --- a/src/plan_exec.c +++ b/src/plan_exec.c @@ -65,7 +65,7 @@ stat_t mp_exec_move() if (cm.motion_state == MOTION_STOP) cm_set_motion_state(MOTION_RUN); } if (bf->bf_func == 0) - return(cm_hard_alarm(STAT_INTERNAL_ERROR)); // never supposed to get here + return cm_hard_alarm(STAT_INTERNAL_ERROR); // never supposed to get here return bf->bf_func(bf); // run the move callback in the planner buffer } @@ -203,7 +203,7 @@ stat_t mp_exec_aline(mpBuf_t *bf) if (mr.section == SECTION_BODY) { status = _exec_aline_body();} else if (mr.section == SECTION_TAIL) { status = _exec_aline_tail();} else if (mr.move_state == MOVE_SKIP_BLOCK) { status = STAT_OK;} - else { return(cm_hard_alarm(STAT_INTERNAL_ERROR));} // never supposed to get here + else { return cm_hard_alarm(STAT_INTERNAL_ERROR);} // never supposed to get here // Feedhold processing. Refer to canonical_machine.h for state machine // Catch the feedhold request and start the planning the hold @@ -387,7 +387,7 @@ static stat_t _exec_aline_head() if (mr.section_state == SECTION_NEW) { // initialize the move singleton (mr) if (fp_ZERO(mr.head_length)) { mr.section = SECTION_BODY; - return(_exec_aline_body()); // skip ahead to the body generator + return _exec_aline_body(); // skip ahead to the body generator } mr.midpoint_velocity = (mr.entry_velocity + mr.cruise_velocity) / 2; mr.gm.move_time = mr.head_length / mr.midpoint_velocity; // time for entire accel region @@ -399,7 +399,7 @@ static stat_t _exec_aline_head() mr.elapsed_accel_time = mr.segment_accel_time / 2; // elapsed time starting point (offset) mr.segment_count = (uint32_t)mr.segments; if (mr.segment_time < MIN_SEGMENT_TIME) - return(STAT_MINIMUM_TIME_MOVE); // exit without advancing position + return STAT_MINIMUM_TIME_MOVE; // exit without advancing position mr.section = SECTION_HEAD; mr.section_state = SECTION_1st_HALF; } @@ -410,7 +410,7 @@ static stat_t _exec_aline_head() mr.section_state = SECTION_2nd_HALF; mr.elapsed_accel_time = mr.segment_accel_time / 2; // start time from midpoint of segment } - return(STAT_EAGAIN); + return STAT_EAGAIN; } if (mr.section_state == SECTION_2nd_HALF) { // SECOND HAF (convex part of accel curve) mr.segment_velocity = mr.midpoint_velocity + @@ -418,12 +418,12 @@ static stat_t _exec_aline_head() (square(mr.elapsed_accel_time) * mr.jerk_div2); if (_exec_aline_segment() == STAT_OK) { // OK means this section is done if ((fp_ZERO(mr.body_length)) && (fp_ZERO(mr.tail_length))) - return(STAT_OK); // ends the move + return STAT_OK; // ends the move mr.section = SECTION_BODY; mr.section_state = SECTION_NEW; } } - return(STAT_EAGAIN); + return STAT_EAGAIN; } #else // __ JERK_EXEC @@ -432,7 +432,7 @@ static stat_t _exec_aline_head() if (mr.section_state == SECTION_NEW) { // initialize the move singleton (mr) if (fp_ZERO(mr.head_length)) { mr.section = SECTION_BODY; - return(_exec_aline_body()); // skip ahead to the body generator + return _exec_aline_body(); // skip ahead to the body generator } mr.gm.move_time = 2*mr.head_length / (mr.entry_velocity + mr.cruise_velocity);// time for entire accel region mr.segments = ceil(uSec(mr.gm.move_time) / NOM_SEGMENT_USEC);// # of segments for the section @@ -440,7 +440,7 @@ static stat_t _exec_aline_head() _init_forward_diffs(mr.entry_velocity, mr.cruise_velocity); mr.segment_count = (uint32_t)mr.segments; if (mr.segment_time < MIN_SEGMENT_TIME) - return(STAT_MINIMUM_TIME_MOVE); // exit without advancing position + return STAT_MINIMUM_TIME_MOVE; // exit without advancing position mr.section = SECTION_HEAD; mr.section_state = SECTION_1st_HALF; // Note: Set to SECTION_1st_HALF for one segment } @@ -453,7 +453,7 @@ static stat_t _exec_aline_head() } else { mr.section_state = SECTION_2nd_HALF; } - return(STAT_EAGAIN); + return STAT_EAGAIN; } if (mr.section_state == SECTION_2nd_HALF) { // SECOND HALF (convex part of accel curve) #ifndef __KAHAN @@ -467,7 +467,7 @@ static stat_t _exec_aline_head() if (_exec_aline_segment() == STAT_OK) { // set up for body if ((fp_ZERO(mr.body_length)) && (fp_ZERO(mr.tail_length))) - return(STAT_OK); // ends the move + return STAT_OK; // ends the move mr.section = SECTION_BODY; mr.section_state = SECTION_NEW; } else { @@ -503,7 +503,7 @@ static stat_t _exec_aline_head() #endif } } - return(STAT_EAGAIN); + return STAT_EAGAIN; } #endif // __ JERK_EXEC @@ -518,7 +518,7 @@ static stat_t _exec_aline_body() if (mr.section_state == SECTION_NEW) { if (fp_ZERO(mr.body_length)) { mr.section = SECTION_TAIL; - return(_exec_aline_tail()); // skip ahead to tail periods + return _exec_aline_tail(); // skip ahead to tail periods } mr.gm.move_time = mr.body_length / mr.cruise_velocity; mr.segments = ceil(uSec(mr.gm.move_time) / NOM_SEGMENT_USEC); @@ -526,19 +526,19 @@ static stat_t _exec_aline_body() mr.segment_velocity = mr.cruise_velocity; mr.segment_count = (uint32_t)mr.segments; if (mr.segment_time < MIN_SEGMENT_TIME) - return(STAT_MINIMUM_TIME_MOVE); // exit without advancing position + return STAT_MINIMUM_TIME_MOVE; // exit without advancing position mr.section = SECTION_BODY; mr.section_state = SECTION_2nd_HALF; // uses PERIOD_2 so last segment detection works } if (mr.section_state == SECTION_2nd_HALF) { // straight part (period 3) if (_exec_aline_segment() == STAT_OK) { // OK means this section is done if (fp_ZERO(mr.tail_length)) - return(STAT_OK); // ends the move + return STAT_OK; // ends the move mr.section = SECTION_TAIL; mr.section_state = SECTION_NEW; } } - return(STAT_EAGAIN); + return STAT_EAGAIN; } /********************************************************************************************* @@ -551,7 +551,7 @@ static stat_t _exec_aline_tail() { if (mr.section_state == SECTION_NEW) { // INITIALIZATION if (fp_ZERO(mr.tail_length)) - return(STAT_OK); // end the move + return STAT_OK; // end the move mr.midpoint_velocity = (mr.cruise_velocity + mr.exit_velocity) / 2; mr.gm.move_time = mr.tail_length / mr.midpoint_velocity; mr.segments = ceil(uSec(mr.gm.move_time) / (2 * NOM_SEGMENT_USEC));// # of segments in *each half* @@ -562,7 +562,7 @@ static stat_t _exec_aline_tail() mr.elapsed_accel_time = mr.segment_accel_time / 2; //compute time from midpoint of segment mr.segment_count = (uint32_t)mr.segments; if (mr.segment_time < MIN_SEGMENT_TIME) - return(STAT_MINIMUM_TIME_MOVE); // exit without advancing position + return STAT_MINIMUM_TIME_MOVE; // exit without advancing position mr.section = SECTION_TAIL; mr.section_state = SECTION_1st_HALF; } @@ -573,7 +573,7 @@ static stat_t _exec_aline_tail() mr.section_state = SECTION_2nd_HALF; mr.elapsed_accel_time = mr.segment_accel_time / 2; // start time from midpoint of segment } - return(STAT_EAGAIN); + return STAT_EAGAIN; } if (mr.section_state == SECTION_2nd_HALF) { // SECOND HALF - concave part (period 5) mr.segment_velocity = mr.midpoint_velocity - @@ -581,7 +581,7 @@ static stat_t _exec_aline_tail() (square(mr.elapsed_accel_time) * mr.jerk_div2); return _exec_aline_segment(); // ends the move or continues EAGAIN } - return(STAT_EAGAIN); // should never get here + return STAT_EAGAIN; // should never get here } #else // __JERK_EXEC -- run forward differencing math @@ -590,14 +590,14 @@ static stat_t _exec_aline_tail() { if (mr.section_state == SECTION_NEW) { // INITIALIZATION if (fp_ZERO(mr.tail_length)) - return(STAT_OK); // end the move + return STAT_OK; // end the move mr.gm.move_time = 2*mr.tail_length / (mr.cruise_velocity + mr.exit_velocity); // len/avg. velocity mr.segments = ceil(uSec(mr.gm.move_time) / NOM_SEGMENT_USEC);// # of segments for the section mr.segment_time = mr.gm.move_time / mr.segments; // time to advance for each segment _init_forward_diffs(mr.cruise_velocity, mr.exit_velocity); mr.segment_count = (uint32_t)mr.segments; if (mr.segment_time < MIN_SEGMENT_TIME) - return(STAT_MINIMUM_TIME_MOVE); // exit without advancing position + return STAT_MINIMUM_TIME_MOVE; // exit without advancing position mr.section = SECTION_TAIL; mr.section_state = SECTION_1st_HALF; } @@ -611,7 +611,7 @@ static stat_t _exec_aline_tail() } else { mr.section_state = SECTION_2nd_HALF; } - return(STAT_EAGAIN); + return STAT_EAGAIN; } if (mr.section_state == SECTION_2nd_HALF) { // SECOND HALF - concave part (period 5) #ifndef __KAHAN @@ -658,7 +658,7 @@ static stat_t _exec_aline_tail() #endif } } - return(STAT_EAGAIN); // should never get here + return STAT_EAGAIN; // should never get here } #endif // __JERK_EXEC diff --git a/src/plan_line.c b/src/plan_line.c index f024317..c880ef3 100644 --- a/src/plan_line.c +++ b/src/plan_line.c @@ -143,7 +143,7 @@ stat_t mp_aline(GCodeState_t *gm_in) // get a cleared buffer and setup move variables if ((bf = mp_get_write_buffer()) == 0) - return(cm_hard_alarm(STAT_BUFFER_FULL_FATAL)); // never supposed to fail + return cm_hard_alarm(STAT_BUFFER_FULL_FATAL); // never supposed to fail bf->bf_func = mp_exec_aline; // register the callback to the exec function bf->length = length; memcpy(&bf->gm, gm_in, sizeof(GCodeState_t)); // copy model state into planner buffer diff --git a/src/plan_zoid.c b/src/plan_zoid.c index f477438..7b289f5 100644 --- a/src/plan_zoid.c +++ b/src/plan_zoid.c @@ -336,7 +336,7 @@ void mp_calculate_trapezoid(mpBuf_t *bf) * e) Vf = L^(2/3) * Jm^(1/3) + Vi * * FYI: Here's an expression that returns the jerk for a given deltaV and L: - * return(cube(deltaV / (pow(L, 0.66666666)))); + * return cube(deltaV / (pow(L, 0.66666666))); */ float mp_get_target_length(const float Vi, const float Vf, const mpBuf_t *bf) diff --git a/src/planner.c b/src/planner.c index df5f394..07c02bb 100644 --- a/src/planner.c +++ b/src/planner.c @@ -237,7 +237,7 @@ stat_t mp_dwell(float seconds) mpBuf_t *bf; if ((bf = mp_get_write_buffer()) == 0) // get write buffer or fail - return(cm_hard_alarm(STAT_BUFFER_FULL_FATAL)); // not ever supposed to fail + return cm_hard_alarm(STAT_BUFFER_FULL_FATAL); // not ever supposed to fail bf->bf_func = _exec_dwell; // register callback to dwell start bf->gm.move_time = seconds; // in seconds, not minutes @@ -400,7 +400,7 @@ uint8_t mp_free_run_buffer() // EMPTY current run buf & adv t mpBuf_t * mp_get_first_buffer() { - return(mp_get_run_buffer()); // returns buffer or 0 if nothing's running + return mp_get_run_buffer(); // returns buffer or 0 if nothing's running } mpBuf_t * mp_get_last_buffer() @@ -408,7 +408,7 @@ mpBuf_t * mp_get_last_buffer() mpBuf_t *bf = mp_get_run_buffer(); mpBuf_t *bp = bf; - if (bf == 0) return(0); + if (bf == 0) return 0; do { if ((bp->nx->move_state == MOVE_OFF) || (bp->nx == bf)) { diff --git a/src/report.c b/src/report.c index b5289e5..bd2e842 100644 --- a/src/report.c +++ b/src/report.c @@ -61,7 +61,7 @@ stat_t rpt_exception(uint8_t status) TINYG_FIRMWARE_BUILD, status, get_status_message(status)); } } - return status; // makes it possible to inline, e.g: return(rpt_exception(status)); + return status; // makes it possible to inline, e.g: return rpt_exception(status); } /* @@ -69,7 +69,7 @@ stat_t rpt_exception(uint8_t status) */ stat_t rpt_er(nvObj_t *nv) { - return(rpt_exception(STAT_GENERIC_EXCEPTION_REPORT)); // bogus exception report for testing + return rpt_exception(STAT_GENERIC_EXCEPTION_REPORT); // bogus exception report for testing } /**** Application Messages ********************************************************* @@ -226,7 +226,7 @@ stat_t sr_set_status_report(nvObj_t *nv) if (elements == 0) return STAT_INVALID_OR_MALFORMED_COMMAND; memcpy(sr.status_report_list, status_report_list, sizeof(status_report_list)); - return(_populate_unfiltered_status_report()); // return current values + return _populate_unfiltered_status_report(); // return current values } /* @@ -386,7 +386,7 @@ stat_t sr_set_si(nvObj_t *nv) { if (nv->value < STATUS_REPORT_MIN_MS) { nv->value = STATUS_REPORT_MIN_MS;} sr.status_report_interval = (uint32_t)nv->value; - return(STAT_OK); + return STAT_OK; } /********************* diff --git a/src/spindle.c b/src/spindle.c index 0237e7c..f687802 100644 --- a/src/spindle.c +++ b/src/spindle.c @@ -88,7 +88,7 @@ stat_t cm_spindle_control(uint8_t spindle_mode) { float value[AXES] = { (float)spindle_mode, 0,0,0,0,0 }; mp_queue_command(_exec_spindle_control, value, value); - return(STAT_OK); + return STAT_OK; } //static void _exec_spindle_control(uint8_t spindle_mode, float f, float *vector, float *flag) diff --git a/src/stepper.c b/src/stepper.c index 47b8123..2270095 100644 --- a/src/stepper.c +++ b/src/stepper.c @@ -40,26 +40,25 @@ #include "text_parser.h" #include "util.h" -/**** Allocate structures ****/ stConfig_t st_cfg; stPrepSingleton_t st_pre; static stRunSingleton_t st_run; -/**** Setup local functions ****/ - static void _load_move(); static void _request_load_move(); + // handy macro #define _f_to_period(f) (uint16_t)((float)F_CPU / (float)f) + /* * stepper_init() - initialize stepper motor subsystem * * Notes: * - This init requires sys_init() to be run beforehand - * - microsteps are setup during config_init() + * - microsteps are setup during config_init() * - motor polarity is setup during config_init() * - high level interrupts must be enabled in main() once all inits are complete */ @@ -75,69 +74,69 @@ static void _request_load_move(); * pmc_enable_periph_clk(TC_ID_DDA); * TC_Start(TC_BLOCK_DDA, TC_CHANNEL_DDA); */ +void stepper_init() { + memset(&st_run, 0, sizeof(st_run)); // clear all values, pointers and status + stepper_init_assertions(); -void stepper_init() -{ - memset(&st_run, 0, sizeof(st_run)); // clear all values, pointers and status - stepper_init_assertions(); + // Configure virtual ports + PORTCFG.VPCTRLA = PORTCFG_VP0MAP_PORT_MOTOR_1_gc | PORTCFG_VP1MAP_PORT_MOTOR_2_gc; + PORTCFG.VPCTRLB = PORTCFG_VP2MAP_PORT_MOTOR_3_gc | PORTCFG_VP3MAP_PORT_MOTOR_4_gc; - // Configure virtual ports - PORTCFG.VPCTRLA = PORTCFG_VP0MAP_PORT_MOTOR_1_gc | PORTCFG_VP1MAP_PORT_MOTOR_2_gc; - PORTCFG.VPCTRLB = PORTCFG_VP2MAP_PORT_MOTOR_3_gc | PORTCFG_VP3MAP_PORT_MOTOR_4_gc; + // setup ports and data structures + for (uint8_t i = 0; i < MOTORS; i++) { + hw.st_port[i]->DIR = MOTOR_PORT_DIR_gm; // sets outputs for motors & GPIO1, and GPIO2 inputs + hw.st_port[i]->OUT = MOTOR_ENABLE_BIT_bm; // zero port bits AND disable motor + } - // setup ports and data structures - for (uint8_t i=0; iDIR = MOTOR_PORT_DIR_gm; // sets outputs for motors & GPIO1, and GPIO2 inputs - hw.st_port[i]->OUT = MOTOR_ENABLE_BIT_bm;// zero port bits AND disable motor - } - // setup DDA timer - TIMER_DDA.CTRLA = STEP_TIMER_DISABLE; // turn timer off - TIMER_DDA.CTRLB = STEP_TIMER_WGMODE; // waveform mode - TIMER_DDA.INTCTRLA = TIMER_DDA_INTLVL; // interrupt mode + // setup DDA timer + TIMER_DDA.CTRLA = STEP_TIMER_DISABLE; // turn timer off + TIMER_DDA.CTRLB = STEP_TIMER_WGMODE; // waveform mode + TIMER_DDA.INTCTRLA = TIMER_DDA_INTLVL; // interrupt mode - // setup DWELL timer - TIMER_DWELL.CTRLA = STEP_TIMER_DISABLE; // turn timer off - TIMER_DWELL.CTRLB = STEP_TIMER_WGMODE; // waveform mode - TIMER_DWELL.INTCTRLA = TIMER_DWELL_INTLVL; // interrupt mode + // setup DWELL timer + TIMER_DWELL.CTRLA = STEP_TIMER_DISABLE; // turn timer off + TIMER_DWELL.CTRLB = STEP_TIMER_WGMODE; // waveform mode + TIMER_DWELL.INTCTRLA = TIMER_DWELL_INTLVL; // interrupt mode - // setup software interrupt load timer - TIMER_LOAD.CTRLA = LOAD_TIMER_DISABLE; // turn timer off - TIMER_LOAD.CTRLB = LOAD_TIMER_WGMODE; // waveform mode - TIMER_LOAD.INTCTRLA = TIMER_LOAD_INTLVL; // interrupt mode - TIMER_LOAD.PER = LOAD_TIMER_PERIOD; // set period + // setup software interrupt load timer + TIMER_LOAD.CTRLA = LOAD_TIMER_DISABLE; // turn timer off + TIMER_LOAD.CTRLB = LOAD_TIMER_WGMODE; // waveform mode + TIMER_LOAD.INTCTRLA = TIMER_LOAD_INTLVL; // interrupt mode + TIMER_LOAD.PER = LOAD_TIMER_PERIOD; // set period - // setup software interrupt exec timer - TIMER_EXEC.CTRLA = EXEC_TIMER_DISABLE; // turn timer off - TIMER_EXEC.CTRLB = EXEC_TIMER_WGMODE; // waveform mode - TIMER_EXEC.INTCTRLA = TIMER_EXEC_INTLVL; // interrupt mode - TIMER_EXEC.PER = EXEC_TIMER_PERIOD; // set period + // setup software interrupt exec timer + TIMER_EXEC.CTRLA = EXEC_TIMER_DISABLE; // turn timer off + TIMER_EXEC.CTRLB = EXEC_TIMER_WGMODE; // waveform mode + TIMER_EXEC.INTCTRLA = TIMER_EXEC_INTLVL; // interrupt mode + TIMER_EXEC.PER = EXEC_TIMER_PERIOD; // set period - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_EXEC; - st_reset(); // reset steppers to known state + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_EXEC; + st_reset(); // reset steppers to known state } + /* * stepper_init_assertions() - test assertions, return error code if violation exists * stepper_test_assertions() - test assertions, return error code if violation exists */ - -void stepper_init_assertions() -{ - st_run.magic_end = MAGICNUM; - st_run.magic_start = MAGICNUM; - st_pre.magic_end = MAGICNUM; - st_pre.magic_start = MAGICNUM; +void stepper_init_assertions() { + st_run.magic_end = MAGICNUM; + st_run.magic_start = MAGICNUM; + st_pre.magic_end = MAGICNUM; + st_pre.magic_start = MAGICNUM; } -stat_t stepper_test_assertions() -{ - if (st_run.magic_end != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; - if (st_run.magic_start != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; - if (st_pre.magic_end != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; - if (st_pre.magic_start != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; - return STAT_OK; + +stat_t stepper_test_assertions() { + if (st_run.magic_end != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; + if (st_run.magic_start != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; + if (st_pre.magic_end != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; + if (st_pre.magic_start != MAGICNUM) return STAT_STEPPER_ASSERTION_FAILURE; + + return STAT_OK; } + /* * st_runtime_isbusy() - return TRUE if runtime is busy: * @@ -145,37 +144,28 @@ stat_t stepper_test_assertions() * - motors are running * - dwell is running */ - -uint8_t st_runtime_isbusy() -{ - if (st_run.dda_ticks_downcount == 0) { - return false; - } - return true; +uint8_t st_runtime_isbusy() { + return st_run.dda_ticks_downcount != 0; } -/* - * st_reset() - reset stepper internals - */ -void st_reset() -{ - for (uint8_t motor=0; motor st_run.mot[m].power_systick ) { - st_run.mot[m].power_state = MOTOR_IDLE; - _deenergize_motor(m); - sr_request_status_report(SR_TIMED_REQUEST); // request a status report when motors shut down - } - } +stat_t st_motor_power_callback() { // called by controller + // manage power for each motor individually + for (uint8_t m = MOTOR_1; m < MOTORS; m++) { + + // de-energize motor if it's set to MOTOR_DISABLED + if (st_cfg.mot[m].power_mode == MOTOR_DISABLED) { + _deenergize_motor(m); + continue; } - return STAT_OK; -} - -/****************************** - * Interrupt Service Routines * - ******************************/ - -/***** Stepper Interrupt Service Routine ************************************************ - * ISR - DDA timer interrupt routine - service ticks from DDA timer - */ + // energize motor if it's set to MOTOR_ALWAYS_POWERED + if (st_cfg.mot[m].power_mode == MOTOR_ALWAYS_POWERED) { + if (! _motor_is_enabled(m)) _energize_motor(m); + continue; + } -/* - * Uses direct struct addresses and literal values for hardware devices - it's faster than - * using indexed timer and port accesses. I checked. Even when -0s or -03 is used. - */ -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 - st_run.mot[MOTOR_1].substep_accumulator -= st_run.dda_ticks_X_substeps; - INCREMENT_ENCODER(MOTOR_1); + // start a countdown if MOTOR_POWERED_IN_CYCLE or MOTOR_POWERED_ONLY_WHEN_MOVING + if (st_run.mot[m].power_state == MOTOR_POWER_TIMEOUT_START) { + st_run.mot[m].power_state = MOTOR_POWER_TIMEOUT_COUNTDOWN; + st_run.mot[m].power_systick = SysTickTimer_getValue() + + (st_cfg.motor_power_timeout * 1000); } - if ((st_run.mot[MOTOR_2].substep_accumulator += st_run.mot[MOTOR_2].substep_increment) > 0) { - 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); + + // do not process countdown if in a feedhold + if (cm_get_combined_state() == COMBINED_HOLD) { + continue; } - if ((st_run.mot[MOTOR_3].substep_accumulator += st_run.mot[MOTOR_3].substep_increment) > 0) { - 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); + + // do not process countdown if in a feedhold + if (cm_get_combined_state() == COMBINED_HOLD) { + continue; } - if ((st_run.mot[MOTOR_4].substep_accumulator += st_run.mot[MOTOR_4].substep_increment) > 0) { - 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); + + // run the countdown if you are in a countdown + if (st_run.mot[m].power_state == MOTOR_POWER_TIMEOUT_COUNTDOWN) { + if (SysTickTimer_getValue() > st_run.mot[m].power_systick ) { + st_run.mot[m].power_state = MOTOR_IDLE; + _deenergize_motor(m); + sr_request_status_report(SR_TIMED_REQUEST); // request a status report when motors shut down + } } + } - // pulse stretching for using external drivers.- turn step bits off - 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 + return STAT_OK; +} - if (--st_run.dda_ticks_downcount != 0) return; - TIMER_DDA.CTRLA = STEP_TIMER_DISABLE; // disable DDA timer - _load_move(); // load the next move -} +/*** + Stepper Interrupt Service Routine + DDA timer interrupt routine - service ticks from DDA timer + Uses direct struct addresses and literal values for hardware devices - it's faster than + using indexed timer and port accesses. I checked. Even when -0s or -03 is used. +*/ +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 + st_run.mot[MOTOR_1].substep_accumulator -= st_run.dda_ticks_X_substeps; + INCREMENT_ENCODER(MOTOR_1); + } -/***** Dwell Interrupt Service Routine ************************************************** - * ISR - DDA timer interrupt routine - service ticks from DDA timer - */ + if ((st_run.mot[MOTOR_2].substep_accumulator += st_run.mot[MOTOR_2].substep_increment) > 0) { + 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; + 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; + st_run.mot[MOTOR_4].substep_accumulator -= st_run.dda_ticks_X_substeps; + INCREMENT_ENCODER(MOTOR_4); + } + + // pulse stretching for using external drivers.- turn step bits off + 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 + _load_move(); // load the next move +} + + +/// DDA timer interrupt routine - service ticks from DDA timer ISR(TIMER_DWELL_ISR_vect) { // DWELL timer interrupt - if (--st_run.dda_ticks_downcount == 0) { - TIMER_DWELL.CTRLA = STEP_TIMER_DISABLE; // disable DWELL timer - _load_move(); - } + if (--st_run.dda_ticks_downcount == 0) { + TIMER_DWELL.CTRLA = STEP_TIMER_DISABLE; // disable DWELL timer + _load_move(); + } } + /**************************************************************************************** * Exec sequencing code - computes and prepares next load segment * st_request_exec_move() - SW interrupt to request to execute a move * exec_timer interrupt - interrupt handler for calling exec function */ - -void st_request_exec_move() -{ - if (st_pre.buffer_state == PREP_BUFFER_OWNED_BY_EXEC) {// bother interrupting - TIMER_EXEC.PER = EXEC_TIMER_PERIOD; - TIMER_EXEC.CTRLA = EXEC_TIMER_ENABLE; // trigger a LO interrupt - } +void st_request_exec_move() { + if (st_pre.buffer_state == PREP_BUFFER_OWNED_BY_EXEC) {// bother interrupting + TIMER_EXEC.PER = EXEC_TIMER_PERIOD; + TIMER_EXEC.CTRLA = EXEC_TIMER_ENABLE; // trigger a LO interrupt + } } + ISR(TIMER_EXEC_ISR_vect) { // exec move SW interrupt - TIMER_EXEC.CTRLA = EXEC_TIMER_DISABLE; // disable SW interrupt timer - - // exec_move - if (st_pre.buffer_state == PREP_BUFFER_OWNED_BY_EXEC) { - if (mp_exec_move() != STAT_NOOP) { - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // flip it back - _request_load_move(); - } + TIMER_EXEC.CTRLA = EXEC_TIMER_DISABLE; // disable SW interrupt timer + + // exec_move + if (st_pre.buffer_state == PREP_BUFFER_OWNED_BY_EXEC) { + if (mp_exec_move() != STAT_NOOP) { + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // flip it back + _request_load_move(); } + } } /**************************************************************************************** @@ -392,21 +376,19 @@ ISR(TIMER_EXEC_ISR_vect) { // exec move SW interr * the DDA or dwell ISR. A software interrupt has been provided to allow a non-ISR to * request a load (see st_request_load_move()) */ +static void _request_load_move() { + if (st_runtime_isbusy()) return; // don't request a load if the runtime is busy -static void _request_load_move() -{ - if (st_runtime_isbusy()) { - return; // don't request a load if the runtime is busy - } - if (st_pre.buffer_state == PREP_BUFFER_OWNED_BY_LOADER) { // bother interrupting - TIMER_LOAD.PER = LOAD_TIMER_PERIOD; - TIMER_LOAD.CTRLA = LOAD_TIMER_ENABLE; // trigger a HI interrupt - } + if (st_pre.buffer_state == PREP_BUFFER_OWNED_BY_LOADER) { // bother interrupting + TIMER_LOAD.PER = LOAD_TIMER_PERIOD; + TIMER_LOAD.CTRLA = LOAD_TIMER_ENABLE; // trigger a HI interrupt + } } -ISR(TIMER_LOAD_ISR_vect) { // load steppers SW interrupt - TIMER_LOAD.CTRLA = LOAD_TIMER_DISABLE; // disable SW interrupt timer - _load_move(); + +ISR(TIMER_LOAD_ISR_vect) { // load steppers SW interrupt + TIMER_LOAD.CTRLA = LOAD_TIMER_DISABLE; // disable SW interrupt timer + _load_move(); } @@ -422,218 +404,230 @@ ISR(TIMER_LOAD_ISR_vect) { // load steppe * - If axis has 0 steps the direction setting can be omitted * - If axis has 0 steps the motor must not be enabled to support power mode = 1 */ -static void _load_move() -{ - // Be aware that dda_ticks_downcount must equal zero for the loader to run. - // So the initial load must also have this set to zero as part of initialization - if (st_runtime_isbusy()) { - return; // exit if the runtime is busy - } - if (st_pre.buffer_state != PREP_BUFFER_OWNED_BY_LOADER) { // if there are no moves to load... - return; +static void _load_move() { + // Be aware that dda_ticks_downcount must equal zero for the loader to run. + // So the initial load must also have this set to zero as part of initialization + if (st_runtime_isbusy()) return; // exit if the runtime is busy + if (st_pre.buffer_state != PREP_BUFFER_OWNED_BY_LOADER) return; // if there are no moves to load... + + // handle aline loads first (most common case) + if (st_pre.move_type == MOVE_TYPE_ALINE) { + //**** setup the new segment **** + st_run.dda_ticks_downcount = st_pre.dda_ticks; + st_run.dda_ticks_X_substeps = st_pre.dda_ticks_X_substeps; + + //**** MOTOR_1 LOAD **** + + // These sections are somewhat optimized for execution speed. The whole load operation + // is supposed to take < 10 uSec (Xmega). Be careful if you mess with this. + + // the following if() statement sets the runtime substep increment value or zeroes it + if ((st_run.mot[MOTOR_1].substep_increment = st_pre.mot[MOTOR_1].substep_increment) != 0) { + // NB: If motor has 0 steps the following is all skipped. This ensures that state comparisons + // always operate on the last segment actually run by this motor, regardless of how many + // segments it may have been inactive in between. + + // Apply accumulator correction if the time base has changed since previous segment + if (st_pre.mot[MOTOR_1].accumulator_correction_flag == true) { + st_pre.mot[MOTOR_1].accumulator_correction_flag = false; + st_run.mot[MOTOR_1].substep_accumulator *= st_pre.mot[MOTOR_1].accumulator_correction; + } + + // Detect direction change and if so: + // - Set the direction bit in hardware. + // - Compensate for direction change by flipping substep accumulator value about its midpoint. + if (st_pre.mot[MOTOR_1].direction != st_pre.mot[MOTOR_1].prev_direction) { + st_pre.mot[MOTOR_1].prev_direction = st_pre.mot[MOTOR_1].direction; + st_run.mot[MOTOR_1].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_1].substep_accumulator); + + if (st_pre.mot[MOTOR_1].direction == DIRECTION_CW) + PORT_MOTOR_1_VPORT.OUT &= ~DIRECTION_BIT_bm; + else PORT_MOTOR_1_VPORT.OUT |= DIRECTION_BIT_bm; + } + + SET_ENCODER_STEP_SIGN(MOTOR_1, st_pre.mot[MOTOR_1].step_sign); + + // Enable the stepper and start motor power management + if (st_cfg.mot[MOTOR_1].power_mode != MOTOR_DISABLED) { + PORT_MOTOR_1_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; // energize motor + st_run.mot[MOTOR_1].power_state = MOTOR_POWER_TIMEOUT_START;// set power management state + } + + } else if (st_cfg.mot[MOTOR_1].power_mode == MOTOR_POWERED_IN_CYCLE) { + // Motor has 0 steps; might need to energize motor for power mode processing + PORT_MOTOR_1_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; // energize motor + st_run.mot[MOTOR_1].power_state = MOTOR_POWER_TIMEOUT_START; } - // handle aline loads first (most common case) - if (st_pre.move_type == MOVE_TYPE_ALINE) { - - //**** setup the new segment **** - - st_run.dda_ticks_downcount = st_pre.dda_ticks; - st_run.dda_ticks_X_substeps = st_pre.dda_ticks_X_substeps; - - //**** MOTOR_1 LOAD **** - - // These sections are somewhat optimized for execution speed. The whole load operation - // is supposed to take < 10 uSec (Xmega). Be careful if you mess with this. - - // the following if() statement sets the runtime substep increment value or zeroes it - if ((st_run.mot[MOTOR_1].substep_increment = st_pre.mot[MOTOR_1].substep_increment) != 0) { - - // NB: If motor has 0 steps the following is all skipped. This ensures that state comparisons - // always operate on the last segment actually run by this motor, regardless of how many - // segments it may have been inactive in between. - - // Apply accumulator correction if the time base has changed since previous segment - if (st_pre.mot[MOTOR_1].accumulator_correction_flag == true) { - st_pre.mot[MOTOR_1].accumulator_correction_flag = false; - st_run.mot[MOTOR_1].substep_accumulator *= st_pre.mot[MOTOR_1].accumulator_correction; - } - - // Detect direction change and if so: - // - Set the direction bit in hardware. - // - Compensate for direction change by flipping substep accumulator value about its midpoint. - - if (st_pre.mot[MOTOR_1].direction != st_pre.mot[MOTOR_1].prev_direction) { - st_pre.mot[MOTOR_1].prev_direction = st_pre.mot[MOTOR_1].direction; - st_run.mot[MOTOR_1].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_1].substep_accumulator); - if (st_pre.mot[MOTOR_1].direction == DIRECTION_CW) - PORT_MOTOR_1_VPORT.OUT &= ~DIRECTION_BIT_bm; else - PORT_MOTOR_1_VPORT.OUT |= DIRECTION_BIT_bm; - } - SET_ENCODER_STEP_SIGN(MOTOR_1, st_pre.mot[MOTOR_1].step_sign); - - // Enable the stepper and start motor power management - if (st_cfg.mot[MOTOR_1].power_mode != MOTOR_DISABLED) { - PORT_MOTOR_1_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; // energize motor - st_run.mot[MOTOR_1].power_state = MOTOR_POWER_TIMEOUT_START;// set power management state - } - - } else { // Motor has 0 steps; might need to energize motor for power mode processing - if (st_cfg.mot[MOTOR_1].power_mode == MOTOR_POWERED_IN_CYCLE) { - PORT_MOTOR_1_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; // energize motor - st_run.mot[MOTOR_1].power_state = MOTOR_POWER_TIMEOUT_START; - } - } - // accumulate counted steps to the step position and zero out counted steps for the segment currently being loaded - ACCUMULATE_ENCODER(MOTOR_1); + + // accumulate counted steps to the step position and zero out counted steps for the segment currently being loaded + ACCUMULATE_ENCODER(MOTOR_1); #if (MOTORS >= 2) //**** MOTOR_2 LOAD **** - if ((st_run.mot[MOTOR_2].substep_increment = st_pre.mot[MOTOR_2].substep_increment) != 0) { - if (st_pre.mot[MOTOR_2].accumulator_correction_flag == true) { - st_pre.mot[MOTOR_2].accumulator_correction_flag = false; - st_run.mot[MOTOR_2].substep_accumulator *= st_pre.mot[MOTOR_2].accumulator_correction; - } - if (st_pre.mot[MOTOR_2].direction != st_pre.mot[MOTOR_2].prev_direction) { - st_pre.mot[MOTOR_2].prev_direction = st_pre.mot[MOTOR_2].direction; - st_run.mot[MOTOR_2].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_2].substep_accumulator); - if (st_pre.mot[MOTOR_2].direction == DIRECTION_CW) - PORT_MOTOR_2_VPORT.OUT &= ~DIRECTION_BIT_bm; else - PORT_MOTOR_2_VPORT.OUT |= DIRECTION_BIT_bm; - } - SET_ENCODER_STEP_SIGN(MOTOR_2, st_pre.mot[MOTOR_2].step_sign); - if (st_cfg.mot[MOTOR_2].power_mode != MOTOR_DISABLED) { - PORT_MOTOR_2_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_2].power_state = MOTOR_POWER_TIMEOUT_START; - } - } else { - if (st_cfg.mot[MOTOR_2].power_mode == MOTOR_POWERED_IN_CYCLE) { - PORT_MOTOR_2_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_2].power_state = MOTOR_POWER_TIMEOUT_START; - } - } - ACCUMULATE_ENCODER(MOTOR_2); + if ((st_run.mot[MOTOR_2].substep_increment = st_pre.mot[MOTOR_2].substep_increment) != 0) { + if (st_pre.mot[MOTOR_2].accumulator_correction_flag == true) { + st_pre.mot[MOTOR_2].accumulator_correction_flag = false; + st_run.mot[MOTOR_2].substep_accumulator *= st_pre.mot[MOTOR_2].accumulator_correction; + } + + if (st_pre.mot[MOTOR_2].direction != st_pre.mot[MOTOR_2].prev_direction) { + st_pre.mot[MOTOR_2].prev_direction = st_pre.mot[MOTOR_2].direction; + st_run.mot[MOTOR_2].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_2].substep_accumulator); + if (st_pre.mot[MOTOR_2].direction == DIRECTION_CW) + PORT_MOTOR_2_VPORT.OUT &= ~DIRECTION_BIT_bm; + else PORT_MOTOR_2_VPORT.OUT |= DIRECTION_BIT_bm; + } + + SET_ENCODER_STEP_SIGN(MOTOR_2, st_pre.mot[MOTOR_2].step_sign); + + if (st_cfg.mot[MOTOR_2].power_mode != MOTOR_DISABLED) { + PORT_MOTOR_2_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_2].power_state = MOTOR_POWER_TIMEOUT_START; + } + } else if (st_cfg.mot[MOTOR_2].power_mode == MOTOR_POWERED_IN_CYCLE) { + PORT_MOTOR_2_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_2].power_state = MOTOR_POWER_TIMEOUT_START; + } + + ACCUMULATE_ENCODER(MOTOR_2); #endif + #if (MOTORS >= 3) //**** MOTOR_3 LOAD **** - if ((st_run.mot[MOTOR_3].substep_increment = st_pre.mot[MOTOR_3].substep_increment) != 0) { - if (st_pre.mot[MOTOR_3].accumulator_correction_flag == true) { - st_pre.mot[MOTOR_3].accumulator_correction_flag = false; - st_run.mot[MOTOR_3].substep_accumulator *= st_pre.mot[MOTOR_3].accumulator_correction; - } - if (st_pre.mot[MOTOR_3].direction != st_pre.mot[MOTOR_3].prev_direction) { - st_pre.mot[MOTOR_3].prev_direction = st_pre.mot[MOTOR_3].direction; - st_run.mot[MOTOR_3].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_3].substep_accumulator); - if (st_pre.mot[MOTOR_3].direction == DIRECTION_CW) - PORT_MOTOR_3_VPORT.OUT &= ~DIRECTION_BIT_bm; else - PORT_MOTOR_3_VPORT.OUT |= DIRECTION_BIT_bm; - } - SET_ENCODER_STEP_SIGN(MOTOR_3, st_pre.mot[MOTOR_3].step_sign); - if (st_cfg.mot[MOTOR_3].power_mode != MOTOR_DISABLED) { - PORT_MOTOR_3_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_3].power_state = MOTOR_POWER_TIMEOUT_START; - } - } else { - if (st_cfg.mot[MOTOR_3].power_mode == MOTOR_POWERED_IN_CYCLE) { - PORT_MOTOR_3_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_3].power_state = MOTOR_POWER_TIMEOUT_START; - } - } - ACCUMULATE_ENCODER(MOTOR_3); + if ((st_run.mot[MOTOR_3].substep_increment = st_pre.mot[MOTOR_3].substep_increment) != 0) { + if (st_pre.mot[MOTOR_3].accumulator_correction_flag == true) { + st_pre.mot[MOTOR_3].accumulator_correction_flag = false; + st_run.mot[MOTOR_3].substep_accumulator *= st_pre.mot[MOTOR_3].accumulator_correction; + } + + if (st_pre.mot[MOTOR_3].direction != st_pre.mot[MOTOR_3].prev_direction) { + st_pre.mot[MOTOR_3].prev_direction = st_pre.mot[MOTOR_3].direction; + st_run.mot[MOTOR_3].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_3].substep_accumulator); + if (st_pre.mot[MOTOR_3].direction == DIRECTION_CW) + PORT_MOTOR_3_VPORT.OUT &= ~DIRECTION_BIT_bm; + else PORT_MOTOR_3_VPORT.OUT |= DIRECTION_BIT_bm; + } + + SET_ENCODER_STEP_SIGN(MOTOR_3, st_pre.mot[MOTOR_3].step_sign); + + if (st_cfg.mot[MOTOR_3].power_mode != MOTOR_DISABLED) { + PORT_MOTOR_3_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_3].power_state = MOTOR_POWER_TIMEOUT_START; + } + + } else if (st_cfg.mot[MOTOR_3].power_mode == MOTOR_POWERED_IN_CYCLE) { + PORT_MOTOR_3_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_3].power_state = MOTOR_POWER_TIMEOUT_START; + } + + ACCUMULATE_ENCODER(MOTOR_3); #endif + #if (MOTORS >= 4) //**** MOTOR_4 LOAD **** - if ((st_run.mot[MOTOR_4].substep_increment = st_pre.mot[MOTOR_4].substep_increment) != 0) { - if (st_pre.mot[MOTOR_4].accumulator_correction_flag == true) { - st_pre.mot[MOTOR_4].accumulator_correction_flag = false; - st_run.mot[MOTOR_4].substep_accumulator *= st_pre.mot[MOTOR_4].accumulator_correction; - } - if (st_pre.mot[MOTOR_4].direction != st_pre.mot[MOTOR_4].prev_direction) { - st_pre.mot[MOTOR_4].prev_direction = st_pre.mot[MOTOR_4].direction; - st_run.mot[MOTOR_4].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_4].substep_accumulator); - if (st_pre.mot[MOTOR_4].direction == DIRECTION_CW) - PORT_MOTOR_4_VPORT.OUT &= ~DIRECTION_BIT_bm; else - PORT_MOTOR_4_VPORT.OUT |= DIRECTION_BIT_bm; - } - SET_ENCODER_STEP_SIGN(MOTOR_4, st_pre.mot[MOTOR_4].step_sign); - if (st_cfg.mot[MOTOR_4].power_mode != MOTOR_DISABLED) { - PORT_MOTOR_4_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_4].power_state = MOTOR_POWER_TIMEOUT_START; - } - } else { - if (st_cfg.mot[MOTOR_4].power_mode == MOTOR_POWERED_IN_CYCLE) { - PORT_MOTOR_4_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_4].power_state = MOTOR_POWER_TIMEOUT_START; - } - } - ACCUMULATE_ENCODER(MOTOR_4); + if ((st_run.mot[MOTOR_4].substep_increment = st_pre.mot[MOTOR_4].substep_increment) != 0) { + if (st_pre.mot[MOTOR_4].accumulator_correction_flag == true) { + st_pre.mot[MOTOR_4].accumulator_correction_flag = false; + st_run.mot[MOTOR_4].substep_accumulator *= st_pre.mot[MOTOR_4].accumulator_correction; + } + + if (st_pre.mot[MOTOR_4].direction != st_pre.mot[MOTOR_4].prev_direction) { + st_pre.mot[MOTOR_4].prev_direction = st_pre.mot[MOTOR_4].direction; + st_run.mot[MOTOR_4].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_4].substep_accumulator); + + if (st_pre.mot[MOTOR_4].direction == DIRECTION_CW) + PORT_MOTOR_4_VPORT.OUT &= ~DIRECTION_BIT_bm; + else PORT_MOTOR_4_VPORT.OUT |= DIRECTION_BIT_bm; + } + + SET_ENCODER_STEP_SIGN(MOTOR_4, st_pre.mot[MOTOR_4].step_sign); + + if (st_cfg.mot[MOTOR_4].power_mode != MOTOR_DISABLED) { + PORT_MOTOR_4_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_4].power_state = MOTOR_POWER_TIMEOUT_START; + } + + } else if (st_cfg.mot[MOTOR_4].power_mode == MOTOR_POWERED_IN_CYCLE) { + PORT_MOTOR_4_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_4].power_state = MOTOR_POWER_TIMEOUT_START; + } + + ACCUMULATE_ENCODER(MOTOR_4); #endif + #if (MOTORS >= 5) //**** MOTOR_5 LOAD **** - if ((st_run.mot[MOTOR_5].substep_increment = st_pre.mot[MOTOR_5].substep_increment) != 0) { - if (st_pre.mot[MOTOR_5].accumulator_correction_flag == true) { - st_pre.mot[MOTOR_5].accumulator_correction_flag = false; - st_run.mot[MOTOR_5].substep_accumulator *= st_pre.mot[MOTOR_5].accumulator_correction; - } - if (st_pre.mot[MOTOR_5].direction != st_pre.mot[MOTOR_5].prev_direction) { - st_pre.mot[MOTOR_5].prev_direction = st_pre.mot[MOTOR_5].direction; - st_run.mot[MOTOR_5].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_5].substep_accumulator); - if (st_pre.mot[MOTOR_5].direction == DIRECTION_CW) - PORT_MOTOR_5_VPORT.OUT &= ~DIRECTION_BIT_bm; else - PORT_MOTOR_5_VPORT.OUT |= DIRECTION_BIT_bm; - } - PORT_MOTOR_5_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_5].power_state = MOTOR_POWER_TIMEOUT_START; - SET_ENCODER_STEP_SIGN(MOTOR_5, st_pre.mot[MOTOR_5].step_sign); - } else { - if (st_cfg.mot[MOTOR_5].power_mode == MOTOR_POWERED_IN_CYCLE) { - PORT_MOTOR_5_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_5].power_state = MOTOR_POWER_TIMEOUT_START; - } - } - ACCUMULATE_ENCODER(MOTOR_5); + if ((st_run.mot[MOTOR_5].substep_increment = st_pre.mot[MOTOR_5].substep_increment) != 0) { + if (st_pre.mot[MOTOR_5].accumulator_correction_flag == true) { + st_pre.mot[MOTOR_5].accumulator_correction_flag = false; + st_run.mot[MOTOR_5].substep_accumulator *= st_pre.mot[MOTOR_5].accumulator_correction; + } + + if (st_pre.mot[MOTOR_5].direction != st_pre.mot[MOTOR_5].prev_direction) { + st_pre.mot[MOTOR_5].prev_direction = st_pre.mot[MOTOR_5].direction; + st_run.mot[MOTOR_5].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_5].substep_accumulator); + + if (st_pre.mot[MOTOR_5].direction == DIRECTION_CW) + PORT_MOTOR_5_VPORT.OUT &= ~DIRECTION_BIT_bm; + else PORT_MOTOR_5_VPORT.OUT |= DIRECTION_BIT_bm; + } + + PORT_MOTOR_5_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_5].power_state = MOTOR_POWER_TIMEOUT_START; + SET_ENCODER_STEP_SIGN(MOTOR_5, st_pre.mot[MOTOR_5].step_sign); + + } else if (st_cfg.mot[MOTOR_5].power_mode == MOTOR_POWERED_IN_CYCLE) { + PORT_MOTOR_5_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_5].power_state = MOTOR_POWER_TIMEOUT_START; + } + + ACCUMULATE_ENCODER(MOTOR_5); #endif + #if (MOTORS >= 6) //**** MOTOR_6 LOAD **** - if ((st_run.mot[MOTOR_6].substep_increment = st_pre.mot[MOTOR_6].substep_increment) != 0) { - if (st_pre.mot[MOTOR_6].accumulator_correction_flag == true) { - st_pre.mot[MOTOR_6].accumulator_correction_flag = false; - st_run.mot[MOTOR_6].substep_accumulator *= st_pre.mot[MOTOR_6].accumulator_correction; - } - if (st_pre.mot[MOTOR_6].direction != st_pre.mot[MOTOR_6].prev_direction) { - st_pre.mot[MOTOR_6].prev_direction = st_pre.mot[MOTOR_6].direction; - st_run.mot[MOTOR_6].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_6].substep_accumulator); - if (st_pre.mot[MOTOR_6].direction == DIRECTION_CW) - PORT_MOTOR_6_VPORT.OUT &= ~DIRECTION_BIT_bm; else - PORT_MOTOR_6_VPORT.OUT |= DIRECTION_BIT_bm; - } - PORT_MOTOR_6_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_6].power_state = MOTOR_POWER_TIMEOUT_START; - SET_ENCODER_STEP_SIGN(MOTOR_6, st_pre.mot[MOTOR_6].step_sign); - } else { - if (st_cfg.mot[MOTOR_6].power_mode == MOTOR_POWERED_IN_CYCLE) { - PORT_MOTOR_6_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; - st_run.mot[MOTOR_6].power_state = MOTOR_POWER_TIMEOUT_START; - } - } - ACCUMULATE_ENCODER(MOTOR_6); + if ((st_run.mot[MOTOR_6].substep_increment = st_pre.mot[MOTOR_6].substep_increment) != 0) { + if (st_pre.mot[MOTOR_6].accumulator_correction_flag == true) { + st_pre.mot[MOTOR_6].accumulator_correction_flag = false; + st_run.mot[MOTOR_6].substep_accumulator *= st_pre.mot[MOTOR_6].accumulator_correction; + } + + if (st_pre.mot[MOTOR_6].direction != st_pre.mot[MOTOR_6].prev_direction) { + st_pre.mot[MOTOR_6].prev_direction = st_pre.mot[MOTOR_6].direction; + st_run.mot[MOTOR_6].substep_accumulator = -(st_run.dda_ticks_X_substeps + st_run.mot[MOTOR_6].substep_accumulator); + if (st_pre.mot[MOTOR_6].direction == DIRECTION_CW) + PORT_MOTOR_6_VPORT.OUT &= ~DIRECTION_BIT_bm; + else PORT_MOTOR_6_VPORT.OUT |= DIRECTION_BIT_bm; + } + + PORT_MOTOR_6_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_6].power_state = MOTOR_POWER_TIMEOUT_START; + SET_ENCODER_STEP_SIGN(MOTOR_6, st_pre.mot[MOTOR_6].step_sign); + + } else if (st_cfg.mot[MOTOR_6].power_mode == MOTOR_POWERED_IN_CYCLE) { + PORT_MOTOR_6_VPORT.OUT &= ~MOTOR_ENABLE_BIT_bm; + st_run.mot[MOTOR_6].power_state = MOTOR_POWER_TIMEOUT_START; + } + + ACCUMULATE_ENCODER(MOTOR_6); #endif - //**** do this last **** - TIMER_DDA.PER = st_pre.dda_period; - TIMER_DDA.CTRLA = STEP_TIMER_ENABLE; // enable the DDA timer + //**** do this last **** + TIMER_DDA.PER = st_pre.dda_period; + TIMER_DDA.CTRLA = STEP_TIMER_ENABLE; // enable the DDA timer + } else if (st_pre.move_type == MOVE_TYPE_DWELL) { // handle dwells - } else if (st_pre.move_type == MOVE_TYPE_DWELL) { - st_run.dda_ticks_downcount = st_pre.dda_ticks; - TIMER_DWELL.PER = st_pre.dda_period; // load dwell timer period - TIMER_DWELL.CTRLA = STEP_TIMER_ENABLE; // enable the dwell timer + st_run.dda_ticks_downcount = st_pre.dda_ticks; + TIMER_DWELL.PER = st_pre.dda_period; // load dwell timer period + TIMER_DWELL.CTRLA = STEP_TIMER_ENABLE; // enable the dwell timer + } else if (st_pre.move_type == MOVE_TYPE_COMMAND) // handle synchronous commands - } else if (st_pre.move_type == MOVE_TYPE_COMMAND) { - mp_runtime_command(st_pre.bf); - } + mp_runtime_command(st_pre.bf); - // all other cases drop to here (e.g. Null moves after Mcodes skip to here) - st_pre.move_type = MOVE_TYPE_0; - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_EXEC; // we are done with the prep buffer - flip the flag back - st_request_exec_move(); // exec and prep next move + // all other cases drop to here (e.g. Null moves after Mcodes skip to here) + st_pre.move_type = MOVE_TYPE_0; + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_EXEC; // we are done with the prep buffer - flip the flag back + st_request_exec_move(); // exec and prep next move } + /*********************************************************************************** * st_prep_line() - Prepare the next move for the loader * @@ -654,215 +648,163 @@ static void _load_move() * 100% accurate this will affect the move velocity, but not the distance traveled. * * NOTE: Many of the expressions are sensitive to casting and execution order to avoid long-term - * accuracy errors due to floating point round off. One earlier failed attempt was: - * dda_ticks_X_substeps = (int32_t)((microseconds/1000000) * f_dda * dda_substeps); + * accuracy errors due to floating point round off. One earlier failed attempt was: + * dda_ticks_X_substeps = (int32_t)((microseconds / 1000000) * f_dda * dda_substeps); */ - -stat_t st_prep_line(float travel_steps[], float following_error[], float segment_time) -{ - // trap conditions that would prevent queueing the line - if (st_pre.buffer_state != PREP_BUFFER_OWNED_BY_EXEC) { - return cm_hard_alarm(STAT_INTERNAL_ERROR); - } else if (isinf(segment_time)) { return cm_hard_alarm(STAT_PREP_LINE_MOVE_TIME_IS_INFINITE); // never supposed to happen - } else if (isnan(segment_time)) { return cm_hard_alarm(STAT_PREP_LINE_MOVE_TIME_IS_NAN); // never supposed to happen - } else if (segment_time < EPSILON) { return STAT_MINIMUM_TIME_MOVE; +stat_t st_prep_line(float travel_steps[], float following_error[], float segment_time) { + // trap conditions that would prevent queueing the line + if (st_pre.buffer_state != PREP_BUFFER_OWNED_BY_EXEC) return cm_hard_alarm(STAT_INTERNAL_ERROR); + else if (isinf(segment_time)) return cm_hard_alarm(STAT_PREP_LINE_MOVE_TIME_IS_INFINITE); // never supposed to happen + else if (isnan(segment_time)) return cm_hard_alarm(STAT_PREP_LINE_MOVE_TIME_IS_NAN); // never supposed to happen + else if (segment_time < EPSILON) return STAT_MINIMUM_TIME_MOVE; + + // setup segment parameters + // - dda_ticks is the integer number of DDA clock ticks needed to play out the segment + // - ticks_X_substeps is the maximum depth of the DDA accumulator (as a negative number) + st_pre.dda_period = _f_to_period(FREQUENCY_DDA); + st_pre.dda_ticks = (int32_t)(segment_time * 60 * FREQUENCY_DDA);// NB: converts minutes to seconds + st_pre.dda_ticks_X_substeps = st_pre.dda_ticks * DDA_SUBSTEPS; + + // setup motor parameters + float correction_steps; + for (uint8_t motor = 0; motor < MOTORS; motor++) { + // Skip this motor if there are no new steps. Leave all other values intact. + if (fp_ZERO(travel_steps[motor])) { + st_pre.mot[motor].substep_increment = 0; + continue; } - // setup segment parameters - // - dda_ticks is the integer number of DDA clock ticks needed to play out the segment - // - ticks_X_substeps is the maximum depth of the DDA accumulator (as a negative number) - st_pre.dda_period = _f_to_period(FREQUENCY_DDA); - st_pre.dda_ticks = (int32_t)(segment_time * 60 * FREQUENCY_DDA);// NB: converts minutes to seconds - st_pre.dda_ticks_X_substeps = st_pre.dda_ticks * DDA_SUBSTEPS; + // Setup the direction, compensating for polarity. + // Set the step_sign which is used by the stepper ISR to accumulate step position + if (travel_steps[motor] >= 0) { // positive direction + st_pre.mot[motor].direction = DIRECTION_CW ^ st_cfg.mot[motor].polarity; + st_pre.mot[motor].step_sign = 1; - // setup motor parameters - - float correction_steps; - for (uint8_t motor=0; motor 0.0000001) { // highly tuned FP != compare + if (fp_NOT_ZERO(st_pre.mot[motor].prev_segment_time)) { // special case to skip first move + st_pre.mot[motor].accumulator_correction_flag = true; + st_pre.mot[motor].accumulator_correction = segment_time / st_pre.mot[motor].prev_segment_time; + } - // Setup the direction, compensating for polarity. - // Set the step_sign which is used by the stepper ISR to accumulate step position + st_pre.mot[motor].prev_segment_time = segment_time; + } - if (travel_steps[motor] >= 0) { // positive direction - st_pre.mot[motor].direction = DIRECTION_CW ^ st_cfg.mot[motor].polarity; - st_pre.mot[motor].step_sign = 1; - } else { - st_pre.mot[motor].direction = DIRECTION_CCW ^ st_cfg.mot[motor].polarity; - st_pre.mot[motor].step_sign = -1; - } +#ifdef __STEP_CORRECTION + // 'Nudge' correction strategy. Inject a single, scaled correction value then hold off + if ((--st_pre.mot[motor].correction_holdoff < 0) && + (fabs(following_error[motor]) > STEP_CORRECTION_THRESHOLD)) { - // Detect segment time changes and setup the accumulator correction factor and flag. - // Putting this here computes the correct factor even if the motor was dormant for some - // number of previous moves. Correction is computed based on the last segment time actually used. + st_pre.mot[motor].correction_holdoff = STEP_CORRECTION_HOLDOFF; + correction_steps = following_error[motor] * STEP_CORRECTION_FACTOR; - if (fabs(segment_time - st_pre.mot[motor].prev_segment_time) > 0.0000001) { // highly tuned FP != compare - if (fp_NOT_ZERO(st_pre.mot[motor].prev_segment_time)) { // special case to skip first move - st_pre.mot[motor].accumulator_correction_flag = true; - st_pre.mot[motor].accumulator_correction = segment_time / st_pre.mot[motor].prev_segment_time; - } - st_pre.mot[motor].prev_segment_time = segment_time; - } + if (correction_steps > 0) + correction_steps = min3(correction_steps, fabs(travel_steps[motor]), STEP_CORRECTION_MAX); + else correction_steps = max3(correction_steps, -fabs(travel_steps[motor]), -STEP_CORRECTION_MAX); -#ifdef __STEP_CORRECTION - // 'Nudge' correction strategy. Inject a single, scaled correction value then hold off - - if ((--st_pre.mot[motor].correction_holdoff < 0) && - (fabs(following_error[motor]) > STEP_CORRECTION_THRESHOLD)) { - - st_pre.mot[motor].correction_holdoff = STEP_CORRECTION_HOLDOFF; - correction_steps = following_error[motor] * STEP_CORRECTION_FACTOR; - - if (correction_steps > 0) { - correction_steps = min3(correction_steps, fabs(travel_steps[motor]), STEP_CORRECTION_MAX); - } else { - correction_steps = max3(correction_steps, -fabs(travel_steps[motor]), -STEP_CORRECTION_MAX); - } - st_pre.mot[motor].corrected_steps += correction_steps; - travel_steps[motor] -= correction_steps; - } + st_pre.mot[motor].corrected_steps += correction_steps; + travel_steps[motor] -= correction_steps; + } #endif - // Compute substeb increment. The accumulator must be *exactly* the incoming - // fractional steps times the substep multiplier or positional drift will occur. - // Rounding is performed to eliminate a negative bias in the uint32 conversion - // that results in long-term negative drift. (fabs/round order doesn't matter) - st_pre.mot[motor].substep_increment = round(fabs(travel_steps[motor] * DDA_SUBSTEPS)); - } - st_pre.move_type = MOVE_TYPE_ALINE; - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // signal that prep buffer is ready - return STAT_OK; -} + // Compute substeb increment. The accumulator must be *exactly* the incoming + // fractional steps times the substep multiplier or positional drift will occur. + // Rounding is performed to eliminate a negative bias in the uint32 conversion + // that results in long-term negative drift. (fabs/round order doesn't matter) + st_pre.mot[motor].substep_increment = round(fabs(travel_steps[motor] * DDA_SUBSTEPS)); + } -/* - * st_prep_null() - Keeps the loader happy. Otherwise performs no action - */ + st_pre.move_type = MOVE_TYPE_ALINE; + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // signal that prep buffer is ready -void st_prep_null() -{ - st_pre.move_type = MOVE_TYPE_0; - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_EXEC; // signal that prep buffer is empty + return STAT_OK; } -/* - * st_prep_command() - Stage command to execution - */ -void st_prep_command(void *bf) -{ - st_pre.move_type = MOVE_TYPE_COMMAND; - st_pre.bf = (mpBuf_t *)bf; - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // signal that prep buffer is ready +/// Keeps the loader happy. Otherwise performs no action +void st_prep_null() { + st_pre.move_type = MOVE_TYPE_0; + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_EXEC; // signal that prep buffer is empty } -/* - * st_prep_dwell() - Add a dwell to the move buffer - */ -void st_prep_dwell(float microseconds) -{ - st_pre.move_type = MOVE_TYPE_DWELL; - st_pre.dda_period = _f_to_period(FREQUENCY_DWELL); - st_pre.dda_ticks = (uint32_t)((microseconds/1000000) * FREQUENCY_DWELL); - st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // signal that prep buffer is ready +/// Stage command to execution +void st_prep_command(void *bf) { + st_pre.move_type = MOVE_TYPE_COMMAND; + st_pre.bf = (mpBuf_t *)bf; + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // signal that prep buffer is ready } -/* - * _set_hw_microsteps() - set microsteps in hardware - * - * For now the microsteps is the same as the microsteps (1,2,4,8) - * This may change if microstep morphing is implemented. - */ -static void _set_hw_microsteps(const uint8_t motor, const uint8_t microsteps) -{ - if (microsteps == 8) { - hw.st_port[motor]->OUTSET = MICROSTEP_BIT_0_bm; - hw.st_port[motor]->OUTSET = MICROSTEP_BIT_1_bm; - } else if (microsteps == 4) { - hw.st_port[motor]->OUTCLR = MICROSTEP_BIT_0_bm; - hw.st_port[motor]->OUTSET = MICROSTEP_BIT_1_bm; - } else if (microsteps == 2) { - hw.st_port[motor]->OUTSET = MICROSTEP_BIT_0_bm; - hw.st_port[motor]->OUTCLR = MICROSTEP_BIT_1_bm; - } else if (microsteps == 1) { - hw.st_port[motor]->OUTCLR = MICROSTEP_BIT_0_bm; - hw.st_port[motor]->OUTCLR = MICROSTEP_BIT_1_bm; - } +/// Add a dwell to the move buffer +void st_prep_dwell(float microseconds) { + st_pre.move_type = MOVE_TYPE_DWELL; + st_pre.dda_period = _f_to_period(FREQUENCY_DWELL); + st_pre.dda_ticks = (uint32_t)(microseconds / 1000000 * FREQUENCY_DWELL); + st_pre.buffer_state = PREP_BUFFER_OWNED_BY_LOADER; // signal that prep buffer is ready } -/*********************************************************************************** - * CONFIGURATION AND INTERFACE FUNCTIONS - * Functions to get and set variables from the cfgArray table - ***********************************************************************************/ +/// Helper to return motor number as an index +static int8_t _get_motor(const nvObj_t *nv) { + return nv->group[0] ? nv->group[0] : nv->token[0] - 0x31; +} -/* HELPERS - * _get_motor() - helper to return motor number as an index - */ -static int8_t _get_motor(const nvObj_t *nv) -{ - return (nv->group[0] ? nv->group[0] : nv->token[0] - 0x31); +/// This function will need to be rethought if microstep morphing is implemented +static void _set_motor_steps_per_unit(nvObj_t *nv) { + uint8_t m = _get_motor(nv); + st_cfg.mot[m].steps_per_unit = (360 * st_cfg.mot[m].microsteps) / (st_cfg.mot[m].travel_rev * st_cfg.mot[m].step_angle); + st_reset(); } -/* - * _set_motor_steps_per_unit() - what it says - * This function will need to be rethought if microstep morphing is implemented - */ -static void _set_motor_steps_per_unit(nvObj_t *nv) -{ - uint8_t m = _get_motor(nv); - st_cfg.mot[m].steps_per_unit = (360 * st_cfg.mot[m].microsteps) / (st_cfg.mot[m].travel_rev * st_cfg.mot[m].step_angle); - st_reset(); +/// Set motor step angle +stat_t st_set_sa(nvObj_t *nv) { + set_flt(nv); + _set_motor_steps_per_unit(nv); + + return STAT_OK; } -/* PER-MOTOR FUNCTIONS - * st_set_sa() - set motor step angle - * st_set_tr() - set travel per motor revolution - * st_set_mi() - set motor microsteps - * st_set_pm() - set motor power mode - * st_set_pl() - set motor power level - */ -stat_t st_set_sa(nvObj_t *nv) // motor step angle -{ - set_flt(nv); - _set_motor_steps_per_unit(nv); - return(STAT_OK); -} +/// Set motor travel per revolution +stat_t st_set_tr(nvObj_t *nv) { + set_flu(nv); + _set_motor_steps_per_unit(nv); -stat_t st_set_tr(nvObj_t *nv) // motor travel per revolution -{ - set_flu(nv); - _set_motor_steps_per_unit(nv); - return(STAT_OK); + return STAT_OK; } -stat_t st_set_mi(nvObj_t *nv) // motor microsteps -{ - uint32_t mi = (uint32_t)nv->value; - if ((mi != 1) && (mi != 2) && (mi != 4) && (mi != 8)) { - nv_add_conditional_message((const char_t *)"*** WARNING *** Setting non-standard microstep value"); - } - set_int(nv); // set it anyway, even if it's unsupported. It could also be > 255 - _set_motor_steps_per_unit(nv); - _set_hw_microsteps(_get_motor(nv), (uint8_t)nv->value); - return STAT_OK; + +// Set motor microsteps +stat_t st_set_mi(nvObj_t *nv) { + set_int(nv); + _set_motor_steps_per_unit(nv); + + return STAT_OK; } -stat_t st_set_pm(nvObj_t *nv) // motor power mode -{ - if ((uint8_t)nv->value >= MOTOR_POWER_MODE_MAX_VALUE) - return STAT_INPUT_VALUE_RANGE_ERROR; - set_ui8(nv); - return STAT_OK; - // NOTE: The motor power callback makes these settings take effect immediately + +// Set motor power mode +stat_t st_set_pm(nvObj_t *nv) { + // NOTE: The motor power callback makes these settings take effect immediately + if ((uint8_t)nv->value >= MOTOR_POWER_MODE_MAX_VALUE) + return STAT_INPUT_VALUE_RANGE_ERROR; + + set_ui8(nv); + + return STAT_OK; } + /* * st_set_pl() - set motor power level * @@ -870,77 +812,71 @@ stat_t st_set_pm(nvObj_t *nv) // motor power mode * This function sets both the scaled and dynamic power levels, and applies the * scaled value to the vref. */ -stat_t st_set_pl(nvObj_t *nv) // motor power level -{ - return(STAT_OK); +stat_t st_set_pl(nvObj_t *nv) { + return STAT_OK; } -/* - * st_get_pwr() - get motor enable power state - */ -stat_t st_get_pwr(nvObj_t *nv) -{ - nv->value = _motor_is_enabled(_get_motor(nv)); - nv->valuetype = TYPE_INTEGER; - return STAT_OK; + +/// get motor enable power state +stat_t st_get_pwr(nvObj_t *nv) { + nv->value = _motor_is_enabled(_get_motor(nv)); + nv->valuetype = TYPE_INTEGER; + + return STAT_OK; } + /* GLOBAL FUNCTIONS (SYSTEM LEVEL) - * - * st_set_mt() - set motor timeout in seconds - * st_set_md() - disable motor power - * st_set_me() - enable motor power - * * Calling me or md with 0 will enable or disable all motors * Setting a value of 0 will enable or disable all motors * Setting a value from 1 to MOTORS will enable or disable that motor only */ -stat_t st_set_mt(nvObj_t *nv) -{ - st_cfg.motor_power_timeout = min(MOTOR_TIMEOUT_SECONDS_MAX, max(nv->value, MOTOR_TIMEOUT_SECONDS_MIN)); - return STAT_OK; +/// Set motor timeout in seconds +stat_t st_set_mt(nvObj_t *nv) { + st_cfg.motor_power_timeout = min(MOTOR_TIMEOUT_SECONDS_MAX, max(nv->value, MOTOR_TIMEOUT_SECONDS_MIN)); + return STAT_OK; } -stat_t st_set_md(nvObj_t *nv) // Make sure this function is not part of initialization --> f00 -{ - if (((uint8_t)nv->value == 0) || (nv->valuetype == TYPE_0)) { - st_deenergize_motors(); - } else { - uint8_t motor = (uint8_t)nv->value; - if (motor > MOTORS) { - return STAT_INPUT_VALUE_RANGE_ERROR; - } - _deenergize_motor(motor-1); // adjust so that motor 1 is actually 0 (etc) - } - return STAT_OK; + +/// Disable motor power +stat_t st_set_md(nvObj_t *nv) { + // Make sure this function is not part of initialization --> f00 + if (((uint8_t)nv->value == 0) || (nv->valuetype == TYPE_0)) + st_deenergize_motors(); + + else { + uint8_t motor = (uint8_t)nv->value; + if (motor > MOTORS) return STAT_INPUT_VALUE_RANGE_ERROR; + _deenergize_motor(motor - 1); // adjust so that motor 1 is actually 0 (etc) + } + + return STAT_OK; } -stat_t st_set_me(nvObj_t *nv) // Make sure this function is not part of initialization --> f00 -{ - if (((uint8_t)nv->value == 0) || (nv->valuetype == TYPE_0)) { - st_energize_motors(); - } else { - uint8_t motor = (uint8_t)nv->value; - if (motor > MOTORS) { - return STAT_INPUT_VALUE_RANGE_ERROR; - } - _energize_motor(motor-1); // adjust so that motor 1 is actually 0 (etc) - } - return STAT_OK; + +/// enable motor power +stat_t st_set_me(nvObj_t *nv) { + // Make sure this function is not part of initialization --> f00 + if (((uint8_t)nv->value == 0) || (nv->valuetype == TYPE_0)) + st_energize_motors(); + + else { + uint8_t motor = (uint8_t)nv->value; + if (motor > MOTORS) return STAT_INPUT_VALUE_RANGE_ERROR; + _energize_motor(motor - 1); // adjust so that motor 1 is actually 0 (etc) + } + + return STAT_OK; } -/*********************************************************************************** - * TEXT MODE SUPPORT - * Functions to print variables from the cfgArray table - ***********************************************************************************/ #ifdef __TEXT_MODE static const char msg_units0[] PROGMEM = " in"; // used by generic print functions static const char msg_units1[] PROGMEM = " mm"; static const char msg_units2[] PROGMEM = " deg"; -static const char *const msg_units[] PROGMEM = { msg_units0, msg_units1, msg_units2 }; +static const char *const msg_units[] PROGMEM = {msg_units0, msg_units1, msg_units2}; #define DEGREE_INDEX 2 static const char fmt_me[] PROGMEM = "motors energized\n"; @@ -949,43 +885,43 @@ static const char fmt_mt[] PROGMEM = "[mt] motor idle timeout%14.2f Sec\n"; static const char fmt_0ma[] PROGMEM = "[%s%s] m%s map to axis%15d [0=X,1=Y,2=Z...]\n"; static const char fmt_0sa[] PROGMEM = "[%s%s] m%s step angle%20.3f%s\n"; static const char fmt_0tr[] PROGMEM = "[%s%s] m%s travel per revolution%10.4f%s\n"; -static const char fmt_0mi[] PROGMEM = "[%s%s] m%s microsteps%16d [1,2,4,8]\n"; +static const char fmt_0mi[] PROGMEM = "[%s%s] m%s microsteps%16d [1,2,4,8,16,32,64,128,256]\n"; static const char fmt_0po[] PROGMEM = "[%s%s] m%s polarity%18d [0=normal,1=reverse]\n"; static const char fmt_0pm[] PROGMEM = "[%s%s] m%s power management%10d [0=disabled,1=always on,2=in cycle,3=when moving]\n"; static const char fmt_0pl[] PROGMEM = "[%s%s] m%s motor power level%13.3f [0.000=minimum, 1.000=maximum]\n"; static const char fmt_pwr[] PROGMEM = "Motor %c power enabled state:%2.0f\n"; -void st_print_mt(nvObj_t *nv) { text_print_flt(nv, fmt_mt);} -void st_print_me(nvObj_t *nv) { text_print_nul(nv, fmt_me);} -void st_print_md(nvObj_t *nv) { text_print_nul(nv, fmt_md);} +void st_print_mt(nvObj_t *nv) {text_print_flt(nv, fmt_mt);} +void st_print_me(nvObj_t *nv) {text_print_nul(nv, fmt_me);} +void st_print_md(nvObj_t *nv) {text_print_nul(nv, fmt_md);} -static void _print_motor_ui8(nvObj_t *nv, const char *format) -{ - fprintf_P(stderr, format, nv->group, nv->token, nv->group, (uint8_t)nv->value); + +static void _print_motor_ui8(nvObj_t *nv, const char *format) { + fprintf_P(stderr, format, nv->group, nv->token, nv->group, (uint8_t)nv->value); } -static void _print_motor_flt_units(nvObj_t *nv, const char *format, uint8_t units) -{ - fprintf_P(stderr, format, nv->group, nv->token, nv->group, nv->value, GET_TEXT_ITEM(msg_units, units)); + +static void _print_motor_flt_units(nvObj_t *nv, const char *format, uint8_t units) { + fprintf_P(stderr, format, nv->group, nv->token, nv->group, nv->value, GET_TEXT_ITEM(msg_units, units)); } -static void _print_motor_flt(nvObj_t *nv, const char *format) -{ - fprintf_P(stderr, format, nv->group, nv->token, nv->group, nv->value); + +static void _print_motor_flt(nvObj_t *nv, const char *format) { + fprintf_P(stderr, format, nv->group, nv->token, nv->group, nv->value); } -static void _print_motor_pwr(nvObj_t *nv, const char *format) -{ - fprintf_P(stderr, format, nv->token[0], nv->value); +static void _print_motor_pwr(nvObj_t *nv, const char *format) { + fprintf_P(stderr, format, nv->token[0], nv->value); } -void st_print_ma(nvObj_t *nv) { _print_motor_ui8(nv, fmt_0ma);} -void st_print_sa(nvObj_t *nv) { _print_motor_flt_units(nv, fmt_0sa, DEGREE_INDEX);} -void st_print_tr(nvObj_t *nv) { _print_motor_flt_units(nv, fmt_0tr, cm_get_units_mode(MODEL));} -void st_print_mi(nvObj_t *nv) { _print_motor_ui8(nv, fmt_0mi);} -void st_print_po(nvObj_t *nv) { _print_motor_ui8(nv, fmt_0po);} -void st_print_pm(nvObj_t *nv) { _print_motor_ui8(nv, fmt_0pm);} -void st_print_pl(nvObj_t *nv) { _print_motor_flt(nv, fmt_0pl);} -void st_print_pwr(nvObj_t *nv){ _print_motor_pwr(nv, fmt_pwr);} + +void st_print_ma(nvObj_t *nv) {_print_motor_ui8(nv, fmt_0ma);} +void st_print_sa(nvObj_t *nv) {_print_motor_flt_units(nv, fmt_0sa, DEGREE_INDEX);} +void st_print_tr(nvObj_t *nv) {_print_motor_flt_units(nv, fmt_0tr, cm_get_units_mode(MODEL));} +void st_print_mi(nvObj_t *nv) {_print_motor_ui8(nv, fmt_0mi);} +void st_print_po(nvObj_t *nv) {_print_motor_ui8(nv, fmt_0po);} +void st_print_pm(nvObj_t *nv) {_print_motor_ui8(nv, fmt_0pm);} +void st_print_pl(nvObj_t *nv) {_print_motor_flt(nv, fmt_0pl);} +void st_print_pwr(nvObj_t *nv){_print_motor_pwr(nv, fmt_pwr);} #endif // __TEXT_MODE diff --git a/src/stepper.h b/src/stepper.h index fe913e6..f388c44 100644 --- a/src/stepper.h +++ b/src/stepper.h @@ -67,56 +67,58 @@ * Also, all moves are loaded from the DDA interrupt level (HI), avoiding the need * for mutual exclusion locking or volatiles (which slow things down). */ + /* - **** Move generation overview and timing illustration **** - * - * This ASCII art illustrates a 4 segment move to show stepper sequencing timing. - * - * LOAD/STEP (~5000uSec) [L1][segment1][L2][segment2][L3][segment3][L4][segment4][Lb1] - * PREP (100 uSec) [P1] [P2] [P3] [P4] [Pb1] - * EXEC (400 uSec) [EXEC1] [EXEC2] [EXEC3] [EXEC4] [EXECb1] - * PLAN (<4ms) [planmoveA][plan move B][plan move C][plan move D][plan move E] etc. - * - * The move begins with the planner PLANning move A [planmoveA]. When this is done the - * computations for the first segment of move A's S curve are performed by the planner - * runtime, EXEC1. The runtime computes the number of segments and the segment-by-segment - * accelerations and decelerations for the move. Each call to EXEC generates the values - * for the next segment to be run. Once the move is running EXEC is executed as a - * callback from the step loader. - * - * When the runtime calculations are done EXEC calls the segment PREParation function [P1]. - * PREP turns the EXEC results into values needed for the loader and does some encoder work. - * The combined exec and prep take about 400 uSec. - * - * PREP takes care of heavy numerics and other cycle-intesive operations so the step loader - * L1 can run as fast as possible. The time budget for LOAD is about 10 uSec. In the diagram, - * when P1 is done segment 1 is loaded into the stepper runtime [L1] - * - * Once the segment is loaded it will pulse out steps for the duration of the segment. - * Segment timing can vary, but segments take around 5 Msec to pulse out, which is 250 DDA - * ticks at a 50 KHz step clock. - * - * Now the move is pulsing out segment 1 (at HI interrupt level). Once the L1 loader is - * finished it invokes the exec function for the next segment (at LO interrupt level). - * [EXEC2] and [P2] compute and prepare the segment 2 for the loader so it can be loaded - * as soon as segment 1 is complete [L2]. When move A is done EXEC pulls the next move - * (moveB) from the planner queue, The process repeats until there are no more segments or moves. - * - * While all this is happening subsequent moves (B, C, and D) are being planned in background. - * As long as a move takes less than the segment times (5ms x N) the timing budget is satisfied, - * - * A few things worth noting: - * - This scheme uses 2 interrupt levels and background, for 3 levels of execution: - * - STEP pulsing and LOADs occur at HI interrupt level - * - EXEC and PREP occur at LO interrupt level (leaving MED int level for serial IO) - * - move PLANning occurs in background and is managed by the controller - * - * - Because of the way the timing is laid out there is no contention for resources between - * the STEP, LOAD, EXEC, and PREP phases. PLANing is similarly isolated. Very few volatiles - * or mutexes are needed, which makes the code simpler and faster. With the exception of - * the actual values used in step generation (which runs continuously) you can count on - * LOAD, EXEC, PREP and PLAN not stepping on each other's variables. - */ +**** Move generation overview and timing illustration **** +* +* This ASCII art illustrates a 4 segment move to show stepper sequencing timing. +* +* LOAD/STEP (~5000uSec) [L1][segment1][L2][segment2][L3][segment3][L4][segment4][Lb1] +* PREP (100 uSec) [P1] [P2] [P3] [P4] [Pb1] +* EXEC (400 uSec) [EXEC1] [EXEC2] [EXEC3] [EXEC4] [EXECb1] +* PLAN (<4ms) [planmoveA][plan move B][plan move C][plan move D][plan move E] etc. +* +* The move begins with the planner PLANning move A [planmoveA]. When this is done the +* computations for the first segment of move A's S curve are performed by the planner +* runtime, EXEC1. The runtime computes the number of segments and the segment-by-segment +* accelerations and decelerations for the move. Each call to EXEC generates the values +* for the next segment to be run. Once the move is running EXEC is executed as a +* callback from the step loader. +* +* When the runtime calculations are done EXEC calls the segment PREParation function [P1]. +* PREP turns the EXEC results into values needed for the loader and does some encoder work. +* The combined exec and prep take about 400 uSec. +* +* PREP takes care of heavy numerics and other cycle-intesive operations so the step loader +* L1 can run as fast as possible. The time budget for LOAD is about 10 uSec. In the diagram, +* when P1 is done segment 1 is loaded into the stepper runtime [L1] +* +* Once the segment is loaded it will pulse out steps for the duration of the segment. +* Segment timing can vary, but segments take around 5 Msec to pulse out, which is 250 DDA +* ticks at a 50 KHz step clock. +* +* Now the move is pulsing out segment 1 (at HI interrupt level). Once the L1 loader is +* finished it invokes the exec function for the next segment (at LO interrupt level). +* [EXEC2] and [P2] compute and prepare the segment 2 for the loader so it can be loaded +* as soon as segment 1 is complete [L2]. When move A is done EXEC pulls the next move +* (moveB) from the planner queue, The process repeats until there are no more segments or moves. +* +* While all this is happening subsequent moves (B, C, and D) are being planned in background. +* As long as a move takes less than the segment times (5ms x N) the timing budget is satisfied, +* +* A few things worth noting: +* - This scheme uses 2 interrupt levels and background, for 3 levels of execution: +* - STEP pulsing and LOADs occur at HI interrupt level +* - EXEC and PREP occur at LO interrupt level (leaving MED int level for serial IO) +* - move PLANning occurs in background and is managed by the controller +* +* - Because of the way the timing is laid out there is no contention for resources between +* the STEP, LOAD, EXEC, and PREP phases. PLANing is similarly isolated. Very few volatiles +* or mutexes are needed, which makes the code simpler and faster. With the exception of +* the actual values used in step generation (which runs continuously) you can count on +* LOAD, EXEC, PREP and PLAN not stepping on each other's variables. +*/ + /**** Line planning and execution (in more detail) **** * * Move planning, execution and pulse generation takes place at 3 levels: @@ -145,7 +147,8 @@ * timer interrupts that generate the stepper pulses. This level also transfers new * stepper parameters once each pulse train ("segment") is complete ("load" and "run" stages). */ -/* What happens when the pulse generator is done with the current pulse train (segment) + +/* What happens when the pulse generator is done with the current pulse train (segment) * is a multi-stage "pull" queue that looks like this: * * As long as the steppers are running the sequence of events is: @@ -183,6 +186,7 @@ * invoked from the main loop by the software interrupt, and the stepper load is * invoked from the exec by another software interrupt. */ + /* Control flow can be a bit confusing. This is a typical sequence for planning * executing, and running an acceleration planned line: * @@ -229,6 +233,7 @@ * Note: For this to work you have to be really careful about what structures * are modified at what level, and use volatiles where necessary. */ + /* Partial steps and phase angle compensation * * The DDA accepts partial steps as input. Fractional steps are managed by the @@ -237,45 +242,43 @@ * be thought of as a phase angle value for the DDA accumulation. Each 360 * degrees of phase angle results in a step being generated. */ + #ifndef STEPPER_H_ONCE #define STEPPER_H_ONCE -/********************************* - * Stepper configs and constants * - *********************************/ -//See hardware.h for platform specific stepper definitions +// See hardware.h for platform specific stepper definitions enum prepBufferState { - PREP_BUFFER_OWNED_BY_LOADER = 0, // staging buffer is ready for load - PREP_BUFFER_OWNED_BY_EXEC // staging buffer is being loaded + PREP_BUFFER_OWNED_BY_LOADER = 0, // staging buffer is ready for load + PREP_BUFFER_OWNED_BY_EXEC // staging buffer is being loaded }; + // Currently there is no distinction between IDLE and OFF (DEENERGIZED) // In the future IDLE will be powered at a low, torque-maintaining current - -enum motorPowerState { // used w/start and stop flags to sequence motor power - MOTOR_OFF = 0, // motor is stopped and deenergized - MOTOR_IDLE, // motor is stopped and may be partially energized for torque maintenance - MOTOR_RUNNING, // motor is running (and fully energized) - MOTOR_POWER_TIMEOUT_START, // transitional state to start power-down timeout - MOTOR_POWER_TIMEOUT_COUNTDOWN // count down the time to de-energizing motors +enum motorPowerState { // used w/start and stop flags to sequence motor power + MOTOR_OFF = 0, // motor is stopped and deenergized + MOTOR_IDLE, // motor is stopped and may be partially energized for torque maintenance + MOTOR_RUNNING, // motor is running (and fully energized) + MOTOR_POWER_TIMEOUT_START, // transitional state to start power-down timeout + MOTOR_POWER_TIMEOUT_COUNTDOWN // count down the time to de-energizing motors }; + enum cmMotorPowerMode { - MOTOR_DISABLED = 0, // motor enable is deactivated - MOTOR_ALWAYS_POWERED, // motor is always powered while machine is ON - MOTOR_POWERED_IN_CYCLE, // motor fully powered during cycles, de-powered out of cycle - MOTOR_POWERED_ONLY_WHEN_MOVING, // motor only powered while moving - idles shortly after it's stopped - even in cycle -// MOTOR_POWER_REDUCED_WHEN_IDLE, // enable Vref current reduction for idle (FUTURE) -// MOTOR_ADAPTIVE_POWER // adjust motor current with velocity (FUTURE) - MOTOR_POWER_MODE_MAX_VALUE // for input range checking + MOTOR_DISABLED = 0, // motor enable is deactivated + MOTOR_ALWAYS_POWERED, // motor is always powered while machine is ON + MOTOR_POWERED_IN_CYCLE, // motor fully powered during cycles, de-powered out of cycle + MOTOR_POWERED_ONLY_WHEN_MOVING, // motor only powered while moving - idles shortly after it's stopped - even in cycle + MOTOR_POWER_MODE_MAX_VALUE // for input range checking }; + // Min/Max timeouts allowed for motor disable. Allow for inertial stop; must be non-zero -#define MOTOR_TIMEOUT_SECONDS_MIN (float)0.1 // seconds !!! SHOULD NEVER BE ZERO !!! +#define MOTOR_TIMEOUT_SECONDS_MIN (float)0.1 // seconds !!! SHOULD NEVER BE ZERO !!! #define MOTOR_TIMEOUT_SECONDS_MAX (float)4294967 // (4294967295/1000) -- for conversion to uint32_t -#define MOTOR_TIMEOUT_SECONDS (float)0.1 // seconds in DISABLE_AXIS_WHEN_IDLE mode -#define MOTOR_TIMEOUT_WHEN_MOVING (float)0.25 // timeout for a motor in _ONLY_WHEN_MOVING mode +#define MOTOR_TIMEOUT_SECONDS (float)0.1 // seconds in DISABLE_AXIS_WHEN_IDLE mode +#define MOTOR_TIMEOUT_WHEN_MOVING (float)0.25 // timeout for a motor in _ONLY_WHEN_MOVING mode /* DDA substepping * DDA Substepping is a fixed.point scheme to increase the resolution of the DDA pulse generation @@ -296,6 +299,7 @@ enum cmMotorPowerMode { */ #define DDA_SUBSTEPS ((MAX_LONG * 0.90) / (FREQUENCY_DDA * (NOM_SEGMENT_TIME * 60))) + /* Step correction settings * Step correction settings determine how the encoder error is fed back to correct position errors. * Since the following_error is running 2 segments behind the current segment you have to be careful @@ -305,10 +309,11 @@ enum cmMotorPowerMode { * and error will grow instead of shrink (or oscillate). */ #define STEP_CORRECTION_THRESHOLD (float)2.00 // magnitude of forwarding error to apply correction (in steps) -#define STEP_CORRECTION_FACTOR (float)0.25 // factor to apply to step correction for a single segment -#define STEP_CORRECTION_MAX (float)0.60 // max step correction allowed in a single segment -#define STEP_CORRECTION_HOLDOFF 5 // minimum number of segments to wait between error correction -#define STEP_INITIAL_DIRECTION DIRECTION_CW +#define STEP_CORRECTION_FACTOR (float)0.25 // factor to apply to step correction for a single segment +#define STEP_CORRECTION_MAX (float)0.60 // max step correction allowed in a single segment +#define STEP_CORRECTION_HOLDOFF 5 // minimum number of segments to wait between error correction +#define STEP_INITIAL_DIRECTION DIRECTION_CW + /* * Stepper control structures @@ -316,11 +321,11 @@ enum cmMotorPowerMode { * There are 5 main structures involved in stepper operations; * * data structure: found in: runs primarily at: - * mpBuffer planning buffers (bf) planner.c main loop - * mrRuntimeSingleton (mr) planner.c MED ISR - * stConfig (st_cfg) stepper.c write=bkgd, read=ISRs - * stPrepSingleton (st_pre) stepper.c MED ISR - * stRunSingleton (st_run) stepper.c HI ISR + * mpBuffer planning buffers (bf) planner.c main loop + * mrRuntimeSingleton (mr) planner.c MED ISR + * stConfig (st_cfg) stepper.c write=bkgd, read=ISRs + * stPrepSingleton (st_pre) stepper.c MED ISR + * stRunSingleton (st_run) stepper.c HI ISR * * Care has been taken to isolate actions on these structures to the execution level * in which they run and to use the minimum number of volatiles in these structures. @@ -328,84 +333,86 @@ enum cmMotorPowerMode { */ // Motor config structure - -typedef struct cfgMotor { // per-motor configs - // public - uint8_t motor_map; // map motor to axis - uint32_t microsteps; // microsteps to apply for each axis (ex: 8) - uint8_t polarity; // 0=normal polarity, 1=reverse motor direction - uint8_t power_mode; // See cmMotorPowerMode for enum - float power_level; // set 0.000 to 1.000 for PMW vref setting - float step_angle; // degrees per whole step (ex: 1.8) - float travel_rev; // mm or deg of travel per motor revolution - float steps_per_unit; // microsteps per mm (or degree) of travel - float units_per_step; // mm or degrees of travel per microstep - - // private - float power_level_scaled; // scaled to internal range - must be between 0 and 1 +typedef struct cfgMotor { // per-motor configs + // public + uint8_t motor_map; // map motor to axis + uint32_t microsteps; // microsteps to apply for each axis (ex: 8) + uint8_t polarity; // 0=normal polarity, 1=reverse motor direction + uint8_t power_mode; // See cmMotorPowerMode for enum + float power_level; // set 0.000 to 1.000 for PMW vref setting + float step_angle; // degrees per whole step (ex: 1.8) + float travel_rev; // mm or deg of travel per motor revolution + float steps_per_unit; // microsteps per mm (or degree) of travel + float units_per_step; // mm or degrees of travel per microstep + + // private + float power_level_scaled; // scaled to internal range - must be between 0 and 1 } cfgMotor_t; -typedef struct stConfig { // stepper configs - float motor_power_timeout; // seconds before setting motors to idle current (currently this is OFF) - cfgMotor_t mot[MOTORS]; // settings for motors 1-N + +typedef struct stConfig { // stepper configs + float motor_power_timeout; // seconds before setting motors to idle current (currently this is OFF) + cfgMotor_t mot[MOTORS]; // settings for motors 1-N } stConfig_t; -// Motor runtime structure. Used exclusively by step generation ISR (HI) -typedef struct stRunMotor { // one per controlled motor - uint32_t substep_increment; // total steps in axis times substeps factor - int32_t substep_accumulator; // DDA phase angle accumulator - uint8_t power_state; // state machine for managing motor power - uint32_t power_systick; // sys_tick for next motor power state transition +// Motor runtime structure. Used exclusively by step generation ISR (HI) +typedef struct stRunMotor { // one per controlled motor + uint32_t substep_increment; // total steps in axis times substeps factor + int32_t substep_accumulator; // DDA phase angle accumulator + uint8_t power_state; // state machine for managing motor power + uint32_t power_systick; // sys_tick for next motor power state transition } stRunMotor_t; -typedef struct stRunSingleton { // Stepper static values and axis parameters - uint16_t magic_start; // magic number to test memory integrity - uint32_t dda_ticks_downcount; // tick down-counter (unscaled) - uint32_t dda_ticks_X_substeps; // ticks multiplied by scaling factor - stRunMotor_t mot[MOTORS]; // runtime motor structures - uint16_t magic_end; + +typedef struct stRunSingleton { // Stepper static values and axis parameters + uint16_t magic_start; // magic number to test memory integrity + uint32_t dda_ticks_downcount; // tick down-counter (unscaled) + uint32_t dda_ticks_X_substeps; // ticks multiplied by scaling factor + stRunMotor_t mot[MOTORS]; // runtime motor structures + uint16_t magic_end; } stRunSingleton_t; + // Motor prep structure. Used by exec/prep ISR (MED) and read-only during load // Must be careful about volatiles in this one - typedef struct stPrepMotor { - uint32_t substep_increment; // total steps in axis times substep factor + uint32_t substep_increment; // total steps in axis times substep factor - // direction and direction change - int8_t direction; // travel direction corrected for polarity - uint8_t prev_direction; // travel direction from previous segment run for this motor - int8_t step_sign; // set to +1 or -1 for encoders + // direction and direction change + int8_t direction; // travel direction corrected for polarity + uint8_t prev_direction; // travel direction from previous segment run for this motor + int8_t step_sign; // set to +1 or -1 for encoders - // following error correction - int32_t correction_holdoff; // count down segments between corrections - float corrected_steps; // accumulated correction steps for the cycle (for diagnostic display only) + // following error correction + int32_t correction_holdoff; // count down segments between corrections + float corrected_steps; // accumulated correction steps for the cycle (for diagnostic display only) - // accumulator phase correction - float prev_segment_time; // segment time from previous segment run for this motor - float accumulator_correction; // factor for adjusting accumulator between segments - uint8_t accumulator_correction_flag;// signals accumulator needs correction + // accumulator phase correction + float prev_segment_time; // segment time from previous segment run for this motor + float accumulator_correction; // factor for adjusting accumulator between segments + uint8_t accumulator_correction_flag;// signals accumulator needs correction } stPrepMotor_t; + typedef struct stPrepSingleton { - uint16_t magic_start; // magic number to test memory integrity - volatile uint8_t buffer_state; // prep buffer state - owned by exec or loader - struct mpBuffer *bf; // static pointer to relevant buffer - uint8_t move_type; // move type - - uint16_t dda_period; // DDA or dwell clock period setting - uint32_t dda_ticks; // DDA or dwell ticks for the move - uint32_t dda_ticks_X_substeps; // DDA ticks scaled by substep factor - stPrepMotor_t mot[MOTORS]; // prep time motor structs - uint16_t magic_end; + uint16_t magic_start; // magic number to test memory integrity + volatile uint8_t buffer_state; // prep buffer state - owned by exec or loader + struct mpBuffer *bf; // static pointer to relevant buffer + uint8_t move_type; // move type + + uint16_t dda_period; // DDA or dwell clock period setting + uint32_t dda_ticks; // DDA or dwell ticks for the move + uint32_t dda_ticks_X_substeps; // DDA ticks scaled by substep factor + stPrepMotor_t mot[MOTORS]; // prep time motor structs + uint16_t magic_end; } stPrepSingleton_t; -extern stConfig_t st_cfg; // config struct is exposed. The rest are private -extern stPrepSingleton_t st_pre; // only used by config_app diagnostics -/**** FUNCTION PROTOTYPES ****/ +extern stConfig_t st_cfg; // config struct is exposed. The rest are private +extern stPrepSingleton_t st_pre; // only used by config_app diagnostics + void stepper_init(); void stepper_init_assertions(); @@ -441,32 +448,32 @@ stat_t st_set_me(nvObj_t *nv); #ifdef __TEXT_MODE - void st_print_ma(nvObj_t *nv); - void st_print_sa(nvObj_t *nv); - void st_print_tr(nvObj_t *nv); - void st_print_mi(nvObj_t *nv); - void st_print_po(nvObj_t *nv); - void st_print_pm(nvObj_t *nv); - void st_print_pl(nvObj_t *nv); - void st_print_pwr(nvObj_t *nv); - void st_print_mt(nvObj_t *nv); - void st_print_me(nvObj_t *nv); - void st_print_md(nvObj_t *nv); +void st_print_ma(nvObj_t *nv); +void st_print_sa(nvObj_t *nv); +void st_print_tr(nvObj_t *nv); +void st_print_mi(nvObj_t *nv); +void st_print_po(nvObj_t *nv); +void st_print_pm(nvObj_t *nv); +void st_print_pl(nvObj_t *nv); +void st_print_pwr(nvObj_t *nv); +void st_print_mt(nvObj_t *nv); +void st_print_me(nvObj_t *nv); +void st_print_md(nvObj_t *nv); #else - #define st_print_ma tx_print_stub - #define st_print_sa tx_print_stub - #define st_print_tr tx_print_stub - #define st_print_mi tx_print_stub - #define st_print_po tx_print_stub - #define st_print_pm tx_print_stub - #define st_print_pl tx_print_stub - #define st_print_pwr tx_print_stub - #define st_print_mt tx_print_stub - #define st_print_me tx_print_stub - #define st_print_md tx_print_stub +#define st_print_ma tx_print_stub +#define st_print_sa tx_print_stub +#define st_print_tr tx_print_stub +#define st_print_mi tx_print_stub +#define st_print_po tx_print_stub +#define st_print_pm tx_print_stub +#define st_print_pl tx_print_stub +#define st_print_pwr tx_print_stub +#define st_print_mt tx_print_stub +#define st_print_me tx_print_stub +#define st_print_md tx_print_stub #endif // __TEXT_MODE -#endif // End of include guard: STEPPER_H_ONCE +#endif // STEPPER_H_ONCE diff --git a/src/tinyg.h b/src/tinyg.h index 13b9244..99e69e1 100644 --- a/src/tinyg.h +++ b/src/tinyg.h @@ -165,7 +165,7 @@ char *get_status_message(stat_t status); // ritorno is a handy way to provide exception returns // It returns only if an error occurred. (ritorno is Italian for return) -#define ritorno(a) if((status_code=a) != STAT_OK) { return(status_code); } +#define ritorno(a) if((status_code=a) != STAT_OK) { return status_code; } // OS, communications and low-level status #define STAT_OK 0 // function completed OK -- 2.27.0