Preliminary TMC2660 driver
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 2 Jan 2016 06:04:06 +0000 (22:04 -0800)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 2 Jan 2016 06:04:06 +0000 (22:04 -0800)
12 files changed:
Makefile
src/config.h
src/controller.h
src/hardware.h
src/main.c
src/report.c
src/report.h
src/stepper.c
src/tmc2660.c [new file with mode: 0644]
src/tmc2660.h [new file with mode: 0644]
src/usart.c
src/usart.h

index b4d1208320ae178b4cc57c17b2e17a6d7d9c8a3c..1db20ee921302754495ca9a1d273b668d11a70f8 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Makefile for the project TinyG firmware
 PROJECT = tinyg
-MCU     = atxmega192a3
+MCU     = atxmega192a3u
 CLOCK   = 32000000
 
 TARGET  = $(PROJECT).elf
@@ -12,8 +12,8 @@ CPP = avr-g++
 COMMON = -mmcu=$(MCU)
 
 CFLAGS += $(COMMON)
-CFLAGS += -gdwarf-2 -std=gnu99 -Wall -Werror -DF_CPU=$(CLOCK)UL -Os -funsigned-char
-CFLAGS += -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -gdwarf-2 -std=gnu99 -Wall -Werror -DF_CPU=$(CLOCK)UL -Os
+CFLAGS += -funsigned-bitfields -fpack-struct -fshort-enums -funsigned-char
 CFLAGS += -MD -MP -MT $@ -MF build/dep/$(@F).d
 
 # Linker flags
index 2d80ff9cfdfa63ceb6857b22d4986cfe135aad60..078f5a0814a41adea4927eb37606c39e812564b9 100644 (file)
  *    largest possible operation - usually the status report.
  */
 
-/***********************************************************************************
- **** DEFINITIONS AND SETTINGS *****************************************************
- ***********************************************************************************/
+#include <stdint.h>
 
 // Sizing and footprints                // chose one based on # of elements in cfgArray
-//typedef uint8_t index_t;                // use this if there are < 256 indexed objects
-typedef uint16_t index_t;                // use this if there are > 255 indexed objects
+//typedef uint8_t index_t;               // use this if there are < 256 indexed objects
+typedef uint16_t index_t;               // use this if there are > 255 indexed objects
 
                                         // defines allocated from stack (not-pre-allocated)
-#define NV_FORMAT_LEN 128                // print formatting string max length
-#define NV_MESSAGE_LEN 128                // sufficient space to contain end-user messages
+#define NV_FORMAT_LEN 128               // print formatting string max length
+#define NV_MESSAGE_LEN 128              // sufficient space to contain end-user messages
 
                                         // pre-allocated defines (take RAM permanently)
 #define NV_SHARED_STRING_LEN 512        // shared string for string values
-#define NV_BODY_LEN 30                    // body elements - allow for 1 parent + N children
+#define NV_BODY_LEN 30                  // body elements - allow for 1 parent + N children
                                         // (each body element takes about 30 bytes of RAM)
 
 // Stuff you probably don't want to change
 
-#define GROUP_LEN 3                        // max length of group prefix
-#define TOKEN_LEN 5                        // mnemonic token string: group prefix + short token
-#define NV_FOOTER_LEN 18                // sufficient space to contain a JSON footer array
-#define NV_LIST_LEN (NV_BODY_LEN+2)        // +2 allows for a header and a footer
-#define NV_MAX_OBJECTS (NV_BODY_LEN-1)    // maximum number of objects in a body string
+#define GROUP_LEN 3                      // max length of group prefix
+#define TOKEN_LEN 5                      // mnemonic token string: group prefix + short token
+#define NV_FOOTER_LEN 18                 // sufficient space to contain a JSON footer array
+#define NV_LIST_LEN (NV_BODY_LEN+2)      // +2 allows for a header and a footer
+#define NV_MAX_OBJECTS (NV_BODY_LEN-1)   // maximum number of objects in a body string
 #define NO_MATCH (index_t)0xFFFF
 #define NV_STATUS_REPORT_LEN NV_MAX_OBJECTS // max number of status report elements - see cfgArray
                                             // **** must also line up in cfgArray, se00 - seXX ****
 
 enum tgCommunicationsMode {
-    TEXT_MODE = 0,                        // text command line mode
-    JSON_MODE,                            // strict JSON construction
+    TEXT_MODE = 0,                       // text command line mode
+    JSON_MODE,                           // strict JSON construction
     JSON_MODE_RELAXED                    // relaxed JSON construction (future)
 };
 
 enum flowControl {
-    FLOW_CONTROL_OFF = 0,                // flow control disabled
-    FLOW_CONTROL_XON,                    // flow control uses XON/XOFF
+    FLOW_CONTROL_OFF = 0,               // flow control disabled
+    FLOW_CONTROL_XON,                   // flow control uses XON/XOFF
     FLOW_CONTROL_RTS                    // flow control uses RTS/CTS
 };
 
-/*
-enum lineTermination {                    // REMOVED. Too easy to make the board non-responsive (not a total brick, but close)
-    IGNORE_OFF = 0,                        // accept either CR or LF as termination on RX text line
-    IGNORE_CR,                            // ignore CR on RX
-    IGNORE_LF                            // ignore LF on RX
-};
-*/
-/*
-enum tgCommunicationsSticky {
-    NOT_STICKY = 0,                        // communications mode changes automatically
-    STICKY                                // communications mode does not change
-};
-*/
-
 enum valueType {                        // value typing for config and JSON
     TYPE_EMPTY = -1,                    // value struct is empty (which is not the same as "0")
-    TYPE_0 = 0,                        // value is 'null' (meaning the JSON null value)
-    TYPE_BOOL,                            // value is "true" (1) or "false"(0)
-    TYPE_INTEGER,                        // value is a uint32_t
-    TYPE_DATA,                            // value is blind cast to uint32_t
-    TYPE_FLOAT,                            // value is a floating point number
+    TYPE_0 = 0,                         // value is 'null' (meaning the JSON null value)
+    TYPE_BOOL,                          // value is "true" (1) or "false"(0)
+    TYPE_INTEGER,                       // value is a uint32_t
+    TYPE_DATA,                          // value is blind cast to uint32_t
+    TYPE_FLOAT,                         // value is a floating point number
     TYPE_STRING,                        // value is in string field
-    TYPE_ARRAY,                            // value is array element count, values are CSV ASCII in string field
-    TYPE_PARENT                            // object is a parent to a sub-object
+    TYPE_ARRAY,                         // value is array element count, values are CSV ASCII in string field
+    TYPE_PARENT                         // object is a parent to a sub-object
 };
 
 /**** operations flags and shorthand ****/
 
 #define F_INITIALIZE    0x01            // initialize this item (run set during initialization)
-#define F_PERSIST         0x02            // persist this item when set is run
-#define F_NOSTRIP        0x04            // do not strip the group prefix from the token
-#define F_CONVERT        0x08            // set if unit conversion is required
-
-#define _f0                0x00
-#define _fi                (F_INITIALIZE)
-#define _fp                (F_PERSIST)
-#define _fn                (F_NOSTRIP)
-#define _fc                (F_CONVERT)
+#define F_PERSIST       0x02            // persist this item when set is run
+#define F_NOSTRIP       0x04            // do not strip the group prefix from the token
+#define F_CONVERT       0x08            // set if unit conversion is required
+
+#define _f0             0x00
+#define _fi             (F_INITIALIZE)
+#define _fp             (F_PERSIST)
+#define _fn             (F_NOSTRIP)
+#define _fc             (F_CONVERT)
 #define _fip            (F_INITIALIZE | F_PERSIST)
-#define _fipc            (F_INITIALIZE | F_PERSIST | F_CONVERT)
-#define _fipn            (F_INITIALIZE | F_PERSIST | F_NOSTRIP)
-#define _fipnc            (F_INITIALIZE | F_PERSIST | F_NOSTRIP | F_CONVERT)
+#define _fipc           (F_INITIALIZE | F_PERSIST | F_CONVERT)
+#define _fipn           (F_INITIALIZE | F_PERSIST | F_NOSTRIP)
+#define _fipnc          (F_INITIALIZE | F_PERSIST | F_NOSTRIP | F_CONVERT)
 
 /**** Structures ****/
 
index 9a85b53d63cd3d63c848319d318e7a70e98328d7..5d5421d671920bbc12a8976213cebffa5f4739b6 100644 (file)
@@ -70,9 +70,9 @@ extern controller_t cs;                    // controller state structure
 
 enum cmControllerState {                // manages startup lines
     CONTROLLER_INITIALIZING = 0,        // controller is initializing - not ready for use
-    CONTROLLER_NOT_CONNECTED,            // controller has not yet detected connection to USB (or other comm channel)
-    CONTROLLER_CONNECTED,                // controller has connected to USB (or other comm channel)
-    CONTROLLER_STARTUP,                    // controller is running startup messages and lines
+    CONTROLLER_NOT_CONNECTED,           // controller has not yet detected connection to comm channel
+    CONTROLLER_CONNECTED,               // controller has connected to comm channel
+    CONTROLLER_STARTUP,                 // controller is running startup messages and lines
     CONTROLLER_READY                    // controller is active and ready for use
 };
 
index 0cf848ff2e43a0d7abcce67b539f35e1bad050c7..9c40629b600fd1b9f794a26f6dd43ca6fbb2da0a 100644 (file)
@@ -36,8 +36,8 @@
  *    HI    Dwell timer counter                  (set in stepper.h)
  *    LO    Segment execution SW interrupt       (set in stepper.h)
  *   MED    GPIO1 switch port                    (set in gpio.h)
