#define PORT_MOTOR_3 PORTE
#define PORT_MOTOR_4 PORTD
+// Motor fault ISRs
+#define PORT_1_FAULT_ISR_vect PORTA_INT1_vect
+#define PORT_2_FAULT_ISR_vect PORTD_INT1_vect
+#define PORT_3_FAULT_ISR_vect PORTE_INT1_vect
+#define PORT_4_FAULT_ISR_vect PORTF_INT1_vect
+
// Switch axes mapped to ports
#define PORT_SWITCH_X PORTA
#define PORT_SWITCH_Y PORTF
#define MOTOR_PORT_DIR_gm 0x2f // pin dir settings
/// motor control port bit positions
-enum cfgPortBits {
- STEP_BIT_bp, // bit 0
- DIRECTION_BIT_bp, // bit 1 (low = clockwise)
- MOTOR_ENABLE_BIT_bp, // bit 2 (low = enabled)
- CHIP_SELECT_BIT_bp, // bit 3
- FAULT_BIT_bp, // bit 4
- GPIO1_OUT_BIT_bp, // bit 5 (gpio1 output bit; 1 from each axis)
- SW_MIN_BIT_bp, // bit 6 (input bit for homing/limit switches)
- SW_MAX_BIT_bp // bit 7 (input bit for homing/limit switches)
-};
+#define STEP_BIT_bp 0
+#define DIRECTION_BIT_bp 1
+#define MOTOR_ENABLE_BIT_bp 2
+#define CHIP_SELECT_BIT_bp 3
+#define FAULT_BIT_bp 4
+#define GPIO1_OUT_BIT_bp 5
+#define SW_MIN_BIT_bp 6 //4 homing/limit switches
+#define SW_MAX_BIT_bp 7 // homing/limit switches
#define STEP_BIT_bm (1 << STEP_BIT_bp)
#define DIRECTION_BIT_bm (1 << DIRECTION_BIT_bp)
swSingleton_t sw;
+static bool _read_switch(uint8_t sw_num) {
+ switch (sw_num) {
+ case SW_MIN_X: return hw.sw_port[AXIS_X]->IN & SW_MIN_BIT_bm;
+ case SW_MAX_X: return hw.sw_port[AXIS_X]->IN & SW_MAX_BIT_bm;
+ case SW_MIN_Y: return hw.sw_port[AXIS_Y]->IN & SW_MIN_BIT_bm;
+ case SW_MAX_Y: return hw.sw_port[AXIS_Y]->IN & SW_MAX_BIT_bm;
+ case SW_MIN_Z: return hw.sw_port[AXIS_Z]->IN & SW_MIN_BIT_bm;
+ case SW_MAX_Z: return hw.sw_port[AXIS_Z]->IN & SW_MAX_BIT_bm;
+ case SW_MIN_A: return hw.sw_port[AXIS_A]->IN & SW_MIN_BIT_bm;
+ case SW_MAX_A: return hw.sw_port[AXIS_A]->IN & SW_MAX_BIT_bm;
+ default: return false;
+ }
+}
+
+
+/* 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];
+
+ bool set = _read_switch(i);
+ if (set == s->last) continue;
+
+ if (s->mode == SW_MODE_DISABLED) return; // never supposed to happen
+ if (s->debounce == SW_LOCKOUT) return; // switch is in lockout
+
+ // either transitions state from IDLE or overwrites it
+ s->debounce = SW_DEGLITCHING;
+ // reset deglitch count regardless of entry state
+ s->count = -SW_DEGLITCH_TICKS;
+
+ // A NO switch drives the pin LO when thrown
+ s->state = (s->type == SW_TYPE_NORMALLY_OPEN) ^ set;
+ }
+}
+
+
+// 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();}
+
+
/* Initialize homing/limit switches
*
* This function assumes sys_init() and st_init() have been run previously to
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
hw.sw_port[i]->PIN6CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;
- hw.sw_port[i]->INT0MASK = SW_MIN_BIT_bm; // min on INT0
-
- } else hw.sw_port[i]->INT0MASK = 0; // disable interrupt
+ hw.sw_port[i]->INT0MASK |= SW_MIN_BIT_bm; // min on INT0
+ }
if (sw.switches[MAX_SWITCH(i)].mode != SW_MODE_DISABLED) {
hw.sw_port[i]->DIRCLR = SW_MAX_BIT_bm; // set max input - see 13.14.14
hw.sw_port[i]->PIN7CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;
- hw.sw_port[i]->INT1MASK = SW_MAX_BIT_bm; // max on INT1
-
- } else hw.sw_port[i]->INT1MASK = 0; // disable interrupt
+ hw.sw_port[i]->INT0MASK |= SW_MAX_BIT_bm; // max on INT0
+ }
// set interrupt levels. Interrupts must be enabled in main()
- hw.sw_port[i]->INTCTRL = SWITCH_INTLVL;
+ hw.sw_port[i]->INTCTRL |= SWITCH_INTLVL;
}
// Defaults
- for (int i = 0; i < SWITCHES; i++)
- sw.switches[i].type = SWITCH_TYPE;
-
sw.switches[0].mode = X_SWITCH_MODE_MIN;
sw.switches[1].mode = X_SWITCH_MODE_MAX;
sw.switches[2].mode = Y_SWITCH_MODE_MIN;
sw.switches[6].mode = A_SWITCH_MODE_MIN;
sw.switches[7].mode = A_SWITCH_MODE_MAX;
- reset_switches();
-}
-
-
-/* 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(uint8_t sw_num) {
- switch_t *s = &sw.switches[sw_num];
-
- if (s->mode == SW_MODE_DISABLED) return; // never supposed to happen
- if (s->debounce == SW_LOCKOUT) return; // switch is in lockout
-
- // either transitions state from IDLE or overwrites it
- s->debounce = SW_DEGLITCHING;
- // reset deglitch count regardless of entry state
- s->count = -SW_DEGLITCH_TICKS;
+ for (int i = 0; i < SWITCHES; i++) {
+ switch_t *s = &sw.switches[i];
+ s->type = SWITCH_TYPE;
+ s->debounce = SW_IDLE;
+ s->state = (s->type == SW_TYPE_NORMALLY_OPEN) ^ _read_switch(i);
+ }
- // sets the state value in the struct
- read_switch(sw_num);
+ sw.limit_thrown = false;
}
-// Switch interrupt handler vectors
-ISR(X_MIN_ISR_vect) {_switch_isr(SW_MIN_X);}
-ISR(Y_MIN_ISR_vect) {_switch_isr(SW_MIN_Y);}
-ISR(Z_MIN_ISR_vect) {_switch_isr(SW_MIN_Z);}
-ISR(A_MIN_ISR_vect) {_switch_isr(SW_MIN_A);}
-ISR(X_MAX_ISR_vect) {_switch_isr(SW_MAX_X);}
-ISR(Y_MAX_ISR_vect) {_switch_isr(SW_MAX_Y);}
-ISR(Z_MAX_ISR_vect) {_switch_isr(SW_MAX_Z);}
-ISR(A_MAX_ISR_vect) {_switch_isr(SW_MAX_A);}
-
-
/// Called from RTC for each RTC tick
void switch_rtc_callback() {
for (int i = 0; i < SWITCHES; i++) {
s->debounce = SW_IDLE;
// check if the state has changed while we were in lockout...
- uint8_t old_state = s->state;
- if (old_state != read_switch(i)) {
+ bool old_state = s->state;
+ if (old_state != _read_switch(i)) {
s->debounce = SW_DEGLITCHING;
s->count = -SW_DEGLITCH_TICKS;
}
}
if (!s->count) { // trigger point
- sw.switch_thrown = i; // record number of thrown switch
s->debounce = SW_LOCKOUT;
// regardless of switch type
bool get_limit_switch_thrown() {return sw.limit_thrown;}
-/// reset all switches and reset limit flag
-void reset_switches() {
- for (uint8_t i = 0; i < SWITCHES; i++) {
- sw.switches[i].debounce = SW_IDLE;
- read_switch(i);
- }
-
- sw.limit_thrown = false;
-}
-
-
-/// read a switch directly with no interrupts or deglitching
-uint8_t read_switch(uint8_t sw_num) {
- if (sw_num < 0 || sw_num >= SWITCHES) return SW_DISABLED;
-
- bool hi = false;
- switch (sw_num) {
- case SW_MIN_X: hi = hw.sw_port[AXIS_X]->IN & SW_MIN_BIT_bm; break;
- case SW_MAX_X: hi = hw.sw_port[AXIS_X]->IN & SW_MAX_BIT_bm; break;
- case SW_MIN_Y: hi = hw.sw_port[AXIS_Y]->IN & SW_MIN_BIT_bm; break;
- case SW_MAX_Y: hi = hw.sw_port[AXIS_Y]->IN & SW_MAX_BIT_bm; break;
- case SW_MIN_Z: hi = hw.sw_port[AXIS_Z]->IN & SW_MIN_BIT_bm; break;
- case SW_MAX_Z: hi = hw.sw_port[AXIS_Z]->IN & SW_MAX_BIT_bm; break;
- case SW_MIN_A: hi = hw.sw_port[AXIS_A]->IN & SW_MIN_BIT_bm; break;
- case SW_MAX_A: hi = hw.sw_port[AXIS_A]->IN & SW_MAX_BIT_bm; break;
- }
-
- // A NO switch drives the pin LO when thrown
- if (sw.switches[sw_num].type == SW_TYPE_NORMALLY_OPEN)
- sw.switches[sw_num].state = hi ? SW_OPEN : SW_CLOSED;
- else sw.switches[sw_num].state = hi ? SW_CLOSED : SW_OPEN;
-
- return sw.switches[sw_num].state;
-}
-
-
uint8_t get_switch_type(int index) {
return sw.switches[index].type;
}