CMD(help, command_help, 0, 1, "Print this help screen")
CMD(reboot, command_reboot, 0, 0, "Reboot the controller")
CMD(jog, command_jog, 1, 4, "Jog")
+CMD(mreset, command_mreset, 1, 1, "Reset motor")
#define C_SWITCH_MODE_MIN SW_MODE_HOMING
#define C_SWITCH_MODE_MAX SW_MODE_DISABLED
+// Switch ISRs
+#define X_SWITCH_ISR_vect PORTA_INT0_vect
+#define Y_SWITCH_ISR_vect PORTD_INT0_vect
+#define Z_SWITCH_ISR_vect PORTE_INT0_vect
+#define A_SWITCH_ISR_vect PORTF_INT0_vect
+
+#define SWITCH_INTLVL PORT_INT0LVL_MED_gc
+
+// Timer for debouncing switches
+#define SW_LOCKOUT_TICKS 25 // 25=250ms. RTC ticks are ~10ms each
+#define SW_DEGLITCH_TICKS 3 // 3=30ms
+
// Machine settings
#define CHORDAL_TOLERANCE 0.01 // chordal accuracy for arc drawing
/// Shut down system if limit switch fired
static stat_t _limit_switch_handler() {
if (cm_get_machine_state() == MACHINE_ALARM) return STAT_NOOP;
- if (!get_limit_switch_thrown()) return STAT_NOOP;
+ if (!switch_get_limit_thrown()) return STAT_NOOP;
return cm_hard_alarm(STAT_LIMIT_SWITCH_HIT);
}
return _homing_error_exit(axis, STAT_HOMING_ERROR_TRAVEL_MIN_MAX_IDENTICAL);
// determine the switch setup and that config is OK
- hm.min_mode = get_switch_mode(MIN_SWITCH(axis));
- hm.max_mode = get_switch_mode(MAX_SWITCH(axis));
+ hm.min_mode = switch_get_mode(MIN_SWITCH(axis));
+ hm.max_mode = switch_get_mode(MAX_SWITCH(axis));
// one or the other must be homing
if (!((hm.min_mode & SW_HOMING_BIT) ^ (hm.max_mode & SW_HOMING_BIT)))
}
// if homing is disabled for the axis then skip to the next axis
- uint8_t sw_mode = get_switch_mode(hm.homing_switch);
+ uint8_t sw_mode = switch_get_mode(hm.homing_switch);
if (sw_mode != SW_MODE_HOMING && sw_mode != SW_MODE_HOMING_LIMIT)
return _set_homing_func(_homing_axis_start);
// disable the limit switch parameter if there is no limit switch
- if (get_switch_mode(hm.limit_switch) == SW_MODE_DISABLED)
+ if (switch_get_mode(hm.limit_switch) == SW_MODE_DISABLED)
hm.limit_switch = -1;
hm.saved_jerk = cm_get_axis_jerk(axis); // save the max jerk value
// Handle an initial switch closure by backing off the closed switch
// NOTE: Relies on independent switches per axis (not shared)
- if (sw.switches[hm.homing_switch].state == SW_CLOSED)
+ if (switch_get_closed(hm.homing_switch))
_homing_axis_move(axis, hm.latch_backoff, hm.search_velocity);
- else if (sw.switches[hm.limit_switch].state == SW_CLOSED)
+ else if (switch_get_closed(hm.limit_switch))
_homing_axis_move(axis, -hm.latch_backoff, hm.search_velocity);
return _set_homing_func(_homing_axis_search);
static stat_t _homing_axis_latch(int8_t axis) {
// verify assumption that we arrived here because of homing switch closure
// rather than user-initiated feedhold or other disruption
- if (sw.switches[hm.homing_switch].state != SW_CLOSED)
+ if (!switch_get_closed(hm.homing_switch))
return _set_homing_func(_homing_abort);
_homing_axis_move(axis, hm.latch_backoff, hm.latch_velocity);
// Can't because switch mode is global and our probe is NO, not NC.
pb.probe_switch = SW_MIN_Z; // FIXME: hardcoded...
- pb.saved_switch_mode = sw.switches[pb.probe_switch].mode;
+ pb.saved_switch_mode = switch_get_mode(pb.probe_switch);
- sw.switches[pb.probe_switch].mode = SW_MODE_HOMING;
+ switch_set_mode(pb.probe_switch, SW_MODE_HOMING);
// save the switch type for recovery later.
- pb.saved_switch_type = sw.switches[pb.probe_switch].type;
+ pb.saved_switch_type = switch_get_type(pb.probe_switch);
// contact probes are NO switches... usually
- sw.switches[pb.probe_switch].type = SW_TYPE_NORMALLY_OPEN;
+ switch_set_type(pb.probe_switch, SW_TYPE_NORMALLY_OPEN);
// re-init to pick up new switch settings
switch_init();
static stat_t _probing_start() {
// initial probe state, don't probe if we're already contacted!
- int8_t probe = sw.switches[pb.probe_switch].state;
+ bool closed = switch_get_closed(pb.probe_switch);
- if (probe == SW_OPEN)
- ritorno(cm_straight_feed(pb.target, pb.flags));
+ if (!closed) ritorno(cm_straight_feed(pb.target, pb.flags));
return _set_pb_func(_probing_finish);
}
static stat_t _probing_finish() {
- int8_t probe = sw.switches[pb.probe_switch].state;
- cm.probe_state = probe == SW_CLOSED ? PROBE_SUCCEEDED : PROBE_FAILED;
+ bool closed = switch_get_closed(pb.probe_switch);
+ cm.probe_state = closed ? PROBE_SUCCEEDED : PROBE_FAILED;
for (uint8_t axis = 0; axis < AXES; axis++) {
// if we got here because of a feed hold keep the model position correct
// we should be stopped now, but in case of switch closure
mp_flush_planner();
- sw.switches[pb.probe_switch].type = pb.saved_switch_type;
- sw.switches[pb.probe_switch].mode = pb.saved_switch_mode;
+ switch_set_type(pb.probe_switch, pb.saved_switch_type);
+ switch_set_mode(pb.probe_switch, pb.saved_switch_mode);
switch_init(); // re-init to pick up changes
// restore axis jerk
static void _update_steps_per_unit(int motor);
-/* Initialize stepper motor subsystem
- *
- * Notes:
- * - This init requires sys_init() to be run beforehand
- * - 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
- */
void stepper_init() {
/// clear all values, pointers and status
memset(&st_run, 0, sizeof(st_run));
// Setup ports
for (int motor = 0; motor < MOTORS; motor++) {
- hw.st_port[motor]->DIR = MOTOR_PORT_DIR_gm;
hw.st_port[motor]->OUTSET = MOTOR_ENABLE_BIT_bm; // disable motor
+ hw.st_port[motor]->DIR = MOTOR_PORT_DIR_gm; // pin directions
}
// Setup step timer
uint8_t st_runtime_isbusy() {return st_run.busy;}
-/// returns true if motor is enabled (motor is actually active low)
+/// returns true if motor is enabled
static bool _motor_is_enabled(uint8_t motor) {
- return !(hw.st_port[motor]->OUT & MOTOR_ENABLE_BIT_bm);
+ return st_run.mot[motor].flags & MOTOR_FLAG_ENABLED_bm;
}
/// returns true if motor is in an error state
if (value < MOTOR_POWER_MODE_MAX_VALUE)
st_cfg.mot[index].power_mode = value;
}
+
+
+void command_mreset(int motor) {
+ if (motor < MOTORS) st_run.mot[motor].flags &= 0;
+}
* The normally closed switch modes (NC) trigger an interrupt on the
* rising edge and lockout subsequent interrupts for the defined
* lockout period.
+ *
+ * These functions interact with each other to process switch closures
+ * and firing. Each switch has a counter which is initially set to
+ * negative SW_DEGLITCH_TICKS. When a switch closure is DETECTED the
+ * count increments for each RTC tick. When the count reaches zero
+ * the switch is tripped and action occurs. The counter continues to
+ * increment positive until the lockout is exceeded.
*/
#include "switch.h"
#include <stdbool.h>
+typedef enum { // state machine for managing debouncing and lockout
+ SW_IDLE,
+ SW_DEGLITCHING,
+ SW_LOCKOUT
+} swDebounce_t;
+
+typedef struct {
+ bool last;
+ bool state;
+ swType_t type;
+ swMode_t mode;
+ swDebounce_t debounce; // debounce state
+ int8_t count; // deglitching and lockout counter
+} switch_t;
+
+/* Switch control structures
+ * Note 1: The term "thrown" is used because switches could be normally-open
+ * or normally-closed. "Thrown" means activated or hit.
+ */
+typedef struct {
+ bool limit_thrown;
+ switch_t switches[SWITCHES];
+} swSingleton_t;
+
swSingleton_t sw;
}
-/* These functions interact with each other to process switch closures
- * and firing. Each switch has a counter which is initially set to
- * negative SW_DEGLITCH_TICKS. When a switch closure is DETECTED the
- * count increments for each RTC tick. When the count reaches zero
- * the switch is tripped and action occurs. The counter continues to
- * increment positive until the lockout is exceeded.
- */
-
static void _switch_isr() {
for (int i = 0; i < SWITCHES; i++) {
switch_t *s = &sw.switches[i];
// Switch interrupt handler vectors
-ISR(X_ISR_vect) {_switch_isr();}
-ISR(Y_ISR_vect) {_switch_isr();}
-ISR(Z_ISR_vect) {_switch_isr();}
-ISR(A_ISR_vect) {_switch_isr();}
+ISR(X_SWITCH_ISR_vect) {_switch_isr();}
+ISR(Y_SWITCH_ISR_vect) {_switch_isr();}
+ISR(Z_SWITCH_ISR_vect) {_switch_isr();}
+ISR(A_SWITCH_ISR_vect) {_switch_isr();}
-/* Initialize homing/limit switches
- *
- * This function assumes sys_init() and st_init() have been run previously to
- * bind the ports and set bit IO directions, repsectively.
- */
void switch_init() {
- for (int i = 0; i < NUM_SWITCH_PAIRS; i++) {
+ for (int i = 0; i < SWITCHES / 2; i++) {
// setup input bits and interrupts (previously set to inputs by st_init())
if (sw.switches[MIN_SWITCH(i)].mode != SW_MODE_DISABLED) {
hw.sw_port[i]->DIRCLR = SW_MIN_BIT_bm; // set min input - see 13.14.14
}
-/// return switch mode setting
-swMode_t get_switch_mode(uint8_t sw_num) {return sw.switches[sw_num].mode;}
+bool switch_get_closed(uint8_t n) {return sw.switches[n].state;}
+swType_t switch_get_type(uint8_t n) {return sw.switches[n].type;}
+
+
+void switch_set_type(uint8_t n, swType_t type) {
+ sw.switches[n].type = type;
+}
+
+
+swMode_t switch_get_mode(uint8_t n) {return sw.switches[n].mode;}
+
+
+void switch_set_mode(uint8_t n, swMode_t mode) {
+ sw.switches[n].mode = mode;
+}
+
-/// return true if a limit was tripped
-bool get_limit_switch_thrown() {return sw.limit_thrown;}
+bool switch_get_limit_thrown() {return sw.limit_thrown;}
uint8_t get_switch_type(int index) {
\******************************************************************************/
-/* Switch processing functions
- *
- * Switch processing turns pin transitions into reliable switch states.
- * There are 2 main operations:
- *
- * - read pin get raw data from a pin
- * - read switch return processed switch closures
- *
- * Read pin may be a polled operation or an interrupt on pin
- * change. If interrupts are used they must be provided for both
- * leading and trailing edge transitions.
- *
- * Read switch contains the results of read pin and manages edges and
- * debouncing.
- */
#pragma once
#include <stdint.h>
#include <stdbool.h>
-// timer for debouncing switches
-#define SW_LOCKOUT_TICKS 25 // 25=250ms. RTC ticks are ~10ms each
-#define SW_DEGLITCH_TICKS 3 // 3=30ms
+// macros for finding the index into the switch table give the axis number
+#define MIN_SWITCH(axis) (axis * 2)
+#define MAX_SWITCH(axis) (axis * 2 + 1)
-// switch modes
+/// switch modes
typedef enum {
SW_MODE_DISABLED,
SW_HOMING_BIT,
SW_TYPE_NORMALLY_CLOSED
} swType_t;
+/// indices into switch arrays
typedef enum {
- SW_OPEN,
- SW_CLOSED
-} swState_t;
-
-// macros for finding the index into the switch table give the axis number
-#define MIN_SWITCH(axis) (axis * 2)
-#define MAX_SWITCH(axis) (axis * 2 + 1)
-
-typedef enum { // state machine for managing debouncing and lockout
- SW_IDLE,
- SW_DEGLITCHING,
- SW_LOCKOUT
-} swDebounce_t;
-
-typedef enum { // indexes into switch arrays
- SW_MIN_X,
- SW_MAX_X,
- SW_MIN_Y,
- SW_MAX_Y,
- SW_MIN_Z,
- SW_MAX_Z,
- SW_MIN_A,
- SW_MAX_A
+ SW_MIN_X, SW_MAX_X,
+ SW_MIN_Y, SW_MAX_Y,
+ SW_MIN_Z, SW_MAX_Z,
+ SW_MIN_A, SW_MAX_A
} swNums_t;
-#define SW_OFFSET SW_MAX_X // offset between MIN and MAX switches
-#define NUM_SWITCH_PAIRS (SWITCHES / 2)
-
-/// Interrupt levels and vectors - The vectors are hard-wired to xmega ports
-/// If you change axis port assignments you need to change these, too.
-#define SWITCH_INTLVL PORT_INT0LVL_MED_gc
-
-// port assignments for vectors
-#define X_ISR_vect PORTA_INT0_vect
-#define Y_ISR_vect PORTD_INT0_vect
-#define Z_ISR_vect PORTE_INT0_vect
-#define A_ISR_vect PORTF_INT0_vect
-
-typedef struct {
- bool last;
- bool state;
- swType_t type;
- swMode_t mode;
- swDebounce_t debounce; // debounce state
- int8_t count; // deglitching and lockout counter
-} switch_t;
-
-/* Switch control structures
- * Note 1: The term "thrown" is used because switches could be normally-open
- * or normally-closed. "Thrown" means activated or hit.
- */
-typedef struct {
- bool limit_thrown;
- switch_t switches[SWITCHES];
-} swSingleton_t;
-
-extern swSingleton_t sw;
void switch_init();
-swMode_t get_switch_mode(uint8_t sw_num);
-
void switch_rtc_callback();
-bool get_limit_switch_thrown();
-void reset_switches();
+bool switch_get_closed(uint8_t n);
+swType_t switch_get_type(uint8_t n);
+void switch_set_type(uint8_t n, swType_t type);
+swMode_t switch_get_mode(uint8_t n);
+void switch_set_mode(uint8_t n, swMode_t mode);
+bool switch_get_limit_thrown();