- *   MED    Serial RX for USB & RS-485           (set in usart.c)
- *   MED    Serial TX for USB & RS-485           (set in usart.c) (* see note)
+ *   MED    Serial RX                            (set in usart.c)
+ *   MED    Serial TX                            (set in usart.c) (* see note)
  *    LO    Real time clock interrupt            (set in xmega_rtc.h)
  *
  *    (*) The TX cannot run at LO level or exception reports and other prints
 #ifndef HARDWARE_H_ONCE
 #define HARDWARE_H_ONCE
 
-/*--- Hardware platform enumerations ---*/
-
 enum hwPlatform {
   HM_PLATFORM_NONE = 0,
-
   HW_PLATFORM_TINYG_XMEGA,    // TinyG code base on Xmega boards.
-  //    hwVersion 7 = TinyG v7 and earlier
-  //    hwVersion 8 = TinyG v8
-
-  HW_PLATFORM_G2_DUE,            // G2 code base on native Arduino Due
-
-  HW_PLATFORM_TINYG_V9        // G2 code base on v9 boards
-  //  hwVersion 0 = v9c
-  //  hwVersion 1 = v9d
-  //  hwVersion 2 = v9f
-  //  hwVersion 3 = v9h
-  //  hwVersion 4 = v9i
 };
 
-#define HW_VERSION_TINYGV6        6
-#define HW_VERSION_TINYGV7        7
-#define HW_VERSION_TINYGV8        8
-
-#define HW_VERSION_TINYGV9C        0
-#define HW_VERSION_TINYGV9D        1
-#define HW_VERSION_TINYGV9F        2
-#define HW_VERSION_TINYGV9H        3
-#define HW_VERSION_TINYGV9I        4
+#define HW_VERSION_TINYGV6 6
+#define HW_VERSION_TINYGV7 7
+#define HW_VERSION_TINYGV8 8
 
 #include "config.h"                        // needed for the stat_t typedef
 #include <avr/interrupt.h>
@@ -95,40 +75,40 @@ enum hwPlatform {
  *** These are not all the same, and must line up in multiple places in gpio.h ***
  * Sorry if this is confusing - it's a board routing issue
  */
-#define PORT_MOTOR_1    PORTA            // motors mapped to ports
+#define PORT_MOTOR_1     PORTA            // motors mapped to ports
 #define PORT_MOTOR_2     PORTF
-#define PORT_MOTOR_3    PORTE
-#define PORT_MOTOR_4    PORTD
+#define PORT_MOTOR_3     PORTE
+#define PORT_MOTOR_4     PORTD
 
-#define PORT_SWITCH_X     PORTA            // Switch axes mapped to ports
-#define PORT_SWITCH_Y     PORTD
-#define PORT_SWITCH_Z     PORTE
-#define PORT_SWITCH_A     PORTF
+#define PORT_SWITCH_X    PORTA            // Switch axes mapped to ports
+#define PORT_SWITCH_Y    PORTD
+#define PORT_SWITCH_Z    PORTE
+#define PORT_SWITCH_A    PORTF
 
 #define PORT_OUT_V7_X    PORTA            // v7 mapping - Output bits mapped to ports
-#define PORT_OUT_V7_Y     PORTF
+#define PORT_OUT_V7_Y    PORTF
 #define PORT_OUT_V7_Z    PORTD
 #define PORT_OUT_V7_A    PORTE
 
 #define PORT_OUT_V6_X    PORTA            // v6 and earlier mapping - Output bits mapped to ports
-#define PORT_OUT_V6_Y     PORTF
+#define PORT_OUT_V6_Y    PORTF
 #define PORT_OUT_V6_Z    PORTE
 #define PORT_OUT_V6_A    PORTD
 
 // These next four must be changed when the PORT_MOTOR_* definitions change!
-#define PORTCFG_VP0MAP_PORT_MOTOR_1_gc PORTCFG_VP0MAP_PORTA_gc
-#define PORTCFG_VP1MAP_PORT_MOTOR_2_gc PORTCFG_VP1MAP_PORTF_gc
-#define PORTCFG_VP2MAP_PORT_MOTOR_3_gc PORTCFG_VP2MAP_PORTE_gc
-#define PORTCFG_VP3MAP_PORT_MOTOR_4_gc PORTCFG_VP3MAP_PORTD_gc
+#define PORTCFG_VP0MAP_PORT_MOTOR_1_gc PORTCFG_VP02MAP_PORTA_gc
+#define PORTCFG_VP1MAP_PORT_MOTOR_2_gc PORTCFG_VP13MAP_PORTF_gc
+#define PORTCFG_VP2MAP_PORT_MOTOR_3_gc PORTCFG_VP02MAP_PORTE_gc
+#define PORTCFG_VP3MAP_PORT_MOTOR_4_gc PORTCFG_VP13MAP_PORTD_gc
 
-#define PORT_MOTOR_1_VPORT    VPORT0
-#define PORT_MOTOR_2_VPORT    VPORT1
-#define PORT_MOTOR_3_VPORT    VPORT2
-#define PORT_MOTOR_4_VPORT    VPORT3
+#define PORT_MOTOR_1_VPORT VPORT0
+#define PORT_MOTOR_2_VPORT VPORT1
+#define PORT_MOTOR_3_VPORT VPORT2
+#define PORT_MOTOR_4_VPORT VPORT3
 
 /*
  * Port setup - Stepper / Switch Ports:
- *    b0    (out) step            (SET is step,  CLR is rest)
+ *    b0    (out) step             (SET is step,  CLR is rest)
  *    b1    (out) direction        (CLR = Clockwise)
  *    b2    (out) motor enable     (CLR = Enabled)
  *    b3    (out) microstep 0
@@ -139,33 +119,33 @@ enum hwPlatform {
  */
 #define MOTOR_PORT_DIR_gm 0x3F    // dir settings: lower 6 out, upper 2 in
 
-enum cfgPortBits {            // motor control port bit positions
+enum cfgPortBits {        // motor control port bit positions
   STEP_BIT_bp = 0,        // bit 0
-  DIRECTION_BIT_bp,        // bit 1
+  DIRECTION_BIT_bp,       // bit 1
   MOTOR_ENABLE_BIT_bp,    // bit 2
-  MICROSTEP_BIT_0_bp,        // bit 3
-  MICROSTEP_BIT_1_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)
+  MICROSTEP_BIT_0_bp,     // bit 3
+  MICROSTEP_BIT_1_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)
 };
 
-#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 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
+#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 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
 
 /* Bit assignments for GPIO1_OUTs for spindle, PWM and coolant */
 
 #define SPINDLE_BIT            0x08        // spindle on/off
 #define SPINDLE_DIR            0x04        // spindle direction, 1=CW, 0=CCW
 #define SPINDLE_PWM            0x02        // spindle PWMs output bit
-#define MIST_COOLANT_BIT    0x01        // coolant on/off - these are the same due to limited ports
-#define FLOOD_COOLANT_BIT    0x01        // coolant on/off
+#define MIST_COOLANT_BIT       0x01        // coolant on/off - these are the same due to limited ports
+#define FLOOD_COOLANT_BIT      0x01        // coolant on/off
 
 #define SPINDLE_LED            0
 #define SPINDLE_DIR_LED        1
