From: Joseph Coffland Date: Mon, 21 Mar 2016 02:29:23 +0000 (-0700) Subject: Switch, stepper and tmc2660 cleanup X-Git-Url: https://git.buildbotics.com/?a=commitdiff_plain;h=4f1fd350133bc898bda48f3e0af711d548b62b52;p=bbctrl-firmware Switch, stepper and tmc2660 cleanup --- diff --git a/src/config.h b/src/config.h index c4f83bc..efb2521 100644 --- a/src/config.h +++ b/src/config.h @@ -256,9 +256,9 @@ enum cfgPortBits { 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 (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) + 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_bm (1 << STEP_BIT_bp) diff --git a/src/cycle_homing.c b/src/cycle_homing.c index 9adca0f..7ae2659 100644 --- a/src/cycle_homing.c +++ b/src/cycle_homing.c @@ -282,10 +282,10 @@ static stat_t _homing_axis_clear(int8_t axis) { // Handle an initial switch closure by backing off the closed switch // NOTE: Relies on independent switches per axis (not shared) - if (sw.state[hm.homing_switch] == SW_CLOSED) + if (sw.switches[hm.homing_switch].state == SW_CLOSED) _homing_axis_move(axis, hm.latch_backoff, hm.search_velocity); - else if (sw.state[hm.limit_switch] == SW_CLOSED) + else if (sw.switches[hm.limit_switch].state == SW_CLOSED) _homing_axis_move(axis, -hm.latch_backoff, hm.search_velocity); return _set_homing_func(_homing_axis_search); @@ -306,7 +306,7 @@ static stat_t _homing_axis_search(int8_t axis) { 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.state[hm.homing_switch] != SW_CLOSED) + if (sw.switches[hm.homing_switch].state != SW_CLOSED) return _set_homing_func(_homing_abort); _homing_axis_move(axis, hm.latch_backoff, hm.latch_velocity); diff --git a/src/cycle_probing.c b/src/cycle_probing.c index 618a1de..cf41111 100644 --- a/src/cycle_probing.c +++ b/src/cycle_probing.c @@ -172,13 +172,13 @@ static uint8_t _probing_init() { // 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.mode[pb.probe_switch]; + pb.saved_switch_mode = sw.switches[pb.probe_switch].mode; - sw.mode[pb.probe_switch] = SW_MODE_HOMING; + sw.switches[pb.probe_switch].mode = SW_MODE_HOMING; // save the switch type for recovery later. - pb.saved_switch_type = sw.switch_type; + pb.saved_switch_type = sw.switches[pb.probe_switch].type; // contact probes are NO switches... usually - sw.switch_type = SW_TYPE_NORMALLY_OPEN; + sw.switches[pb.probe_switch].type = SW_TYPE_NORMALLY_OPEN; // re-init to pick up new switch settings switch_init(); @@ -197,9 +197,9 @@ static uint8_t _probing_init() { static stat_t _probing_start() { // initial probe state, don't probe if we're already contacted! - int8_t probe = sw.state[pb.probe_switch]; + int8_t probe = sw.switches[pb.probe_switch].state; - if( probe==SW_OPEN ) + if (probe == SW_OPEN) ritorno(cm_straight_feed(pb.target, pb.flags)); return _set_pb_func(_probing_finish); @@ -207,8 +207,8 @@ static stat_t _probing_start() { static stat_t _probing_finish() { - int8_t probe = sw.state[pb.probe_switch]; - cm.probe_state = (probe==SW_CLOSED) ? PROBE_SUCCEEDED : PROBE_FAILED; + int8_t probe = sw.switches[pb.probe_switch].state; + cm.probe_state = probe == SW_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 @@ -226,8 +226,8 @@ static void _probe_restore_settings() { // we should be stopped now, but in case of switch closure mp_flush_planner(); - sw.switch_type = pb.saved_switch_type; - sw.mode[pb.probe_switch] = pb.saved_switch_mode; + sw.switches[pb.probe_switch].type = pb.saved_switch_type; + sw.switches[pb.probe_switch].mode = pb.saved_switch_mode; switch_init(); // re-init to pick up changes // restore axis jerk diff --git a/src/report.c b/src/report.c index dde3e0c..e4e7d7e 100644 --- a/src/report.c +++ b/src/report.c @@ -44,17 +44,6 @@ static bool report_requested = false; static bool report_full = false; static uint32_t last_report = 0; -static float velocity; -static float positions[AXES]; - - -void report_init() { - velocity = 0; - - for (int axis = 0; axis < AXES; axis++) - positions[axis] = 0; -} - void report_request() { report_requested = true; diff --git a/src/report.h b/src/report.h index f42c963..b05360a 100644 --- a/src/report.h +++ b/src/report.h @@ -30,7 +30,6 @@ #include "status.h" -void report_init(); void report_request(); void report_request_full(); stat_t report_callback(); diff --git a/src/stepper.c b/src/stepper.c index 8a88d7c..9513c06 100644 --- a/src/stepper.c +++ b/src/stepper.c @@ -75,22 +75,28 @@ static void _update_steps_per_unit(int motor); * complete */ void stepper_init() { - memset(&st_run, 0, sizeof(st_run)); // clear all values, pointers and status + /// clear all values, pointers and status + memset(&st_run, 0, sizeof(st_run)); + memset(&st_pre, 0, sizeof(st_pre)); // Setup ports - for (uint8_t i = 0; i < MOTORS; i++) { - hw.st_port[i]->DIR = MOTOR_PORT_DIR_gm; - hw.st_port[i]->OUTSET = MOTOR_ENABLE_BIT_bm; // disable motor + 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 } // Setup step timer - TIMER_STEP.CTRLA = STEP_TIMER_DISABLE; // turn timer off - TIMER_STEP.CTRLB = STEP_TIMER_WGMODE; // waveform mode - TIMER_STEP.INTCTRLA = STEP_TIMER_INTLVL; // interrupt mode + TIMER_STEP.CTRLA = STEP_TIMER_DISABLE; // turn timer off + TIMER_STEP.CTRLB = STEP_TIMER_WGMODE; // waveform mode + TIMER_STEP.INTCTRLA = STEP_TIMER_INTLVL; // interrupt mode st_pre.owner = PREP_BUFFER_OWNER_EXEC; - // Defaults + // Reset steppers to known state + for (int motor = 0; motor < MOTORS; motor++) + st_pre.mot[motor].prev_direction = STEP_INITIAL_DIRECTION; + + // Motor configuration defaults st_cfg.motor_power_timeout = MOTOR_IDLE_TIMEOUT; st_cfg.mot[MOTOR_1].motor_map = M1_MOTOR_MAP; @@ -138,15 +144,7 @@ void stepper_init() { for (int motor = 0; motor < MOTORS; motor++) _update_steps_per_unit(motor); - // reset steppers to known state - for (uint8_t motor = 0; motor < MOTORS; motor++) { - st_pre.mot[motor].prev_direction = STEP_INITIAL_DIRECTION; - st_pre.mot[motor].timer_clock = 0; - st_pre.mot[motor].timer_period = 0; - st_pre.mot[motor].steps = 0; - st_pre.mot[motor].corrected_steps = 0; // diagnostic only - no effect - } - + // Reset position, must be after update steps per unit mp_set_steps_to_runtime_position(); } @@ -155,27 +153,35 @@ void stepper_init() { uint8_t st_runtime_isbusy() {return st_run.busy;} -/// returns 1 if motor is enabled (motor is actually active low) -static uint8_t _motor_is_enabled(uint8_t motor) { - uint8_t port = motor < MOTORS ? hw.st_port[motor]->OUT : 0xff; - return port & MOTOR_ENABLE_BIT_bm ? 0 : 1; +/// returns true if motor is enabled (motor is actually active low) +static bool _motor_is_enabled(uint8_t motor) { + return !(hw.st_port[motor]->OUT & MOTOR_ENABLE_BIT_bm); +} + +/// returns true if motor is in an error state +static bool _motor_error(uint8_t motor) { + return st_run.mot[motor].flags & MOTOR_FLAG_ERROR_bm; } /// Remove power from a motor -static void _deenergize_motor(const uint8_t motor) { - if (motor < MOTORS) hw.st_port[motor]->OUTSET = MOTOR_ENABLE_BIT_bm; - st_run.mot[motor].power_state = MOTOR_OFF; +static void _deenergize_motor(uint8_t motor) { + if (_motor_is_enabled(motor)) { + hw.st_port[motor]->OUTSET = MOTOR_ENABLE_BIT_bm; + st_run.mot[motor].power_state = MOTOR_OFF; + st_run.mot[motor].flags &= MOTOR_FLAG_ENABLED_bm; + report_request(); // request a status report when motors change state + } } /// Apply power to a motor -static void _energize_motor(const uint8_t motor) { - if (st_cfg.mot[motor].power_mode == MOTOR_DISABLED) _deenergize_motor(motor); - - else { - if (motor < MOTORS) hw.st_port[motor]->OUTCLR = MOTOR_ENABLE_BIT_bm; +static void _energize_motor(uint8_t motor) { + if (!_motor_is_enabled(motor) && !_motor_error(motor)) { + hw.st_port[motor]->OUTCLR = MOTOR_ENABLE_BIT_bm; st_run.mot[motor].power_state = MOTOR_POWER_TIMEOUT_START; + st_run.mot[motor].flags |= MOTOR_FLAG_ENABLED_bm; + report_request(); // request a status report when motors change state } } @@ -186,9 +192,7 @@ stat_t st_motor_power_callback() { // called by controller // Manage power for each motor individually for (int motor = 0; motor < MOTORS; motor++) switch (st_cfg.mot[motor].power_mode) { - case MOTOR_ALWAYS_POWERED: - if (!_motor_is_enabled(motor)) _energize_motor(motor); - break; + case MOTOR_ALWAYS_POWERED: _energize_motor(motor); break; case MOTOR_POWERED_IN_CYCLE: case MOTOR_POWERED_ONLY_WHEN_MOVING: if (st_run.mot[motor].power_state == MOTOR_POWER_TIMEOUT_START) { @@ -201,11 +205,8 @@ stat_t st_motor_power_callback() { // called by controller // Run the countdown if not in feedhold and in a countdown if (cm_get_combined_state() != COMBINED_HOLD && st_run.mot[motor].power_state == MOTOR_POWER_TIMEOUT_COUNTDOWN && - rtc_get_time() > st_run.mot[motor].power_systick) { - st_run.mot[motor].power_state = MOTOR_IDLE; + rtc_get_time() > st_run.mot[motor].power_systick) _deenergize_motor(motor); - report_request(); // request a status report when motors shut down - } break; default: _deenergize_motor(motor); break; // Motor disabled @@ -215,6 +216,12 @@ stat_t st_motor_power_callback() { // called by controller } +void st_motor_error_callback(uint8_t motor, cmMotorFlags_t errors) { + st_run.mot[motor].flags |= MOTOR_FLAG_ERROR_bm & errors; + if (_motor_error(motor)) _deenergize_motor(motor); +} + + /// Special interrupt for X-axis ISR(TCE1_CCA_vect) { PORT_MOTOR_1.OUTTGL = STEP_BIT_bm; @@ -271,7 +278,6 @@ ISR(ADCB_CH1_vect) { static inline void _load_motor_move(int motor) { - stRunMotor_t *run_mot = &st_run.mot[motor]; stPrepMotor_t *pre_mot = &st_pre.mot[motor]; const cfgMotor_t *cfg_mot = &st_cfg.mot[motor]; @@ -302,10 +308,8 @@ static inline void _load_motor_move(int motor) { // Energize motor and start power management if ((pre_mot->timer_clock && cfg_mot->power_mode != MOTOR_DISABLED) || - cfg_mot->power_mode == MOTOR_POWERED_IN_CYCLE) { - hw.st_port[motor]->OUTCLR = MOTOR_ENABLE_BIT_bm; // energize motor - run_mot->power_state = MOTOR_POWER_TIMEOUT_START; // start power management - } + cfg_mot->power_mode == MOTOR_POWERED_IN_CYCLE) + _energize_motor(motor); } diff --git a/src/stepper.h b/src/stepper.h index 0d93adc..69229c5 100644 --- a/src/stepper.h +++ b/src/stepper.h @@ -255,6 +255,19 @@ typedef enum { } cmMotorPolarity_t; +typedef enum { + MOTOR_FLAG_ENABLED_bm = 1 << 0, + MOTOR_FLAG_STALLED_bm = 1 << 1, + MOTOR_FLAG_OVERTEMP_WARN_bm = 1 << 2, + MOTOR_FLAG_OVERTEMP_bm = 1 << 3, + MOTOR_FLAG_SHORTED_bm = 1 << 4, + MOTOR_FLAG_ERROR_bm = (MOTOR_FLAG_STALLED_bm | + MOTOR_FLAG_OVERTEMP_WARN_bm | + MOTOR_FLAG_OVERTEMP_bm | + MOTOR_FLAG_SHORTED_bm) +} cmMotorFlags_t; + + /// Min/Max timeouts allowed for motor disable. Allow for inertial stop. /// Must be non-zero #define MOTOR_TIMEOUT_SECONDS_MIN (float)0.1 @@ -330,6 +343,7 @@ typedef struct { typedef struct { // one per controlled motor motorPowerState_t power_state; // state machine for managing motor power uint32_t power_systick; // for next motor power state transition + cmMotorFlags_t flags; } stRunMotor_t; @@ -378,6 +392,7 @@ void stepper_init(); uint8_t st_runtime_isbusy(); stat_t st_motor_power_callback(); +void st_motor_error_callback(uint8_t motor, cmMotorFlags_t errors); void st_request_exec_move(); void st_prep_null(); diff --git a/src/switch.c b/src/switch.c index 8b94cb0..6fac71e 100644 --- a/src/switch.c +++ b/src/switch.c @@ -43,7 +43,7 @@ * * The normally closed switch modes (NC) trigger an interrupt on the * rising edge and lockout subsequent interrupts for the defined - * lockout period. Ditto on the method. + * lockout period. */ #include "switch.h" @@ -57,48 +57,47 @@ #include +swSingleton_t sw; + + /* 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. */ -#define PIN_MODE PORT_OPC_PULLUP_gc // pin mode. see iox192a3.h for details - - void switch_init() { - for (uint8_t i = 0; i < NUM_SWITCH_PAIRS; i++) { + for (int i = 0; i < NUM_SWITCH_PAIRS; i++) { // setup input bits and interrupts (previously set to inputs by st_init()) - if (sw.mode[MIN_SWITCH(i)] != SW_MODE_DISABLED) { - // set min input - see 13.14.14 - hw.sw_port[i]->DIRCLR = SW_MIN_BIT_bm; - hw.sw_port[i]->PIN6CTRL = PIN_MODE | PORT_ISC_BOTHEDGES_gc; - // interrupt on min switch - hw.sw_port[i]->INT0MASK = SW_MIN_BIT_bm; + 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 - if (sw.mode[MAX_SWITCH(i)] != SW_MODE_DISABLED) { - // set max input - see 13.14.14 - hw.sw_port[i]->DIRCLR = SW_MAX_BIT_bm; - hw.sw_port[i]->PIN7CTRL = PIN_MODE | PORT_ISC_BOTHEDGES_gc; + 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; + } else hw.sw_port[i]->INT1MASK = 0; // disable interrupt // set interrupt levels. Interrupts must be enabled in main() - hw.sw_port[i]->INTCTRL = GPIO1_INTLVL; // see gpio.h for setting + hw.sw_port[i]->INTCTRL = SWITCH_INTLVL; } // Defaults - sw.switch_type = SWITCH_TYPE; - sw.mode[0] = X_SWITCH_MODE_MIN; - sw.mode[1] = X_SWITCH_MODE_MAX; - sw.mode[2] = Y_SWITCH_MODE_MIN; - sw.mode[3] = Y_SWITCH_MODE_MAX; - sw.mode[4] = Z_SWITCH_MODE_MIN; - sw.mode[5] = Z_SWITCH_MODE_MAX; - sw.mode[6] = A_SWITCH_MODE_MIN; - sw.mode[7] = A_SWITCH_MODE_MAX; + 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[3].mode = Y_SWITCH_MODE_MAX; + sw.switches[4].mode = Z_SWITCH_MODE_MIN; + sw.switches[5].mode = Z_SWITCH_MODE_MAX; + sw.switches[6].mode = A_SWITCH_MODE_MIN; + sw.switches[7].mode = A_SWITCH_MODE_MAX; reset_switches(); } @@ -112,14 +111,16 @@ void switch_init() { * increment positive until the lockout is exceeded. */ -static void _switch_isr_helper(uint8_t sw_num) { - if (sw.mode[sw_num] == SW_MODE_DISABLED) return; // never supposed to happen - if (sw.debounce[sw_num] == SW_LOCKOUT) return; // switch is in lockout +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 - sw.debounce[sw_num] = SW_DEGLITCHING; + s->debounce = SW_DEGLITCHING; // reset deglitch count regardless of entry state - sw.count[sw_num] = -SW_DEGLITCH_TICKS; + s->count = -SW_DEGLITCH_TICKS; // sets the state value in the struct read_switch(sw_num); @@ -127,70 +128,69 @@ static void _switch_isr_helper(uint8_t sw_num) { // Switch interrupt handler vectors -ISR(X_MIN_ISR_vect) {_switch_isr_helper(SW_MIN_X);} -ISR(Y_MIN_ISR_vect) {_switch_isr_helper(SW_MIN_Y);} -ISR(Z_MIN_ISR_vect) {_switch_isr_helper(SW_MIN_Z);} -ISR(A_MIN_ISR_vect) {_switch_isr_helper(SW_MIN_A);} -ISR(X_MAX_ISR_vect) {_switch_isr_helper(SW_MAX_X);} -ISR(Y_MAX_ISR_vect) {_switch_isr_helper(SW_MAX_Y);} -ISR(Z_MAX_ISR_vect) {_switch_isr_helper(SW_MAX_Z);} -ISR(A_MAX_ISR_vect) {_switch_isr_helper(SW_MAX_A);} +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 (uint8_t i = 0; i < SWITCHES; i++) { - if (sw.mode[i] == SW_MODE_DISABLED || sw.debounce[i] == SW_IDLE) + for (int i = 0; i < SWITCHES; i++) { + switch_t *s = &sw.switches[i]; + + if (s->mode == SW_MODE_DISABLED || s->debounce == SW_IDLE) continue; // state is either lockout or deglitching - if (++sw.count[i] == SW_LOCKOUT_TICKS) { - sw.debounce[i] = SW_IDLE; + if (++s->count == SW_LOCKOUT_TICKS) { + s->debounce = SW_IDLE; // check if the state has changed while we were in lockout... - uint8_t old_state = sw.state[i]; + uint8_t old_state = s->state; if (old_state != read_switch(i)) { - sw.debounce[i] = SW_DEGLITCHING; - sw.count[i] = -SW_DEGLITCH_TICKS; + s->debounce = SW_DEGLITCHING; + s->count = -SW_DEGLITCH_TICKS; } continue; } - if (!sw.count[i]) { // trigger point - sw.sw_num_thrown = i; // record number of thrown switch - sw.debounce[i] = SW_LOCKOUT; + if (!s->count) { // trigger point + sw.switch_thrown = i; // record number of thrown switch + s->debounce = SW_LOCKOUT; // regardless of switch type if (cm.cycle_state == CYCLE_HOMING || cm.cycle_state == CYCLE_PROBE) cm_request_feedhold(); // should be a limit switch, so fire it. - else if (sw.mode[i] & SW_LIMIT_BIT) - sw.limit_flag = true; // triggers an emergency shutdown + else if (s->mode & SW_LIMIT_BIT) + sw.limit_thrown = true; // triggers an emergency shutdown } } } /// return switch mode setting -uint8_t get_switch_mode(uint8_t sw_num) {return sw.mode[sw_num];} +swMode_t get_switch_mode(uint8_t sw_num) {return sw.switches[sw_num].mode;} /// return true if a limit was tripped -uint8_t get_limit_switch_thrown() {return sw.limit_flag;} - -/// return switch number most recently thrown -uint8_t get_switch_thrown() {return sw.sw_num_thrown;} +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.debounce[i] = SW_IDLE; + sw.switches[i].debounce = SW_IDLE; read_switch(i); } - sw.limit_flag = false; + sw.limit_thrown = false; } @@ -198,31 +198,32 @@ void reset_switches() { uint8_t read_switch(uint8_t sw_num) { if (sw_num < 0 || sw_num >= SWITCHES) return SW_DISABLED; - uint8_t read = 0; + bool hi = false; switch (sw_num) { - case SW_MIN_X: read = hw.sw_port[AXIS_X]->IN & SW_MIN_BIT_bm; break; - case SW_MAX_X: read = hw.sw_port[AXIS_X]->IN & SW_MAX_BIT_bm; break; - case SW_MIN_Y: read = hw.sw_port[AXIS_Y]->IN & SW_MIN_BIT_bm; break; - case SW_MAX_Y: read = hw.sw_port[AXIS_Y]->IN & SW_MAX_BIT_bm; break; - case SW_MIN_Z: read = hw.sw_port[AXIS_Z]->IN & SW_MIN_BIT_bm; break; - case SW_MAX_Z: read = hw.sw_port[AXIS_Z]->IN & SW_MAX_BIT_bm; break; - case SW_MIN_A: read = hw.sw_port[AXIS_A]->IN & SW_MIN_BIT_bm; break; - case SW_MAX_A: read = hw.sw_port[AXIS_A]->IN & SW_MAX_BIT_bm; break; + 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.switch_type == SW_TYPE_NORMALLY_OPEN) - sw.state[sw_num] = read ? SW_OPEN : SW_CLOSED; - else sw.state[sw_num] = read ? SW_CLOSED : SW_OPEN; + 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.state[sw_num]; + return sw.switches[sw_num].state; } uint8_t get_switch_type(int index) { - return 0; + return sw.switches[index].type; } -void set_switch_type(int axis, uint8_t value) { +void set_switch_type(int index, uint8_t value) { + sw.switches[index].type = value; } diff --git a/src/switch.h b/src/switch.h index cbc537b..0301455 100644 --- a/src/switch.h +++ b/src/switch.h @@ -47,44 +47,45 @@ #include "config.h" #include +#include // timer for debouncing switches #define SW_LOCKOUT_TICKS 25 // 25=250ms. RTC ticks are ~10ms each #define SW_DEGLITCH_TICKS 3 // 3=30ms // switch modes -enum { +typedef enum { SW_MODE_DISABLED, SW_HOMING_BIT, SW_LIMIT_BIT -}; +} swMode_t; #define SW_MODE_HOMING SW_HOMING_BIT // enable switch for homing only #define SW_MODE_LIMIT SW_LIMIT_BIT // enable switch for limits only #define SW_MODE_HOMING_LIMIT (SW_HOMING_BIT | SW_LIMIT_BIT) // homing & limits -enum swType { +typedef enum { SW_TYPE_NORMALLY_OPEN, SW_TYPE_NORMALLY_CLOSED -}; +} swType_t; -enum swState { +typedef enum { SW_DISABLED = -1, 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) -enum swDebounce { // state machine for managing debouncing and lockout +typedef enum { // state machine for managing debouncing and lockout SW_IDLE, SW_DEGLITCHING, SW_LOCKOUT -}; +} swDebounce_t; -enum swNums { // indexes into switch arrays +typedef enum { // indexes into switch arrays SW_MIN_X, SW_MAX_X, SW_MIN_Y, @@ -93,49 +94,50 @@ enum swNums { // indexes into switch arrays 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 GPIO1_INTLVL (PORT_INT0LVL_MED_gc | PORT_INT1LVL_MED_gc) +#define SWITCH_INTLVL (PORT_INT0LVL_MED_gc | PORT_INT1LVL_MED_gc) // port assignments for vectors #define X_MIN_ISR_vect PORTA_INT0_vect #define Y_MIN_ISR_vect PORTD_INT0_vect #define Z_MIN_ISR_vect PORTE_INT0_vect #define A_MIN_ISR_vect PORTF_INT0_vect + #define X_MAX_ISR_vect PORTA_INT1_vect #define Y_MAX_ISR_vect PORTD_INT1_vect #define Z_MAX_ISR_vect PORTE_INT1_vect #define A_MAX_ISR_vect PORTF_INT1_vect +typedef struct { + swState_t 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. */ -struct swStruct { // switch state - uint8_t switch_type; // 0=NO, 1=NC - applies to all switches - uint8_t limit_flag; // 1=limit switch thrown - do a lockout - uint8_t sw_num_thrown; // number of switch that was just thrown - /// 0=OPEN, 1=CLOSED (depends on switch type) - uint8_t state[SWITCHES]; - /// 0=disabled, 1=homing, 2=homing+limit, 3=limit - volatile uint8_t mode[SWITCHES]; - /// debouncer state machine - see swDebounce - volatile uint8_t debounce[SWITCHES]; - volatile int8_t count[SWITCHES]; // deglitching and lockout counter -}; -struct swStruct sw; +typedef struct { + bool limit_thrown; + uint8_t switch_thrown; // number of switch that was just thrown + switch_t switches[SWITCHES]; +} swSingleton_t; + +extern swSingleton_t sw; void switch_init(); uint8_t read_switch(uint8_t sw_num); -uint8_t get_switch_mode(uint8_t sw_num); +swMode_t get_switch_mode(uint8_t sw_num); void switch_rtc_callback(); -uint8_t get_limit_switch_thrown(); -uint8_t get_switch_thrown(); +bool get_limit_switch_thrown(); void reset_switches(); -void sw_show_switch(); diff --git a/src/tmc2660.c b/src/tmc2660.c index 00ee69a..e00e93b 100644 --- a/src/tmc2660.c +++ b/src/tmc2660.c @@ -27,6 +27,8 @@ #include "tmc2660.h" #include "status.h" +#include "stepper.h" +#include "hardware.h" #include #include @@ -74,7 +76,7 @@ static const uint32_t reg_addrs[] = { static volatile uint8_t driver; -static tmc2660_driver_t drivers[TMC2660_NUM_DRIVERS]; +static tmc2660_driver_t drivers[MOTORS]; static volatile spi_state_t spi_state; static volatile uint8_t spi_byte; @@ -82,23 +84,24 @@ static volatile uint32_t spi_out; static volatile uint32_t spi_in; -static void spi_cs(int driver, int enable) { - if (enable) - switch (driver) { - case 0: TMC2660_SPI_SSX_PORT.OUTCLR = 1 << TMC2660_SPI_SSX_PIN; break; - case 1: TMC2660_SPI_SSY_PORT.OUTCLR = 1 << TMC2660_SPI_SSY_PIN; break; - case 2: TMC2660_SPI_SSZ_PORT.OUTCLR = 1 << TMC2660_SPI_SSZ_PIN; break; - case 3: TMC2660_SPI_SSA_PORT.OUTCLR = 1 << TMC2660_SPI_SSA_PIN; break; - case 4: TMC2660_SPI_SSB_PORT.OUTCLR = 1 << TMC2660_SPI_SSB_PIN; break; - } - else - switch (driver) { - case 0: TMC2660_SPI_SSX_PORT.OUTSET = 1 << TMC2660_SPI_SSX_PIN; break; - case 1: TMC2660_SPI_SSY_PORT.OUTSET = 1 << TMC2660_SPI_SSY_PIN; break; - case 2: TMC2660_SPI_SSZ_PORT.OUTSET = 1 << TMC2660_SPI_SSZ_PIN; break; - case 3: TMC2660_SPI_SSA_PORT.OUTSET = 1 << TMC2660_SPI_SSA_PIN; break; - case 4: TMC2660_SPI_SSB_PORT.OUTSET = 1 << TMC2660_SPI_SSB_PIN; break; - } +static void _report_error_flags(int driver) { + uint8_t dflags = drivers[driver].flags; + uint8_t mflags = 0; + + if ((TMC2660_DRVSTATUS_SHORT_TO_GND_A | TMC2660_DRVSTATUS_SHORT_TO_GND_B) & + dflags) mflags |= MOTOR_FLAG_SHORTED_bm; + if (TMC2660_DRVSTATUS_OVERTEMP_WARN & dflags) + mflags |= MOTOR_FLAG_OVERTEMP_WARN_bm; + if (TMC2660_DRVSTATUS_OVERTEMP & dflags) + mflags |= MOTOR_FLAG_OVERTEMP_bm; + + st_motor_error_callback(driver, mflags); +} + + +static void spi_cs(int motor, int enable) { + if (enable) hw.st_port[motor]->OUTCLR = CHIP_SELECT_BIT_bm; + else hw.st_port[motor]->OUTSET = CHIP_SELECT_BIT_bm; } @@ -173,14 +176,15 @@ void spi_next() { drv->sguard = (uint16_t)((spi_in >> 14) & 0x1ff); drv->flags = spi_in >> 4; + _report_error_flags(driver); + if (drv->reset) { drv->state = TMC2660_STATE_RESET; drv->reset = 0; - } else if (++driver == TMC2660_NUM_DRIVERS) { + } else if (++driver == MOTORS) { driver = 0; spi_delay = 500; - //spi_state = SPI_STATE_QUIT; break; } break; @@ -217,19 +221,19 @@ void tmc2660_init() { memset(drivers, 0, sizeof(drivers)); // Configure motors - for (int i = 0; i < TMC2660_NUM_DRIVERS; i++) { + for (int i = 0; i < MOTORS; i++) { drivers[i].state = TMC2660_STATE_CONFIG; drivers[i].reg = 0; uint32_t mstep = 0; switch (MOTOR_MICROSTEPS) { - case 1: mstep = TMC2660_DRVCTRL_MRES_1; break; - case 2: mstep = TMC2660_DRVCTRL_MRES_2; break; - case 4: mstep = TMC2660_DRVCTRL_MRES_4; break; - case 8: mstep = TMC2660_DRVCTRL_MRES_8; break; - case 16: mstep = TMC2660_DRVCTRL_MRES_16; break; - case 32: mstep = TMC2660_DRVCTRL_MRES_32; break; - case 64: mstep = TMC2660_DRVCTRL_MRES_64; break; + case 1: mstep = TMC2660_DRVCTRL_MRES_1; break; + case 2: mstep = TMC2660_DRVCTRL_MRES_2; break; + case 4: mstep = TMC2660_DRVCTRL_MRES_4; break; + case 8: mstep = TMC2660_DRVCTRL_MRES_8; break; + case 16: mstep = TMC2660_DRVCTRL_MRES_16; break; + case 32: mstep = TMC2660_DRVCTRL_MRES_32; break; + case 64: mstep = TMC2660_DRVCTRL_MRES_64; break; case 128: mstep = TMC2660_DRVCTRL_MRES_128; break; case 256: mstep = TMC2660_DRVCTRL_MRES_256; break; default: break; // Invalid @@ -265,16 +269,11 @@ void tmc2660_init() { TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_MOSI_PIN; // High TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_MOSI_PIN; // Output - TMC2660_SPI_SSX_PORT.OUTSET = 1 << TMC2660_SPI_SSX_PIN; // High - TMC2660_SPI_SSX_PORT.DIRSET = 1 << TMC2660_SPI_SSX_PIN; // Output - TMC2660_SPI_SSY_PORT.OUTSET = 1 << TMC2660_SPI_SSY_PIN; // High - TMC2660_SPI_SSY_PORT.DIRSET = 1 << TMC2660_SPI_SSY_PIN; // Output - TMC2660_SPI_SSZ_PORT.OUTSET = 1 << TMC2660_SPI_SSZ_PIN; // High - TMC2660_SPI_SSZ_PORT.DIRSET = 1 << TMC2660_SPI_SSZ_PIN; // Output - TMC2660_SPI_SSA_PORT.OUTSET = 1 << TMC2660_SPI_SSA_PIN; // High - TMC2660_SPI_SSA_PORT.DIRSET = 1 << TMC2660_SPI_SSA_PIN; // Output - TMC2660_SPI_SSB_PORT.OUTSET = 1 << TMC2660_SPI_SSB_PIN; // High - TMC2660_SPI_SSB_PORT.DIRSET = 1 << TMC2660_SPI_SSB_PIN; // Output + for (int motor = 0; motor < MOTORS; motor++) { + hw.st_port[motor]->OUTSET = CHIP_SELECT_BIT_bm; // High + hw.st_port[motor]->DIRSET = CHIP_SELECT_BIT_bm; // Output + hw.st_port[motor]->DIRCLR = FAULT_BIT_bm; // Input + } // Configure SPI PR.PRPC &= ~PR_SPI_bm; // Disable power reduction @@ -292,12 +291,12 @@ void tmc2660_init() { uint8_t tmc2660_flags(int driver) { - return driver < TMC2660_NUM_DRIVERS ? drivers[driver].flags : 0; + return driver < MOTORS ? drivers[driver].flags : 0; } void tmc2660_reset(int driver) { - if (driver < TMC2660_NUM_DRIVERS) drivers[driver].reset = 1; + if (driver < MOTORS) drivers[driver].reset = 1; } @@ -308,29 +307,13 @@ int tmc2660_ready(int driver) { int tmc2660_all_ready() { - for (int i = 0; i < TMC2660_NUM_DRIVERS; i++) + for (int i = 0; i < MOTORS; i++) if (!tmc2660_ready(i)) return 0; return 1; } -void tmc2660_get_flags(uint8_t flags, char buf[35]) { - buf[0] = 0; - - if (TMC2660_DRVSTATUS_STST & flags) strcat(buf, "stst,"); - if (TMC2660_DRVSTATUS_OLB & flags) strcat(buf, "olb,"); - if (TMC2660_DRVSTATUS_OLA & flags) strcat(buf, "ola,"); - if (TMC2660_DRVSTATUS_S2GB & flags) strcat(buf, "s2gb,"); - if (TMC2660_DRVSTATUS_S2GA & flags) strcat(buf, "s2ga,"); - if (TMC2660_DRVSTATUS_OTPW & flags) strcat(buf, "otpw,"); - if (TMC2660_DRVSTATUS_OT & flags) strcat(buf, "ot,"); - if (TMC2660_DRVSTATUS_SG & flags) strcat(buf, "sg,"); - - if (buf[0] != 0) buf[strlen(buf) - 1] = 0; // Remove last comma -} - - uint8_t get_status_flags(int index) { return drivers[driver].flags; } diff --git a/src/tmc2660.h b/src/tmc2660.h index ef8605d..d0b7b8a 100644 --- a/src/tmc2660.h +++ b/src/tmc2660.h @@ -38,19 +38,6 @@ #define TMC2660_SPI_MISO_PIN 6 #define TMC2660_SPI_MOSI_PIN 7 -#define TMC2660_SPI_SSX_PORT PORTA -#define TMC2660_SPI_SSX_PIN 3 -#define TMC2660_SPI_SSY_PORT PORTF -#define TMC2660_SPI_SSY_PIN 3 -#define TMC2660_SPI_SSZ_PORT PORTE -#define TMC2660_SPI_SSZ_PIN 3 -#define TMC2660_SPI_SSA_PORT PORTD -#define TMC2660_SPI_SSA_PIN 3 -#define TMC2660_SPI_SSB_PORT PORTB -#define TMC2660_SPI_SSB_PIN 3 - -#define TMC2660_NUM_DRIVERS MOTORS - #define TMC2660_TIMER TCC1 void tmc2660_init(); @@ -140,13 +127,11 @@ int tmc2660_all_ready(); #define TMC2660_DRVCONF_RDSEL_SG (1UL << 4) #define TMC2660_DRVCONF_RDSEL_SGCS (2UL << 4) -#define TMC2660_DRVSTATUS_STST (1UL << 7) -#define TMC2660_DRVSTATUS_OLB (1UL << 6) -#define TMC2660_DRVSTATUS_OLA (1UL << 5) -#define TMC2660_DRVSTATUS_S2GB (1UL << 4) -#define TMC2660_DRVSTATUS_S2GA (1UL << 3) -#define TMC2660_DRVSTATUS_OTPW (1UL << 2) -#define TMC2660_DRVSTATUS_OT (1UL << 1) -#define TMC2660_DRVSTATUS_SG (1UL << 0) - - +#define TMC2660_DRVSTATUS_STANDSTILL (1UL << 7) +#define TMC2660_DRVSTATUS_OPEN_LOAD_B (1UL << 6) +#define TMC2660_DRVSTATUS_OPEN_LOAD_A (1UL << 5) +#define TMC2660_DRVSTATUS_SHORT_TO_GND_B (1UL << 4) +#define TMC2660_DRVSTATUS_SHORT_TO_GND_A (1UL << 3) +#define TMC2660_DRVSTATUS_OVERTEMP_WARN (1UL << 2) +#define TMC2660_DRVSTATUS_OVERTEMP (1UL << 1) +#define TMC2660_DRVSTATUS_STALLED (1UL << 0)