Switch, stepper and tmc2660 cleanup
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Mon, 21 Mar 2016 02:29:23 +0000 (19:29 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Mon, 21 Mar 2016 02:29:23 +0000 (19:29 -0700)
src/config.h
src/cycle_homing.c
src/cycle_probing.c
src/report.c
src/report.h
src/stepper.c
src/stepper.h
src/switch.c
src/switch.h
src/tmc2660.c
src/tmc2660.h

index c4f83bce14832c7d155d88f4062124aec345efb9..efb252170b5e154c214b9b9f7cbbbc3fa7515f46 100644 (file)
@@ -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)
index 9adca0f435b913aac31cef2a6c35c6e2b019bf37..7ae26591da402b3d6d28ff2eb9c60fb6e8a8f026 100644 (file)
@@ -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);
index 618a1de0a3dd579e49aa0bead3d580cdd0167f82..cf41111115f3ff443f8b1aa96b6877927223f3c5 100644 (file)
@@ -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
index dde3e0c775978e5bc174ba75d5833c1a59a660b9..e4e7d7e22750f78030af05e92120d5a9c42a6b65 100644 (file)
@@ -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;
index f42c963cf62f40d61f9a4b36bdd6a4472fa93db7..b05360ae92d974c4d31ddd8608e553f0a5912725 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "status.h"
 
-void report_init();
 void report_request();
 void report_request_full();
 stat_t report_callback();
index 8a88d7c85a4d133d43d8a80228cc7ce823c24517..9513c06098994fc3d8ab32840906dac6d87ea6be 100644 (file)
@@ -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);
 }
 
 
index 0d93adcb4e1bb431e53085acb719c75409bc47a4..69229c56defaad3607d174720841c9720e843e43 100644 (file)
@@ -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();
index 8b94cb0753f03c8b3bd3123fd299adb423f354d6..6fac71e91497d08f6cfa57a0ddea1343dfdc6687 100644 (file)
@@ -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"
 #include <stdbool.h>
 
 
+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;
 }
index cbc537bb817e510e52d796f6e335a4026e58bdc6..03014558e274be6a992297c30089e99f23663489 100644 (file)
 #include "config.h"
 
 #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
 
 // 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();
index 00ee69a7460bdfb5878639ca05fa155d907f8a50..e00e93be54aeef05f6b9faa7f0db5386864f4327 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "tmc2660.h"
 #include "status.h"
+#include "stepper.h"
+#include "hardware.h"
 
 #include <avr/io.h>
 #include <avr/interrupt.h>
@@ -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;
 }
index ef8605de680653ffbf81f75738fd82350bfcef41..d0b7b8aed5754fd3289546be7a666674e1b1d085 100644 (file)
 #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)