@@ -177,47 +157,47 @@ enum cfgPortBits {            // motor control port bit positions
 /* Timer assignments - see specific modules for details) */
 
 #define TIMER_DDA            TCC0        // DDA timer     (see stepper.h)
-#define TIMER_DWELL             TCD0        // Dwell timer    (see stepper.h)
-#define TIMER_LOAD            TCE0        // Loader timer    (see stepper.h)
-#define TIMER_EXEC            TCF0        // Exec timer    (see stepper.h)
-#define TIMER_5                TCC1        // unallocated timer
-#define TIMER_PWM1            TCD1        // PWM timer #1 (see pwm.c)
-#define TIMER_PWM2            TCE1        // PWM timer #2    (see pwm.c)
+#define TIMER_DWELL          TCD0        // Dwell timer   (see stepper.h)
+#define TIMER_LOAD           TCE0        // Loader time   (see stepper.h)
+#define TIMER_EXEC           TCF0        // Exec timer    (see stepper.h)
+#define TIMER_TMC2660        TCC1        // TMC2660 timer (see tmc2660.h)
+#define TIMER_PWM1           TCD1        // PWM timer #1  (see pwm.c)
+#define TIMER_PWM2           TCE1        // PWM timer #2  (see pwm.c)
 
 /* Timer setup for stepper and dwells */
 
-#define FREQUENCY_DDA         (float)50000    // DDA frequency in hz.
+#define FREQUENCY_DDA          (float)50000    // DDA frequency in hz.
 #define FREQUENCY_DWELL        (float)10000    // Dwell count frequency in hz.
-#define LOAD_TIMER_PERIOD     100                // cycles you have to shut off SW interrupt
-#define EXEC_TIMER_PERIOD     100                // cycles you have to shut off SW interrupt
-#define EXEC_TIMER_PERIOD_LONG 100            // cycles you have to shut off SW interrupt
+#define LOAD_TIMER_PERIOD      100             // cycles you have to shut off SW interrupt
+#define EXEC_TIMER_PERIOD      100             // cycles you have to shut off SW interrupt
+#define EXEC_TIMER_PERIOD_LONG 100             // cycles you have to shut off SW interrupt
 
-#define STEP_TIMER_TYPE        TC0_struct         // stepper subsybstem uses all the TC0's
+#define STEP_TIMER_TYPE        TC0_struct       // stepper subsybstem uses all the TC0's
 #define STEP_TIMER_DISABLE     0                // turn timer off (clock = 0 Hz)
-#define STEP_TIMER_ENABLE    1                // turn timer clock on (F_CPU = 32 Mhz)
-#define STEP_TIMER_WGMODE    0                // normal mode (count to TOP and rollover)
+#define STEP_TIMER_ENABLE      1                // turn timer clock on (F_CPU = 32 Mhz)
+#define STEP_TIMER_WGMODE      0                // normal mode (count to TOP and rollover)
 
 #define LOAD_TIMER_DISABLE     0                // turn load timer off (clock = 0 Hz)
-#define LOAD_TIMER_ENABLE    1                // turn load timer clock on (F_CPU = 32 Mhz)
-#define LOAD_TIMER_WGMODE    0                // normal mode (count to TOP and rollover)
+#define LOAD_TIMER_ENABLE      1                // turn load timer clock on (F_CPU = 32 Mhz)
+#define LOAD_TIMER_WGMODE      0                // normal mode (count to TOP and rollover)
 
 #define EXEC_TIMER_DISABLE     0                // turn exec timer off (clock = 0 Hz)
-#define EXEC_TIMER_ENABLE    1                // turn exec timer clock on (F_CPU = 32 Mhz)
-#define EXEC_TIMER_WGMODE    0                // normal mode (count to TOP and rollover)
+#define EXEC_TIMER_ENABLE      1                // turn exec timer clock on (F_CPU = 32 Mhz)
+#define EXEC_TIMER_WGMODE      0                // normal mode (count to TOP and rollover)
 
-#define TIMER_DDA_ISR_vect    TCC0_OVF_vect    // must agree with assignment in system.h
-#define TIMER_DWELL_ISR_vect TCD0_OVF_vect    // must agree with assignment in system.h
+#define TIMER_DDA_ISR_vect     TCC0_OVF_vect    // must agree with assignment in system.h
+#define TIMER_DWELL_ISR_vect   TCD0_OVF_vect    // must agree with assignment in system.h
 #define TIMER_LOAD_ISR_vect    TCE0_OVF_vect    // must agree with assignment in system.h
 #define TIMER_EXEC_ISR_vect    TCF0_OVF_vect    // must agree with assignment in system.h
 
-#define TIMER_OVFINTLVL_HI    3                // timer interrupt level (3=hi)
-#define    TIMER_OVFINTLVL_MED 2;                // timer interrupt level (2=med)
-#define    TIMER_OVFINTLVL_LO  1;                // timer interrupt level (1=lo)
+#define TIMER_OVFINTLVL_HI     3                // timer interrupt level (3=hi)
+#define TIMER_OVFINTLVL_MED    2                // timer interrupt level (2=med)
+#define TIMER_OVFINTLVL_LO     1                // timer interrupt level (1=lo)
 
-#define TIMER_DDA_INTLVL     TIMER_OVFINTLVL_HI
-#define TIMER_DWELL_INTLVL    TIMER_OVFINTLVL_HI
-#define TIMER_LOAD_INTLVL    TIMER_OVFINTLVL_HI
-#define TIMER_EXEC_INTLVL    TIMER_OVFINTLVL_LO
+#define TIMER_DDA_INTLVL       TIMER_OVFINTLVL_HI
+#define TIMER_DWELL_INTLVL     TIMER_OVFINTLVL_HI
+#define TIMER_LOAD_INTLVL      TIMER_OVFINTLVL_HI
+#define TIMER_EXEC_INTLVL      TIMER_OVFINTLVL_LO
 
 
 /**** Device singleton - global structure to allow iteration through similar devices ****/
@@ -236,11 +216,11 @@ enum cfgPortBits {            // motor control port bit positions
 typedef struct hmSingleton {
   PORT_t *st_port[MOTORS];        // bindings for stepper motor ports (stepper.c)
   PORT_t *sw_port[MOTORS];        // bindings for switch ports (GPIO2)
-  PORT_t *out_port[MOTORS];        // bindings for output ports (GPIO1)
+  PORT_t *out_port[MOTORS];       // bindings for output ports (GPIO1)
 } hwSingleton_t;
 hwSingleton_t hw;
 
-void hardware_init();            // master hardware init
+void hardware_init();             // master hardware init
 void hw_request_hard_reset();
 void hw_hard_reset();
 stat_t hw_hard_reset_handler();
index 0f8a1b7a1f080bd858dd35d716445b44b765877e..0696c06ce320adf8ec6de69a1f5c5de52a82fca0 100644 (file)
@@ -32,6 +32,7 @@
 #include "test.h"
 #include "pwm.h"
 #include "usart.h"
+#include "tmc2660.h"
 
 #include <avr/interrupt.h>
 #include "xmega/xmega_interrupts.h"
@@ -50,6 +51,7 @@ static void init() {
   usart_init();                   // serial port
 
   // do these next
+  tmc2660_init();                 // motor drivers
   stepper_init();                 // stepper subsystem
   encoder_init();                 // virtual encoders
   switch_init();                  // switches
index 96dc2ff9c099a524d41a33f91c9a94d495c0a6e9..b5289e5be82b1bae3a6f00dac2bd6d5937622503 100644 (file)
@@ -52,16 +52,16 @@ rxSingleton_t rx;
  */
 stat_t rpt_exception(uint8_t status)
 {
-    if (status != STAT_OK) {    // makes it possible to call exception reports w/o checking status value
-        if (js.json_syntax == JSON_SYNTAX_RELAXED) {
-            printf_P(PSTR("{er:{fb:%0.2f,st:%d,msg:\"%s\"}}\n"),
-                TINYG_FIRMWARE_BUILD, status, get_status_message(status));
-        } else {
-            printf_P(PSTR("{\"er\":{\"fb\":%0.2f,\"st\":%d,\"msg\":\"%s\"}}\n"),
-                TINYG_FIRMWARE_BUILD, status, get_status_message(status));
-        }
+  if (status != STAT_OK) {    // makes it possible to call exception reports w/o checking status value
+    if (js.json_syntax == JSON_SYNTAX_RELAXED) {
+      printf_P(PSTR("{er:{fb:%0.2f,st:%d,msg:\"%s\"}}\n"),
+               TINYG_FIRMWARE_BUILD, status, get_status_message(status));
+    } else {
+      printf_P(PSTR("{\"er\":{\"fb\":%0.2f,\"st\":%d,\"msg\":\"%s\"}}\n"),
+               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 *********************************************************
@@ -84,33 +84,33 @@ stat_t rpt_er(nvObj_t *nv)
 void _startup_helper(stat_t status, const char *msg)
 {
 #ifndef __SUPPRESS_STARTUP_MESSAGES
-    js.json_footer_depth = JSON_FOOTER_DEPTH;    //++++ temporary until changeover is complete
-    nv_reset_nv_list();
-    nv_add_object((const char_t *)"fv");        // firmware version
-    nv_add_object((const char_t *)"fb");        // firmware build
-    nv_add_object((const char_t *)"hp");        // hardware platform
-    nv_add_object((const char_t *)"hv");        // hardware version
-    nv_add_object((const char_t *)"id");        // hardware ID
-    nv_add_string((const char_t *)"msg", pstr2str(msg));    // startup message
-    json_print_response(status);
+  js.json_footer_depth = JSON_FOOTER_DEPTH;    //++++ temporary until changeover is complete
+  nv_reset_nv_list();
+  nv_add_object((const char_t *)"fv");        // firmware version
+  nv_add_object((const char_t *)"fb");        // firmware build
+  nv_add_object((const char_t *)"hp");        // hardware platform
+  nv_add_object((const char_t *)"hv");        // hardware version
+  nv_add_object((const char_t *)"id");        // hardware ID
+  nv_add_string((const char_t *)"msg", pstr2str(msg));    // startup message
+  json_print_response(status);
 #endif
 }
 
 void rpt_print_initializing_message()
 {
-    _startup_helper(STAT_INITIALIZING, PSTR(INIT_MESSAGE));
+  _startup_helper(STAT_INITIALIZING, PSTR(INIT_MESSAGE));
 }
 
 void rpt_print_loading_configs_message()
 {
-    _startup_helper(STAT_INITIALIZING, PSTR("Loading configs from EEPROM"));
+  _startup_helper(STAT_INITIALIZING, PSTR("Loading configs from EEPROM"));
 }
 
 void rpt_print_system_ready_message()
 {
-    _startup_helper(STAT_OK, PSTR("SYSTEM READY"));
-    if (cfg.comm_mode == TEXT_MODE)
-        text_response(STAT_OK, (char_t *)"");   // prompt
+  _startup_helper(STAT_OK, PSTR("SYSTEM READY"));
+  if (cfg.comm_mode == TEXT_MODE)
+    text_response(STAT_OK, (char_t *)"");   // prompt
 }
 
 /*****************************************************************************
@@ -160,11 +160,11 @@ static uint8_t _populate_filtered_status_report();
 
 uint8_t _is_stat(nvObj_t *nv)
 {
-    char_t tok[TOKEN_LEN+1];
+  char_t tok[TOKEN_LEN+1];
 
-    GET_TOKEN_STRING(nv->value, tok);
-    if (strcmp(tok, "stat") == 0) { return true;}
-    return false;
+  GET_TOKEN_STRING(nv->value, tok);
+  if (strcmp(tok, "stat") == 0) { return true;}
+  return false;
 }
 
 /*
@@ -175,26 +175,26 @@ uint8_t _is_stat(nvObj_t *nv)
  */
 void sr_init_status_report()
 {
-    nvObj_t *nv = nv_reset_nv_list();    // used for status report persistence locations
-    sr.status_report_requested = false;
-    char_t sr_defaults[NV_STATUS_REPORT_LEN][TOKEN_LEN+1] = { STATUS_REPORT_DEFAULTS };    // see settings.h
-    nv->index = nv_get_index((const char_t *)"", (const char_t *)"se00");    // set first SR persistence index
-    sr.stat_index = 0;
-
-    for (uint8_t i=0; i < NV_STATUS_REPORT_LEN ; i++) {
-        if (sr_defaults[i][0] == 0) break;                // quit on first blank array entry
-        sr.status_report_value[i] = -1234567;                // pre-load values with an unlikely number
-        nv->value = nv_get_index((const char_t *)"", sr_defaults[i]);// load the index for the SR element
-        if (nv->value == NO_MATCH) {
-            rpt_exception(STAT_BAD_STATUS_REPORT_SETTING);    // trap mis-configured profile settings
-            return;
-        }
-        if (_is_stat(nv) == true)
-            sr.stat_index = nv->value;                        // identify index for 'stat' if status is in the report
-        nv_set(nv);
-        nv_persist(nv);                                        // conditionally persist - automatic by nv_persist()
-        nv->index++;                                        // increment SR NVM index
+  nvObj_t *nv = nv_reset_nv_list();    // used for status report persistence locations
+  sr.status_report_requested = false;
+  char_t sr_defaults[NV_STATUS_REPORT_LEN][TOKEN_LEN+1] = { STATUS_REPORT_DEFAULTS };    // see settings.h
+  nv->index = nv_get_index((const char_t *)"", (const char_t *)"se00");    // set first SR persistence index
+  sr.stat_index = 0;
+
+  for (uint8_t i=0; i < NV_STATUS_REPORT_LEN ; i++) {
+    if (sr_defaults[i][0] == 0) break;                // quit on first blank array entry
+    sr.status_report_value[i] = -1234567;                // pre-load values with an unlikely number
+    nv->value = nv_get_index((const char_t *)"", sr_defaults[i]);// load the index for the SR element
+    if (nv->value == NO_MATCH) {
+      rpt_exception(STAT_BAD_STATUS_REPORT_SETTING);    // trap mis-configured profile settings
+      return;
     }
+    if (_is_stat(nv) == true)
+      sr.stat_index = nv->value;                        // identify index for 'stat' if status is in the report
+    nv_set(nv);
+    nv_persist(nv);                                        // conditionally persist - automatic by nv_persist()
+    nv->index++;                                        // increment SR NVM index
+  }
 }
 
 /*
@@ -206,27 +206,27 @@ void sr_init_status_report()
  */
 stat_t sr_set_status_report(nvObj_t *nv)
 {
-    uint8_t elements = 0;
-    index_t status_report_list[NV_STATUS_REPORT_LEN];
-    memset(status_report_list, 0, sizeof(status_report_list));
-    index_t sr_start = nv_get_index((const char_t *)"",(const char_t *)"se00");// set first SR persistence index
-
-    for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
-        if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) break;
-        if ((nv->valuetype == TYPE_BOOL) && (fp_TRUE(nv->value))) {
-            status_report_list[i] = nv->index;
-            nv->value = nv->index;                            // persist the index as the value
-            nv->index = sr_start + i;                        // index of the SR persistence location
-            nv_persist(nv);
-            elements++;
-        } else {
-            return STAT_UNRECOGNIZED_NAME;
-        }
+  uint8_t elements = 0;
+  index_t status_report_list[NV_STATUS_REPORT_LEN];
+  memset(status_report_list, 0, sizeof(status_report_list));
+  index_t sr_start = nv_get_index((const char_t *)"",(const char_t *)"se00");// set first SR persistence index
+
+  for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
+    if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) break;
+    if ((nv->valuetype == TYPE_BOOL) && (fp_TRUE(nv->value))) {
+      status_report_list[i] = nv->index;
+      nv->value = nv->index;                            // persist the index as the value
+      nv->index = sr_start + i;                        // index of the SR persistence location
+      nv_persist(nv);
+      elements++;
+    } else {
+      return STAT_UNRECOGNIZED_NAME;
     }
-    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
+  }
+  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
 }
 
 /*
@@ -243,42 +243,42 @@ stat_t sr_set_status_report(nvObj_t *nv)
  */
 stat_t sr_request_status_report(uint8_t request_type)
 {
-    if (request_type == SR_IMMEDIATE_REQUEST) {
-        sr.status_report_systick = SysTickTimer_getValue();
-    }
-    if ((request_type == SR_TIMED_REQUEST) && (sr.status_report_requested == false)) {
-        sr.status_report_systick = SysTickTimer_getValue() + sr.status_report_interval;
-    }
-    sr.status_report_requested = true;
-    return STAT_OK;
+  if (request_type == SR_IMMEDIATE_REQUEST) {
+    sr.status_report_systick = SysTickTimer_getValue();
+  }
+  if ((request_type == SR_TIMED_REQUEST) && (sr.status_report_requested == false)) {
+    sr.status_report_systick = SysTickTimer_getValue() + sr.status_report_interval;
+  }
+  sr.status_report_requested = true;
+  return STAT_OK;
 }
 
 stat_t sr_status_report_callback()         // called by controller dispatcher
 {
 #ifdef __SUPPRESS_STATUS_REPORTS
-    return STAT_NOOP;
+  return STAT_NOOP;
 #endif
 
-    if (sr.status_report_verbosity == SR_OFF)
-        return STAT_NOOP;
+  if (sr.status_report_verbosity == SR_OFF)
+    return STAT_NOOP;
 
-    if (sr.status_report_requested == false)
-        return STAT_NOOP;
+  if (sr.status_report_requested == false)
+    return STAT_NOOP;
 
-    if (SysTickTimer_getValue() < sr.status_report_systick)
-        return STAT_NOOP;
+  if (SysTickTimer_getValue() < sr.status_report_systick)
+    return STAT_NOOP;
 
-    sr.status_report_requested = false;        // disable reports until requested again
+  sr.status_report_requested = false;        // disable reports until requested again
 
-    if (sr.status_report_verbosity == SR_VERBOSE) {
-        _populate_unfiltered_status_report();
-    } else {
-        if (_populate_filtered_status_report() == false) {    // no new data
-            return STAT_OK;
-        }
+  if (sr.status_report_verbosity == SR_VERBOSE) {
+    _populate_unfiltered_status_report();
+  } else {
+    if (_populate_filtered_status_report() == false) {    // no new data
+      return STAT_OK;
     }
-    nv_print_list(STAT_OK, TEXT_INLINE_PAIRS, JSON_OBJECT_FORMAT);
-    return STAT_OK;
+  }
+  nv_print_list(STAT_OK, TEXT_INLINE_PAIRS, JSON_OBJECT_FORMAT);
+  return STAT_OK;
 }
 
 /*
@@ -286,9 +286,9 @@ stat_t sr_status_report_callback()         // called by controller dispatcher
  */
 stat_t sr_run_text_status_report()
 {
-    _populate_unfiltered_status_report();
-    nv_print_list(STAT_OK, TEXT_MULTILINE_FORMATTED, JSON_RESPONSE_FORMAT);
-    return STAT_OK;
+  _populate_unfiltered_status_report();
+  nv_print_list(STAT_OK, TEXT_MULTILINE_FORMATTED, JSON_RESPONSE_FORMAT);
+  return STAT_OK;
 }
 
 /*
@@ -298,27 +298,27 @@ stat_t sr_run_text_status_report()
  */
 static stat_t _populate_unfiltered_status_report()
 {
-    const char_t sr_str[] = "sr";
-    char_t tmp[TOKEN_LEN+1];
-    nvObj_t *nv = nv_reset_nv_list();        // sets *nv to the start of the body
-
-    nv->valuetype = TYPE_PARENT;             // setup the parent object (no length checking required)
-    strcpy(nv->token, sr_str);
-    nv->index = nv_get_index((const char_t *)"", sr_str);// set the index - may be needed by calling function
-    nv = nv->nx;                            // no need to check for 0 as list has just been reset
-
-    for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
-        if ((nv->index = sr.status_report_list[i]) == 0) { break;}
-        nv_get_nvObj(nv);
-
-        strcpy(tmp, nv->group);            // flatten out groups - WARNING - you cannot use strncpy here...
-        strcat(tmp, nv->token);
-        strcpy(nv->token, tmp);            //...or here.
-
-        if ((nv = nv->nx) == 0)
-            return cm_hard_alarm(STAT_BUFFER_FULL_FATAL);    // should never be 0 unless SR length exceeds available buffer array
-    }
-    return STAT_OK;
+  const char_t sr_str[] = "sr";
+  char_t tmp[TOKEN_LEN+1];
+  nvObj_t *nv = nv_reset_nv_list();        // sets *nv to the start of the body
+
+  nv->valuetype = TYPE_PARENT;             // setup the parent object (no length checking required)
+  strcpy(nv->token, sr_str);
+  nv->index = nv_get_index((const char_t *)"", sr_str);// set the index - may be needed by calling function
+  nv = nv->nx;                            // no need to check for 0 as list has just been reset
+
+  for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
+    if ((nv->index = sr.status_report_list[i]) == 0) { break;}
+    nv_get_nvObj(nv);
+
+    strcpy(tmp, nv->group);            // flatten out groups - WARNING - you cannot use strncpy here...
+    strcat(tmp, nv->token);
+    strcpy(nv->token, tmp);            //...or here.
+
+    if ((nv = nv->nx) == 0)
+      return cm_hard_alarm(STAT_BUFFER_FULL_FATAL);    // should never be 0 unless SR length exceeds available buffer array
+  }
+  return STAT_OK;
 }
 
 /*
@@ -336,40 +336,40 @@ static stat_t _populate_unfiltered_status_report()
  */
 static uint8_t _populate_filtered_status_report()
 {
-    const char_t sr_str[] = "sr";
-    uint8_t has_data = false;
-    char_t tmp[TOKEN_LEN+1];
-    nvObj_t *nv = nv_reset_nv_list();        // sets nv to the start of the body
-
-    nv->valuetype = TYPE_PARENT;             // setup the parent object (no need to length check the copy)
-    strcpy(nv->token, sr_str);
-//    nv->index = nv_get_index((const char_t *)"", sr_str);// OMITTED - set the index - may be needed by calling function
-    nv = nv->nx;                            // no need to check for 0 as list has just been reset
-
-    for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
-        if ((nv->index = sr.status_report_list[i]) == 0) { break;}
-
-        nv_get_nvObj(nv);
-        // do not report values that have not changed...
-        // ...except for stat=3 (STOP), which is an exception
-        if (fp_EQ(nv->value, sr.status_report_value[i])) {
-//            if (nv->index != sr.stat_index) {
-//                if (fp_EQ(nv->value, COMBINED_PROGRAM_STOP)) {
-                    nv->valuetype = TYPE_EMPTY;
-                    continue;
-//                }
-//            }
-            // report anything that has changed
-        } else {
-            strcpy(tmp, nv->group);        // flatten out groups - WARNING - you cannot use strncpy here...
-            strcat(tmp, nv->token);
-            strcpy(nv->token, tmp);        //...or here.
-            sr.status_report_value[i] = nv->value;
-            if ((nv = nv->nx) == 0) return false; // should never be 0 unless SR length exceeds available buffer array
-            has_data = true;
-        }
+  const char_t sr_str[] = "sr";
+  uint8_t has_data = false;
+  char_t tmp[TOKEN_LEN+1];
+  nvObj_t *nv = nv_reset_nv_list();        // sets nv to the start of the body
+
+  nv->valuetype = TYPE_PARENT;             // setup the parent object (no need to length check the copy)
+  strcpy(nv->token, sr_str);
+  //    nv->index = nv_get_index((const char_t *)"", sr_str);// OMITTED - set the index - may be needed by calling function
+  nv = nv->nx;                            // no need to check for 0 as list has just been reset
+
+  for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
+    if ((nv->index = sr.status_report_list[i]) == 0) { break;}
+
+    nv_get_nvObj(nv);
+    // do not report values that have not changed...
+    // ...except for stat=3 (STOP), which is an exception
+    if (fp_EQ(nv->value, sr.status_report_value[i])) {
+      //            if (nv->index != sr.stat_index) {
+      //                if (fp_EQ(nv->value, COMBINED_PROGRAM_STOP)) {
+      nv->valuetype = TYPE_EMPTY;
+      continue;
+      //                }
+      //            }
+      // report anything that has changed
+    } else {
+      strcpy(tmp, nv->group);        // flatten out groups - WARNING - you cannot use strncpy here...
+      strcat(tmp, nv->token);
+      strcpy(nv->token, tmp);        //...or here.
+      sr.status_report_value[i] = nv->value;
+      if ((nv = nv->nx) == 0) return false; // should never be 0 unless SR length exceeds available buffer array
+      has_data = true;
     }
-    return has_data;
+  }
+  return has_data;
 }
 
 /*
@@ -384,9 +384,9 @@ stat_t sr_set(nvObj_t *nv) { return sr_set_status_report(nv);}
 
 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);
+  if (nv->value < STATUS_REPORT_MIN_MS) { nv->value = STATUS_REPORT_MIN_MS;}
+  sr.status_report_interval = (uint32_t)nv->value;
+  return(STAT_OK);
 }
 
 /*********************
@@ -427,10 +427,10 @@ void sr_print_sv(nvObj_t *nv) { text_print_ui8(nv, fmt_sv);}
  */
 void qr_init_queue_report()
 {
-    qr.queue_report_requested = false;
-    qr.buffers_added = 0;
-    qr.buffers_removed = 0;
-    qr.init_tick = SysTickTimer_getValue();
+  qr.queue_report_requested = false;
+  qr.buffers_added = 0;
+  qr.buffers_removed = 0;
+  qr.init_tick = SysTickTimer_getValue();
 }
 
 /*
@@ -441,28 +441,28 @@ void qr_init_queue_report()
  */
 void qr_request_queue_report(int8_t buffers)
 {
-    // get buffer depth and added/removed count
-    qr.buffers_available = mp_get_planner_buffers_available();
-    if (buffers > 0) {
-        qr.buffers_added += buffers;
-    } else {
-        qr.buffers_removed -= buffers;
-    }
-
-    // time-throttle requests while generating arcs
-    qr.motion_mode = cm_get_motion_mode(ACTIVE_MODEL);
-    if ((qr.motion_mode == MOTION_MODE_CW_ARC) || (qr.motion_mode == MOTION_MODE_CCW_ARC)) {
-        uint32_t tick = SysTickTimer_getValue();
-        if (tick - qr.init_tick < MIN_ARC_QR_INTERVAL) {
-            qr.queue_report_requested = false;
-            return;
-        }
+  // get buffer depth and added/removed count
+  qr.buffers_available = mp_get_planner_buffers_available();
+  if (buffers > 0) {
+    qr.buffers_added += buffers;
+  } else {
+    qr.buffers_removed -= buffers;
+  }
+
+  // time-throttle requests while generating arcs
+  qr.motion_mode = cm_get_motion_mode(ACTIVE_MODEL);
+  if ((qr.motion_mode == MOTION_MODE_CW_ARC) || (qr.motion_mode == MOTION_MODE_CCW_ARC)) {
+    uint32_t tick = SysTickTimer_getValue();
+    if (tick - qr.init_tick < MIN_ARC_QR_INTERVAL) {
+      qr.queue_report_requested = false;
+      return;
     }
+  }
 
-    // either return or request a report
-    if (qr.queue_report_verbosity != QR_OFF) {
-        qr.queue_report_requested = true;
-    }
+  // either return or request a report
+  if (qr.queue_report_verbosity != QR_OFF) {
+    qr.queue_report_requested = true;
+  }
 }
 
 /*
@@ -471,50 +471,50 @@ void qr_request_queue_report(int8_t buffers)
 stat_t qr_queue_report_callback()         // called by controller dispatcher
 {
 #ifdef __SUPPRESS_QUEUE_REPORTS
-    return STAT_NOOP;
+  return STAT_NOOP;
 #endif
 
-    if (qr.queue_report_verbosity == QR_OFF)
-        return STAT_NOOP;
+  if (qr.queue_report_verbosity == QR_OFF)
+    return STAT_NOOP;
 
-    if (qr.queue_report_requested == false)
-        return STAT_NOOP;
+  if (qr.queue_report_requested == false)
+    return STAT_NOOP;
 
-    qr.queue_report_requested = false;
+  qr.queue_report_requested = false;
 
-    if (cfg.comm_mode == TEXT_MODE) {
-        if (qr.queue_report_verbosity == QR_SINGLE) {
-            fprintf(stderr, "qr:%d\n", qr.buffers_available);
-        } else  {
-            fprintf(stderr, "qr:%d, qi:%d, qo:%d\n", qr.buffers_available,qr.buffers_added,qr.buffers_removed);
-        }
+  if (cfg.comm_mode == TEXT_MODE) {
+    if (qr.queue_report_verbosity == QR_SINGLE) {
+      fprintf(stderr, "qr:%d\n", qr.buffers_available);
+    } else  {
+      fprintf(stderr, "qr:%d, qi:%d, qo:%d\n", qr.buffers_available,qr.buffers_added,qr.buffers_removed);
+    }
 
-    } else if (js.json_syntax == JSON_SYNTAX_RELAXED) {
-        if (qr.queue_report_verbosity == QR_SINGLE) {
-            fprintf(stderr, "{qr:%d}\n", qr.buffers_available);
-        } else {
-            fprintf(stderr, "{qr:%d,qi:%d,qo:%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
-        }
+  } else if (js.json_syntax == JSON_SYNTAX_RELAXED) {
+    if (qr.queue_report_verbosity == QR_SINGLE) {
+      fprintf(stderr, "{qr:%d}\n", qr.buffers_available);
+    } else {
+      fprintf(stderr, "{qr:%d,qi:%d,qo:%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
+    }
 
+  } else {
+    if (qr.queue_report_verbosity == QR_SINGLE) {
+      fprintf(stderr, "{\"qr\":%d}\n", qr.buffers_available);
     } else {
-        if (qr.queue_report_verbosity == QR_SINGLE) {
-            fprintf(stderr, "{\"qr\":%d}\n", qr.buffers_available);
-        } else {
-            fprintf(stderr, "{\"qr\":%d,\"qi\":%d,\"qo\":%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
-        }
+      fprintf(stderr, "{\"qr\":%d,\"qi\":%d,\"qo\":%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
     }
-    qr_init_queue_report();
+  }
+  qr_init_queue_report();
 
-    return STAT_OK;
+  return STAT_OK;
 }
 
 
 /*
- * rx_request_rx_report() - request an update on usb serial buffer space available
+ * rx_request_rx_report() - request an update on serial buffer space available
  */
 void rx_request_rx_report() {
-    rx.rx_report_requested = true;
-    rx.space_available = usart_rx_space();
+  rx.rx_report_requested = true;
+  rx.space_available = usart_rx_space();
 }
 
 
@@ -522,13 +522,13 @@ void rx_request_rx_report() {
  * rx_report_callback() - send rx report if one has been requested
  */
 stat_t rx_report_callback() {
-    if (!rx.rx_report_requested)
-        return STAT_NOOP;
+  if (!rx.rx_report_requested)
+    return STAT_NOOP;
 
-    rx.rx_report_requested = false;
+  rx.rx_report_requested = false;
 
-    fprintf(stderr, "{\"rx\":%d}\n", rx.space_available);
-    return STAT_OK;
+  fprintf(stderr, "{\"rx\":%d}\n", rx.space_available);
+  return STAT_OK;
 }
 
 
@@ -540,25 +540,25 @@ stat_t rx_report_callback() {
  * qo_get() - run a queue report - buffers out
  */
 stat_t qr_get(nvObj_t *nv) {
-    nv->value = (float)mp_get_planner_buffers_available(); // ensure that manually requested QR count is always up to date
-    nv->valuetype = TYPE_INTEGER;
-    return STAT_OK;
+  nv->value = (float)mp_get_planner_buffers_available(); // ensure that manually requested QR count is always up to date
+  nv->valuetype = TYPE_INTEGER;
+  return STAT_OK;
 }
 
 
 stat_t qi_get(nvObj_t *nv) {
-    nv->value = (float)qr.buffers_added;
-    nv->valuetype = TYPE_INTEGER;
-    qr.buffers_added = 0;                // reset it
-    return STAT_OK;
+  nv->value = (float)qr.buffers_added;
+  nv->valuetype = TYPE_INTEGER;
+  qr.buffers_added = 0;                // reset it
+  return STAT_OK;
 }
 
 
 stat_t qo_get(nvObj_t *nv) {
-    nv->value = (float)qr.buffers_removed;
-    nv->valuetype = TYPE_INTEGER;
-    qr.buffers_removed = 0;                // reset it
-    return STAT_OK;
+  nv->value = (float)qr.buffers_removed;
+  nv->valuetype = TYPE_INTEGER;
+  qr.buffers_removed = 0;                // reset it
+  return STAT_OK;
 }
 
 
@@ -573,61 +573,61 @@ stat_t qo_get(nvObj_t *nv) {
  *    job_print_job()
  */
 stat_t job_populate_job_report() {
-    const char_t job_str[] = "job";
-    char_t tmp[TOKEN_LEN+1];
-    nvObj_t *nv = nv_reset_nv_list();        // sets *nv to the start of the body
+  const char_t job_str[] = "job";
+  char_t tmp[TOKEN_LEN+1];
+  nvObj_t *nv = nv_reset_nv_list();        // sets *nv to the start of the body
 
-    nv->valuetype = TYPE_PARENT;             // setup the parent object
-    strcpy(nv->token, job_str);
+  nv->valuetype = TYPE_PARENT;             // setup the parent object
+  strcpy(nv->token, job_str);
 
-    //nv->index = nv_get_index((const char_t *)"", job_str);// set the index - may be needed by calling function
-    nv = nv->nx;                            // no need to check for 0 as list has just been reset
+  //nv->index = nv_get_index((const char_t *)"", job_str);// set the index - may be needed by calling function
+  nv = nv->nx;                            // no need to check for 0 as list has just been reset
 
-    index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1");// set first job persistence index
-    for (uint8_t i=0; i<4; i++) {
+  index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1");// set first job persistence index
+  for (uint8_t i=0; i<4; i++) {
 
-        nv->index = job_start + i;
-        nv_get_nvObj(nv);
+    nv->index = job_start + i;
+    nv_get_nvObj(nv);
 
-        strcpy(tmp, nv->group);                // concatenate groups and tokens - do NOT use strncpy()
-        strcat(tmp, nv->token);
-        strcpy(nv->token, tmp);
+    strcpy(tmp, nv->group);                // concatenate groups and tokens - do NOT use strncpy()
+    strcat(tmp, nv->token);
+    strcpy(nv->token, tmp);
 
-        if ((nv = nv->nx) == 0)
-            return STAT_OK;               // should never be 0 unless SR length exceeds available buffer array
-    }
-    return STAT_OK;
+    if ((nv = nv->nx) == 0)
+      return STAT_OK;               // should never be 0 unless SR length exceeds available buffer array
+  }
+  return STAT_OK;
 }
 
 stat_t job_set_job_report(nvObj_t *nv)
 {
-    index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1");// set first job persistence index
-
-    for (uint8_t i=0; i<4; i++) {
-        if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) { break;}
-        if (nv->valuetype == TYPE_INTEGER) {
-            cs.job_id[i] = nv->value;
-            nv->index = job_start + i;        // index of the SR persistence location
-            nv_persist(nv);
-        } else {
-            return STAT_UNSUPPORTED_TYPE;
-        }
+  index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1");// set first job persistence index
+
+  for (uint8_t i=0; i<4; i++) {
+    if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) { break;}
+    if (nv->valuetype == TYPE_INTEGER) {
+      cs.job_id[i] = nv->value;
+      nv->index = job_start + i;        // index of the SR persistence location
+      nv_persist(nv);
+    } else {
+      return STAT_UNSUPPORTED_TYPE;
     }
-    job_populate_job_report();                // return current values
-    return STAT_OK;
+  }
+  job_populate_job_report();                // return current values
+  return STAT_OK;
 }
 
 uint8_t job_report_callback()
 {
-    if (cfg.comm_mode == TEXT_MODE) {
-        // no-op, job_ids are client app state
-    } else if (js.json_syntax == JSON_SYNTAX_RELAXED) {
-        fprintf(stderr, "{job:[%lu,%lu,%lu,%lu]}\n", cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3] );
-    } else {
-        fprintf(stderr, "{\"job\":[%lu,%lu,%lu,%lu]}\n", cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3] );
-        //job_clear_report();
-    }
-    return STAT_OK;
+  if (cfg.comm_mode == TEXT_MODE) {
+    // no-op, job_ids are client app state
+  } else if (js.json_syntax == JSON_SYNTAX_RELAXED) {
+    fprintf(stderr, "{job:[%lu,%lu,%lu,%lu]}\n", cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3] );
+  } else {
+    fprintf(stderr, "{\"job\":[%lu,%lu,%lu,%lu]}\n", cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3] );
+    //job_clear_report();
+  }
+  return STAT_OK;
 }
 
 stat_t job_get(nvObj_t *nv) { return job_populate_job_report();}
index 595717c8d2c26194924dc60be13e9a61dae8084f..da41d0d445a42f8377cfa44df44c303d4331c551 100644 (file)
 #define MIN_ARC_QR_INTERVAL 200                    // minimum interval between QRs during arc generation (in system ticks)
 
 enum srVerbosity {                                // status report enable and verbosity
-    SR_OFF = 0,                                    // no reports
-    SR_FILTERED,                                // reports only values that have changed from the last report
-    SR_VERBOSE                                    // reports all values specified
+  SR_OFF = 0,                                    // no reports
+  SR_FILTERED,                                // reports only values that have changed from the last report
+  SR_VERBOSE                                    // reports all values specified
 };
 
 enum cmStatusReportRequest {
-    SR_TIMED_REQUEST = 0,                        // request a status report at next timer interval
-    SR_IMMEDIATE_REQUEST                        // request a status report ASAP
+  SR_TIMED_REQUEST = 0,                        // request a status report at next timer interval
+  SR_IMMEDIATE_REQUEST                        // request a status report ASAP
 };
 
 enum qrVerbosity {                                // planner queue enable and verbosity
-    QR_OFF = 0,                                    // no response is provided
-    QR_SINGLE,                                    // queue depth reported
-    QR_TRIPLE                                    // queue depth reported for buffers, buffers added, buffered removed
+  QR_OFF = 0,                                    // no response is provided
+  QR_SINGLE,                                    // queue depth reported
+  QR_TRIPLE                                    // queue depth reported for buffers, buffers added, buffered removed
 };
 
 typedef struct srSingleton {
 
-    /*** config values (PUBLIC) ***/
-    uint8_t status_report_verbosity;
-    uint32_t status_report_interval;                    // in milliseconds
+  /*** config values (PUBLIC) ***/
+  uint8_t status_report_verbosity;
+  uint32_t status_report_interval;                    // in milliseconds
 
-    /*** runtime values (PRIVATE) ***/
-    uint8_t status_report_requested;                    // flag that SR has been requested
-    uint32_t status_report_systick;                        // SysTick value for next status report
-    index_t stat_index;                                    // table index value for stat - determined during initialization
-    index_t status_report_list[NV_STATUS_REPORT_LEN];    // status report elements to report
-    float status_report_value[NV_STATUS_REPORT_LEN];    // previous values for filtered reporting
+  /*** runtime values (PRIVATE) ***/
+  uint8_t status_report_requested;                    // flag that SR has been requested
+  uint32_t status_report_systick;                        // SysTick value for next status report
+  index_t stat_index;                                    // table index value for stat - determined during initialization
+  index_t status_report_list[NV_STATUS_REPORT_LEN];    // status report elements to report
+  float status_report_value[NV_STATUS_REPORT_LEN];    // previous values for filtered reporting
 
 } srSingleton_t;
 
 typedef struct qrSingleton {        // data for queue reports
 
-    /*** config values (PUBLIC) ***/
-    uint8_t queue_report_verbosity;    // queue reports enabled and verbosity level
+  /*** config values (PUBLIC) ***/
+  uint8_t queue_report_verbosity;    // queue reports enabled and verbosity level
 
-    /*** runtime values (PRIVATE) ***/
-    uint8_t queue_report_requested;    // set to true to request a report
-    uint8_t buffers_available;        // stored buffer depth passed to by callback
-    uint8_t prev_available;            // buffers available at last count
-    uint16_t buffers_added;            // buffers added since last count
-    uint16_t buffers_removed;        // buffers removed since last report
-    uint8_t motion_mode;            // used to detect arc movement
-    uint32_t init_tick;                // time when values were last initialized or cleared
+  /*** runtime values (PRIVATE) ***/
+  uint8_t queue_report_requested;    // set to true to request a report
+  uint8_t buffers_available;        // stored buffer depth passed to by callback
+  uint8_t prev_available;            // buffers available at last count
+  uint16_t buffers_added;            // buffers added since last count
+  uint16_t buffers_removed;        // buffers removed since last report
+  uint8_t motion_mode;            // used to detect arc movement
+  uint32_t init_tick;                // time when values were last initialized or cleared
 
 } qrSingleton_t;
 
 typedef struct rxSingleton {
-    uint8_t rx_report_requested;
-    uint16_t space_available;       // space available in usb rx buffer at time of request
+  uint8_t rx_report_requested;
+  uint16_t space_available;       // space available in rx buffer at time of request
 } rxSingleton_t;
 
 /**** Externs - See report.c for allocation ****/
@@ -128,23 +128,23 @@ stat_t qo_get(nvObj_t *nv);
 
 #ifdef __TEXT_MODE
 
-    void sr_print_sr(nvObj_t *nv);
-    void sr_print_si(nvObj_t *nv);
-    void sr_print_sv(nvObj_t *nv);
-    void qr_print_qv(nvObj_t *nv);
-    void qr_print_qr(nvObj_t *nv);
-    void qr_print_qi(nvObj_t *nv);
-    void qr_print_qo(nvObj_t *nv);
+void sr_print_sr(nvObj_t *nv);
+void sr_print_si(nvObj_t *nv);
+void sr_print_sv(nvObj_t *nv);
+void qr_print_qv(nvObj_t *nv);
+void qr_print_qr(nvObj_t *nv);
+void qr_print_qi(nvObj_t *nv);
+void qr_print_qo(nvObj_t *nv);
 
 #else
 
-    #define sr_print_sr tx_print_stub
-    #define sr_print_si tx_print_stub
-    #define sr_print_sv tx_print_stub
-    #define qr_print_qv tx_print_stub
-    #define qr_print_qr tx_print_stub
-    #define qr_print_qi tx_print_stub
-    #define qr_print_qo tx_print_stub
+#define sr_print_sr tx_print_stub
+#define sr_print_si tx_print_stub
+#define sr_print_sv tx_print_stub
+#define qr_print_qv tx_print_stub
+#define qr_print_qr tx_print_stub
+#define qr_print_qi tx_print_stub
+#define qr_print_qo tx_print_stub
 
 #endif // __TEXT_MODE
 
index 93018548ab941256c4a20a5f7e8440c5a5fed33d..47b81231d81b98a32363865ffe04360c25ff5a0e 100644 (file)
@@ -25,8 +25,9 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
-/*     This module provides the low-level stepper drivers and some related functions.
- *    See stepper.h for a detailed explanation of this module.
+
+/* This module provides the low-level stepper drivers and some related functions.
+ * See stepper.h for a detailed explanation of this module.
  */
 
 #include "tinyg.h"
@@ -62,6 +63,7 @@ static void _request_load_move();
  *      - motor polarity is setup during config_init()
  *      - high level interrupts must be enabled in main() once all inits are complete
  */
+
 /*    NOTE: This is the bare code that the Motate timer calls replace.
  *    NB: requires: #include <component_tc.h>
  *
@@ -814,7 +816,6 @@ static int8_t _get_motor(const nvObj_t *nv)
 static void _set_motor_steps_per_unit(nvObj_t *nv)
 {
     uint8_t m = _get_motor(nv);
-//    st_cfg.mot[m].units_per_step = (st_cfg.mot[m].travel_rev * st_cfg.mot[m].step_angle) / (360 * st_cfg.mot[m].microsteps); // unused
     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();
 }
diff --git a/src/tmc2660.c b/src/tmc2660.c
new file mode 100644 (file)
index 0000000..c6a8164
--- /dev/null
@@ -0,0 +1,237 @@
+/******************************************************************************\
+
+                   This file is part of the TinyG firmware.
+
+                     Copyright (c) 2016, Buildbotics LLC
+                             All rights reserved.
+
+        The C! library is free software: you can redistribute it and/or
+        modify it under the terms of the GNU Lesser General Public License
+        as published by the Free Software Foundation, either version 2.1 of
+        the License, or (at your option) any later version.
+
+        The C! library is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        Lesser General Public License for more details.
+
+        You should have received a copy of the GNU Lesser General Public
+        License along with the C! library.  If not, see
+        <http://www.gnu.org/licenses/>.
+
+        In addition, BSD licensing may be granted on a case by case basis
+        by written permission from at least one of the copyright holders.
+        You may request written permission by emailing the authors.
+
+                For information regarding this software email:
+                               Joseph Coffland
+                            joseph@buildbotics.com
+
+\******************************************************************************/
+
+#include "tmc2660.h"
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <string.h>
+
+
+typedef enum {
+  TMC2660_STATE_CONFIG,
+  TMC2660_STATE_MONITOR,
+  TMC2660_STATE_RESET,
+} tmc2660_state_t;
+
+typedef enum {
+  SPI_STATE_SELECT,
+  SPI_STATE_WRITE,
+  SPI_STATE_READ,
+} spi_state_t;
+
+typedef struct {
+  uint16_t mstep;
+  uint8_t status;
+  uint32_t regs[5];
+} tmc2660_driver_t;
+
+
+static const uint32_t reg_addrs[] = {
+  TMC2660_DRVCTRL_ADDR,
+  TMC2660_CHOPCONF_ADDR,
+  TMC2660_SMARTEN_ADDR,
+  TMC2660_SGCSCONF_ADDR,
+  TMC2660_DRVCONF_ADDR
+};
+
+
+static volatile tmc2660_state_t state;
+static volatile uint8_t driver;
+static volatile uint8_t reg;
+static tmc2660_driver_t drivers[TMC2660_NUM_DRIVERS];
+
+static volatile spi_state_t spi_state;
+static volatile uint8_t spi_byte;
+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 spi_send() {
+  // Flush any status errors
+  // TODO check errors
+  uint8_t x = SPIC.STATUS;
+  x = x;
+
+  // Read
+  if (!spi_byte) spi_in = 0;
+  else spi_in = spi_in << 8 | SPIC.DATA;
+
+  // Write
+  if (spi_byte < 3)
+    SPIC.DATA = 0xff & (spi_out >> ((2 - spi_byte++) * 8));
+  else spi_byte = 0;
+}
+
+
+void spi_next() {
+  switch (spi_state) {
+  case SPI_STATE_SELECT:
+    // Select driver
+    spi_cs(driver, 1);
+
+    // Next state
+    TMC2660_TIMER.PER = 4;
+    spi_state = SPI_STATE_WRITE;
+    break;
+
+  case SPI_STATE_WRITE:
+    spi_out = reg_addrs[reg] | drivers[driver].regs[reg];
+    spi_send();
+
+    // Next state
+    TMC2660_TIMER.PER = 16;
+    spi_state = SPI_STATE_READ;
+    break;
+
+  case SPI_STATE_READ:
+    // Deselect driver
+    spi_cs(driver, 0);
+
+    // Read response
+    drivers[driver].mstep = (spi_in >> 14) & 0x3ff;
+    drivers[driver].status = spi_in >> 4;
+
+    // Next state
+    spi_state = SPI_STATE_SELECT;
+
+    if (++reg == 5) {
+      reg = 0;
+      if (++driver == TMC2660_NUM_DRIVERS) driver = 0;
+
+      TMC2660_TIMER.PER = 10;
+
+    } else TMC2660_TIMER.PER = 2;
+    break;
+  }
+}
+
+
+ISR(SPIC_INT_vect) {
+  spi_send();
+}
+
+
+ISR(TCC1_OVF_vect) {
+  spi_next();
+}
+
+
+void tmc2660_init() {
+  // Reset state
+  state = TMC2660_STATE_CONFIG;
+  spi_state = SPI_STATE_SELECT;
+  driver = reg = spi_byte = 0;
+  memset(drivers, 0, sizeof(drivers));
+
+  // Configure motors
+  for (int i = 0; i < TMC2660_NUM_DRIVERS; i++) {
+    drivers[i].regs[TMC2660_DRVCTRL] = 0;
+    drivers[i].regs[TMC2660_CHOPCONF] = 0x14557;
+    drivers[i].regs[TMC2660_SMARTEN] = 0x8202;
+    drivers[i].regs[TMC2660_SGCSCONF] = 0x1001f;
+    drivers[i].regs[TMC2660_DRVCONF] = 0x10;
+  }
+
+  // Setup pins
+  TMC2660_SPI_PORT.OUTSET = 1 << 4;  // High
+  TMC2660_SPI_PORT.DIRSET = 1 << 4;  // Output
+  TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_SCK_PIN;  // High
+  TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_SCK_PIN;  // Output
+  TMC2660_SPI_PORT.DIRCLR = 1 << TMC2660_SPI_MISO_PIN; // Input
+  TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_MOSI_PIN; // High
+  TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_MOSI_PIN; // Output
+
+#if TMC2660_NUM_DRIVERS > 0
+  TMC2660_SPI_SSX_PORT.OUTSET = 1 << TMC2660_SPI_SSX_PIN; // High
+  TMC2660_SPI_SSX_PORT.DIRSET = 1 << TMC2660_SPI_SSX_PIN; // Output
+#endif
+#if TMC2660_NUM_DRIVERS > 1
+  TMC2660_SPI_SSY_PORT.OUTSET = 1 << TMC2660_SPI_SSY_PIN; // High
+  TMC2660_SPI_SSY_PORT.DIRSET = 1 << TMC2660_SPI_SSY_PIN; // Output
+#endif
+#if TMC2660_NUM_DRIVERS > 2
+  TMC2660_SPI_SSZ_PORT.OUTSET = 1 << TMC2660_SPI_SSZ_PIN; // High
+  TMC2660_SPI_SSZ_PORT.DIRSET = 1 << TMC2660_SPI_SSZ_PIN; // Output
+#endif
+#if TMC2660_NUM_DRIVERS > 3
+  TMC2660_SPI_SSA_PORT.OUTSET = 1 << TMC2660_SPI_SSA_PIN; // High
+  TMC2660_SPI_SSA_PORT.DIRSET = 1 << TMC2660_SPI_SSA_PIN; // Output
+#endif
+#if TMC2660_NUM_DRIVERS > 4
+  TMC2660_SPI_SSB_PORT.OUTSET = 1 << TMC2660_SPI_SSB_PIN; // High
+  TMC2660_SPI_SSB_PORT.DIRSET = 1 << TMC2660_SPI_SSB_PIN; // Output
+#endif
+
+  // Configure SPI
+  PR.PRPC &= ~PR_SPI_bm; // Disable power reduction
+  SPIC.CTRL = SPI_ENABLE_bm | SPI_DORD_bm | SPI_MASTER_bm | SPI_MODE_3_gc |
+    SPI_PRESCALER_DIV128_gc; // enable, big endian, master, mode 3, clock/128
+  PORTC.REMAP = PORT_SPI_bm; // Swap SCK and MOSI
+  SPIC.INTCTRL = SPI_INTLVL_MED_gc; // interupt level
+
+  // Configure timer
+  PR.PRPC &= ~PR_TC1_bm; // Disable power reduction
+  TMC2660_TIMER.PER = F_CPU / 1024 / 10; // Set timer period
+  TMC2660_TIMER.INTCTRLA = TC_OVFINTLVL_LO_gc; // Low priority overflow int
+  TMC2660_TIMER.CTRLA = TC_CLKSEL_DIV1024_gc; // enable, clock/1024
+}
+
+
+uint8_t tmc2660_status(int driver) {
+  return drivers[driver].status;
+}
+
+
+uint16_t tmc2660_step(int driver) {
+  return drivers[driver].mstep;
+}
diff --git a/src/tmc2660.h b/src/tmc2660.h
new file mode 100644 (file)
index 0000000..8a0ff88
--- /dev/null
@@ -0,0 +1,151 @@
+/******************************************************************************\
+
+                   This file is part of the TinyG firmware.
+
+                     Copyright (c) 2016, Buildbotics LLC
+                             All rights reserved.
+
+        The C! library is free software: you can redistribute it and/or
+        modify it under the terms of the GNU Lesser General Public License
+        as published by the Free Software Foundation, either version 2.1 of
+        the License, or (at your option) any later version.
+
+        The C! library is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        Lesser General Public License for more details.
+
+        You should have received a copy of the GNU Lesser General Public
+        License along with the C! library.  If not, see
+        <http://www.gnu.org/licenses/>.
+
+        In addition, BSD licensing may be granted on a case by case basis
+        by written permission from at least one of the copyright holders.
+        You may request written permission by emailing the authors.
+
+                For information regarding this software email:
+                               Joseph Coffland
+                            joseph@buildbotics.com
+
+\******************************************************************************/
+
+#ifndef TMC2660_H
+#define TMC2660_H
+
+#include <stdint.h>
+
+#define TMC2660_SPI_PORT PORTC
+#define TMC2660_SPI_SCK_PIN 5
+#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 4
+
+#define TMC2660_TIMER TCC1
+
+void tmc2660_init();
+uint8_t tmc2660_status(int driver);
+uint16_t tmc2660_step(int driver);
+
+#define TMC2660_DRVCTRL             0
+#define TMC2660_DRVCTRL_ADDR        (0UL << 18)
+#define TMC2660_DRVCTRL_PHA         (1UL << 17)
+#define TMC2660_DRVCTRL_CA(x)       (((int32_t)x & 0xff) << 9)
+#define TMC2660_DRVCTRL_PHB         (1UL << 8)
+#define TMC2660_DRVCTRL_CB(x)       (((int32_t)x & 0xff) << 0)
+#define TMC2660_DRVCTRL_INTPOL      (1UL << 9)
+#define TMC2660_DRVCTRL_DEDGE       (1UL << 8)
+#define TMC2660_DRVCTRL_MRES_256    (0UL << 0)
+#define TMC2660_DRVCTRL_MRES_128    (1UL << 0)
+#define TMC2660_DRVCTRL_MRES_64     (2UL << 0)
+#define TMC2660_DRVCTRL_MRES_32     (3UL << 0)
+#define TMC2660_DRVCTRL_MRES_16     (4UL << 0)
+#define TMC2660_DRVCTRL_MRES_8      (5UL << 0)
+#define TMC2660_DRVCTRL_MRES_4      (6UL << 0)
+#define TMC2660_DRVCTRL_MRES_2      (7UL << 0)
+#define TMC2660_DRVCTRL_MRES_1      (8UL << 0)
+
+#define TMC2660_CHOPCONF            1
+#define TMC2660_CHOPCONF_ADDR       (4UL << 17)
+#define TMC2660_CHOPCONF_TBL_16     (0UL << 15)
+#define TMC2660_CHOPCONF_TBL_24     (1UL << 15)
+#define TMC2660_CHOPCONF_TBL_36     (2UL << 15)
+#define TMC2660_CHOPCONF_TBL_54     (3UL << 15)
+#define TMC2660_CHOPCONF_CHM        (1UL << 14)
+#define TMC2660_CHOPCONF_RNDTF      (1UL << 13)
+#define TMC2660_CHOPCONF_FDM_COMP   (0UL << 12)
+#define TMC2660_CHOPCONF_FDM_TIMER  (1UL << 12)
+#define TMC2660_CHOPCONF_HDEC_16    (0UL << 11)
+#define TMC2660_CHOPCONF_HDEC_32    (1UL << 11)
+#define TMC2660_CHOPCONF_HDEC_48    (2UL << 11)
+#define TMC2660_CHOPCONF_HDEC_64    (3UL << 11)
+#define TMC2660_CHOPCONF_HEND(x)    ((((int32_t)x + 3) & 0xf) << 7)
+#define TMC2660_CHOPCONF_SWO(x)     ((((int32_t)x + 3) & 0xf) << 7)
+#define TMC2660_CHOPCONF_HSTART(x)  ((((int32_t)x - 1) & 7) << 4)
+#define TMC2660_CHOPCONF_FASTD(x)   ((((int32_t)x & 8) << 11) | (x & 7) << 4))
+#define TMC2660_CHOPCONF_TOFF_TBL   (1 << 0)
+#define TMC2660_CHOPCONF_TOFF(x)    (((int32_t)x & 0xf) << 0)
+
+#define TMC2660_SMARTEN             2
+#define TMC2660_SMARTEN_ADDR        (5UL << 17)
+#define TMC2660_SMARTEN_SEIMIN      (1UL << 15)
+#define TMC2660_SMARTEN_SEDN_32     (0UL << 13)
+#define TMC2660_SMARTEN_SEDN_8      (1UL << 13)
+#define TMC2660_SMARTEN_SEDN_2      (2UL << 13)
+#define TMC2660_SMARTEN_SEDN_1      (3UL << 13)
+#define TMC2660_SMARTEN_MAX(x)      ((x & 0xf) << 8)
+#define TMC2660_SMARTEN_SEUP_1      (0UL << 5)
+#define TMC2660_SMARTEN_SEUP_2      (1UL << 5)
+#define TMC2660_SMARTEN_SEUP_4      (2UL << 5)
+#define TMC2660_SMARTEN_SEUP_8      (3UL << 5)
+#define TMC2660_SMARTEN_MIN(x)      (((int32_t)x & 0xf) << 0)
+
+#define TMC2660_SGCSCONF            3
+#define TMC2660_SGCSCONF_ADDR       (6UL << 17)
+#define TMC2660_SGCSCONF_SFILT      (1UL << 17)
+#define TMC2660_SGCSCONF_THRESH(x)  (((int32_t)x & 0x7f) << 8)
+#define TMC2660_SGCSCONF_CS(x)      (((int32_t)x & 0x1f) << 0)
+#define TMC2660_SGCSCONF_CS_NONE    (31UL << 0)
+
+#define TMC2660_DRVCONF             4
+#define TMC2660_DRVCONF_ADDR        (7UL << 17)
+#define TMC2660_DRVCONF_TST         (1UL << 16)
+#define TMC2660_DRVCONF_SLPH_MIN    (0UL << 14)
+#define TMC2660_DRVCONF_SLPH_MIN_TC (1UL << 14)
+#define TMC2660_DRVCONF_SLPH_MED_TC (2UL << 14)
+#define TMC2660_DRVCONF_SLPH_MAX    (3UL << 14)
+#define TMC2660_DRVCONF_SLPL_MIN    (0UL << 12)
+#define TMC2660_DRVCONF_SLPL_MED    (2UL << 12)
+#define TMC2660_DRVCONF_SLPL_MAX    (3UL << 12)
+#define TMC2660_DRVCONF_DISS2G      (1UL << 10)
+#define TMC2660_DRVCONF_TS2G_3_2    (0UL << 8)
+#define TMC2660_DRVCONF_TS2G_1_6    (1UL << 8)
+#define TMC2660_DRVCONF_TS2G_1_2    (2UL << 8)
+#define TMC2660_DRVCONF_TS2G_0_8    (3UL << 8)
+#define TMC2660_DRVCONF_SDOFF       (1UL << 7)
+#define TMC2660_DRVCONF_VSENSE      (1UL << 6)
+#define TMC2660_DRVCONF_RDSEL_MSTEP (0UL << 4)
+#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)
+
+#endif // TMC2660_H
index cbb6024036d7ad76b4946e62eb37a82204977f56..502db7b169ed209ad9b70a1148a6e0d9e1d05784 100644 (file)
@@ -2,7 +2,7 @@
 
                    This file is part of the TinyG firmware.
 
-                     Copyright (c) 2015, Buildbotics LLC
+                   Copyright (c) 2015-2016, Buildbotics LLC
                              All rights reserved.
 
         The C! library is free software: you can redistribute it and/or
@@ -118,7 +118,7 @@ void usart_init(void) {
   USARTC0.CTRLA = USART_RXCINTLVL_HI_gc;
   USARTC0.CTRLB = USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm;
 
-  PMIC.CTRL |= PMIC_HILVLEN_bm; // Lowlevel interrupt on
+  PMIC.CTRL |= PMIC_HILVLEN_bm; // Interrupt level on
 
   // Connect IO
   stdout = &_stdout;
index f4d2b1f56d66d5bcf0b85eeaf771d871a6ea2cf6..c6b8e6e394e3d17f38b6df39a900e40a0850d582 100644 (file)
@@ -2,7 +2,7 @@
 
                    This file is part of the TinyG firmware.
 
-                     Copyright (c) 2015, Buildbotics LLC
+                   Copyright (c) 2015-2016, Buildbotics LLC
                              All rights reserved.
 
         The C! library is free software: you can redistribute it and/or