// © RiceMotion ( Robert Carl Rice ) 2012-2016 - All rights reserved


// This software makes use of tools and libraries obtained from open source projects or released for

// use by relevant hardware manufactures. However, this software is NOT a part of any open source project.

// It is released only on a "need to know" basis for beta testers of the "RiceCNC Interpolation Engine".

// Recipents of this source code must respect the confidential nature of this software and prevent any

// distribution that could result in counterfeit copies of the "RiceCNC Interpolation Engine".


// © RiceMotion ( Robert Carl Rice ) 2012-2016 - All rights reserved

#ifndef dSpinDefines_h

#define dSpinDefines_h



// If we have an error, return the status code from the stepper controller.  Return 0 on no error

// getStatus() return may be non-zero even if there are no errors


/*****************************************************************

Example code for the STMicro L6470 dSPIN stepper motor driver.

This code is public domain beerware/Sunny-D-ware. If you find it useful and

run into me someday, I'd appreciate a cold one.


12/12/2011- Mike Hord, SparkFun Electronics


The breakout board for the dSPIN chip has 7 data lines:

BSYN     - this line is LOW when the chip is busy; busy generally means things

   like executing a move command.

STBY     - drag low to reset the device to default conditions. Also should be

   performed after power up to ensure a known-good initial state.

FLGN     - when the dSPIN raises a flag it usually means an error has occurred

STCK     - used as a step clock input; the direction (and activation of this input

   is done by setting registers on the chip.

SDI          - SPI data FROM the µC TO the dSPIN

SDO          - SPI data TO the µC FROM the dSPIN

CSN          - active-low slave select for the SPI bus

CK          - data clock for the SPI bus



ERRATA: IMPORTANT!!! READ THIS!!!

There are several errors in the datasheet for the L6470:

- the internal oscillator is specified as 16MHz +/- 3%. Experimentally, it

   seems to be more like a 6% tolerance.


- when transitioning from one movement command to another, it may be necessary

   to include a dSPIN_softStop() between the two to ensure proper operation. For

   example, if dSPIN_Move(FWD, 800) is used to move 800 steps FWD, and

   immediately after that, with no soft stop between them, a dSPIN_Run(FWD, 200)

   command is issued, the 'run' command will execute with a speed based on the

   value in the 'MAX_SPEED' register, the way the 'move' command did, and NOT

   with the speed passed to it by the function call.


2)  ABS_POS should be expanded to byte boundary, i.e., 24 bits

3)  Reading SPEED is "glichy" - values do not continuously ascend or decend while accelerating or decelerating

4)  dir bit in status does not change to relect the current motor direction

5)  FS_SPD reads as zero - cannot verify set value

6)  KVAL_RUN reads as 7 bits, i.e., mask 0x7F - cannot verify set value

7)  KVAL_ACC reads as 7 bits, i.e., mask 0x7F - cannot verify set value

8)  KVAL_DEC reads as 7 bits, i.e., mask 0x7F - cannot verify set value

9)  KVAL_HOLD reads as zero - cannot verify set value

10) STALL_TH reads back as 4 bits, i.e., mask 0x0F - cannot verify set value

11) CONFIG set 129 returns 1 - POW_SR not confirmed

12) EL_POS data appears to be non-sequential - need further documentation

13) EL_POS shold be expanded to byte boundary, i.e., 16 bits


Initial release.

*****************************************************************/


// constant definitions for overcurrent thresholds. Write these values to

//  register dSPIN_OCD_TH to set the level at which an overcurrent even occurs.

enum dSPIN_OCD_TH_VALUES {

  dSPIN_OCD_TH_375mA,

  dSPIN_OCD_TH_750mA,

  dSPIN_OCD_TH_1125mA,

  dSPIN_OCD_TH_1500mA,

  dSPIN_OCD_TH_1875mA,

  dSPIN_OCD_TH_2250mA,

  dSPIN_OCD_TH_2625mA,

  dSPIN_OCD_TH_3000mA,

  dSPIN_OCD_TH_3375mA,

  dSPIN_OCD_TH_3750mA,

  dSPIN_OCD_TH_4125mA,

  dSPIN_OCD_TH_4500mA,

  dSPIN_OCD_TH_4875mA,

  dSPIN_OCD_TH_5250mA,

  dSPIN_OCD_TH_5625mA,

  dSPIN_OCD_TH_6000mA };

  

// STEP_MODE option values.

// First comes the "microsteps per step" options...

#define dSPIN_STEP_MODE_STEP_SEL        0x07  // Mask for these bits only.


enum dSPIN_STEP_SEL {

  dSPIN_STEP_SEL_1,

  dSPIN_STEP_SEL_1_2,

  dSPIN_STEP_SEL_1_4,

  dSPIN_STEP_SEL_1_8,

  dSPIN_STEP_SEL_1_16,

  dSPIN_STEP_SEL_1_32,

  dSPIN_STEP_SEL_1_64,

  dSPIN_STEP_SEL_1_128 };


// ...next, define the SYNC_EN bit. When set, the BUSYN pin will instead

//  output a clock related to the full-step frequency as defined by the

//  SYNC_SEL bits below.

#define dSPIN_STEP_MODE_SYNC_EN          0x80  // Mask for this bit

#define dSPIN_SYNC_EN                    0x80


// ...last, define the SYNC_SEL modes. The clock output is defined by

//  the full-step frequency and the value in these bits- see the datasheet

//  for a matrix describing that relationship (page 46).

#define dSPIN_STEP_MODE_SYNC_SEL     0x70

#define dSPIN_SYNC_SEL_1_2               0x00

#define dSPIN_SYNC_SEL_1               0x10

#define dSPIN_SYNC_SEL_2               0x20

#define dSPIN_SYNC_SEL_4               0x30

#define dSPIN_SYNC_SEL_8               0x40

#define dSPIN_SYNC_SEL_16               0x50

#define dSPIN_SYNC_SEL_32               0x60

#define dSPIN_SYNC_SEL_64               0x70


// Bit names for the ALARM_EN register.

//  Each of these bits defines one potential alarm condition.

//  When one of these conditions occurs and the respective bit in ALARM_EN is set,

//  the FLAG pin will go low. The register must be queried to determine which event

//  caused the alarm.

#define dSPIN_ALARM_EN_OVERCURRENT       0x01

#define dSPIN_ALARM_EN_THERMAL_SHUTDOWN      0x02

#define dSPIN_ALARM_EN_THERMAL_WARNING   0x04

#define dSPIN_ALARM_EN_UNDER_VOLTAGE     0x08

#define dSPIN_ALARM_EN_STALL_DET_A       0x10

#define dSPIN_ALARM_EN_STALL_DET_B       0x20

#define dSPIN_ALARM_EN_SW_TURN_ON        0x40

#define dSPIN_ALARM_EN_WRONG_NPERF_CMD   0x80


// CONFIG register renames.


// Oscillator options.

// The dSPIN needs to know what the clock frequency is because it uses that for some

//  calculations during operation.

#define dSPIN_CONFIG_OSC_SEL                 0x000F // Mask for this bit field.

#define dSPIN_CONFIG_INT_16MHZ               0x00     // Internal 16MHz, no output

#define dSPIN_CONFIG_INT_16MHZ_OSCOUT_2MHZ   0x08     // Default; internal 16MHz, 2MHz output

#define dSPIN_CONFIG_INT_16MHZ_OSCOUT_4MHZ   0x09     // Internal 16MHz, 4MHz output

#define dSPIN_CONFIG_INT_16MHZ_OSCOUT_8MHZ   0x0A     // Internal 16MHz, 8MHz output

#define dSPIN_CONFIG_INT_16MHZ_OSCOUT_16MHZ  0x0B     // Internal 16MHz, 16MHz output

#define dSPIN_CONFIG_EXT_8MHZ_XTAL_DRIVE     0x04     // External 8MHz crystal

#define dSPIN_CONFIG_EXT_16MHZ_XTAL_DRIVE    0x05     // External 16MHz crystal

#define dSPIN_CONFIG_EXT_24MHZ_XTAL_DRIVE    0x06     // External 24MHz crystal

#define dSPIN_CONFIG_EXT_32MHZ_XTAL_DRIVE    0x07     // External 32MHz crystal

#define dSPIN_CONFIG_EXT_8MHZ_OSCOUT_INVERT  0x0C     // External 8MHz crystal, output inverted

#define dSPIN_CONFIG_EXT_16MHZ_OSCOUT_INVERT 0x0D     // External 16MHz crystal, output inverted

#define dSPIN_CONFIG_EXT_24MHZ_OSCOUT_INVERT 0x0E     // External 24MHz crystal, output inverted

#define dSPIN_CONFIG_EXT_32MHZ_OSCOUT_INVERT 0x0F     // External 32MHz crystal, output inverted


// Configure the functionality of the external switch input

#define dSPIN_CONFIG_SW_MODE                 0x0010 // Mask for this bit.

#define dSPIN_CONFIG_SW_HARD_STOP            0x00     // Default; hard stop motor on switch.

#define dSPIN_CONFIG_SW_USER                 0x10     // Tie to the GoUntil and ReleaseSW

                                                    //  commands to provide jog function.

                                                    //  See page 25 of datasheet


// Configure the motor voltage compensation mode (see page 34 of datasheet)

#define dSPIN_CONFIG_EN_VSCOMP               0x0020 // Mask for this bit.

#define dSPIN_CONFIG_VS_COMP_DISABLE         0x00     // Disable motor voltage compensation.

#define dSPIN_CONFIG_VS_COMP_ENABLE          0x20     // Enable motor voltage compensation.


// Configure overcurrent detection event handling

#define dSPIN_CONFIG_OC_SD                   0x0080 // Mask for this bit.

#define dSPIN_CONFIG_OC_SD_DISABLE           0x00     // Bridges do NOT shutdown on OC detect

#define dSPIN_CONFIG_OC_SD_ENABLE            0x80     // Bridges shutdown on OC detect


// Configure the slew rate of the power bridge output

#define dSPIN_CONFIG_POW_SR                  0x0300  // Mask for this bit field.

#define dSPIN_CONFIG_SR_320V_us              0x0000  // 320V/us

#define dSPIN_CONFIG_SR_75V_us               0x0100  // 75V/us

#define dSPIN_CONFIG_SR_110V_us              0x0200  // 110V/us

#define dSPIN_CONFIG_SR_260V_us              0x0300  // 260V/us


// Integer divisors for PWM sinewave generation

//  See page 32 of the datasheet for more information on this.

#define dSPIN_CONFIG_F_PWM_DEC               7 << 10      // mask for this bit field

#define dSPIN_CONFIG_PWM_MUL_0_625           0 << 10

#define dSPIN_CONFIG_PWM_MUL_0_75            1 << 10

#define dSPIN_CONFIG_PWM_MUL_0_875           2 << 10

#define dSPIN_CONFIG_PWM_MUL_1               3 << 10

#define dSPIN_CONFIG_PWM_MUL_1_25            4 << 10

#define dSPIN_CONFIG_PWM_MUL_1_5             5 << 10

#define dSPIN_CONFIG_PWM_MUL_1_75            6 << 10

#define dSPIN_CONFIG_PWM_MUL_2               7 << 10


// Multiplier for the PWM sinewave frequency

#define dSPIN_CONFIG_F_PWM_INT               7 << 13     // mask for this bit field.

#define dSPIN_CONFIG_PWM_DIV_1               0 << 13

#define dSPIN_CONFIG_PWM_DIV_2               1 << 13

#define dSPIN_CONFIG_PWM_DIV_3               2 << 13

#define dSPIN_CONFIG_PWM_DIV_4               3 << 13

#define dSPIN_CONFIG_PWM_DIV_5               4 << 13

#define dSPIN_CONFIG_PWM_DIV_6               5 << 13

#define dSPIN_CONFIG_PWM_DIV_7               6 << 13


// Register address redefines.

//  See the dSPIN_Param_Handler() function for more info about these.

#define  dSPIN_NO_OP       0x00

  // ABS_POS is the current absolute offset from home. It is a 22 bit number expressed

  //  in two's complement. At power up, this value is 0. It cannot be written when

  //  the motor is running, but at any other time, it can be updated to change the

  //  interpreted position of the motor.

#define  dSPIN_ABS_POS     0x01

  // EL_POS is the current electrical position in the step generation cycle. It can

  //  be set when the motor is not in motion. Value is 0 on power up.

#define  dSPIN_EL_POS      0x02

  // MARK is a second position other than 0 that the motor can be told to go to. As

  //  with ABS_POS, it is 22-bit two's complement. Value is 0 on power up.

#define  dSPIN_MARK        0x03

  // SPEED contains information about the current speed. It is read-only. It does

  //  NOT provide direction information.

#define  dSPIN_SPEED       0x04

  // ACC and DEC set the acceleration and deceleration rates. Set ACC to 0xFFF

  //  to get infinite acceleration/deceleration - there is no way to get infinite

  //  deceleration w/o infinite acceleration (except the HARD STOP command).

  //  Cannot be written while motor is running. Both default to 0x08A on power up.

  // AccCalc() and DecCalc() functions exist to convert steps/s/s values into

  //  12-bit values for these two registers.

#define  dSPIN_ACC         0x05

#define  dSPIN_DEC         0x06

  // MAX_SPEED is just what it says- any command which attempts to set the speed

  //  of the motor above this value will simply cause the motor to turn at this

  //  speed. Value is 0x041 on power up.

  // MaxSpdCalc() function exists to convert steps/s value into a 10-bit value

  //  for this register.

#define  dSPIN_MAX_SPEED   0x07

  // MIN_SPEED controls two things- the activation of the low-speed optimization

  //  feature and the lowest speed the motor will be allowed to operate at. LSPD_OPT

  //  is the 13th bit, and when it is set, the minimum allowed speed is automatically

  //  set to zero. This value is 0 on startup.

  // MinSpdCalc() function exists to convert steps/s value into a 12-bit value for this

  //  register. setLSPDOpt() function exists to enable/disable the optimization feature.

#define  dSPIN_MIN_SPEED   0x08

  // KVAL is the maximum voltage of the PWM outputs. These 8-bit values are ratiometric

  //  representations: 255 for full output voltage, 128 for half, etc. Default is 0x29.

  // The implications of different KVAL settings is too complex to dig into here, but

  //  it will usually work to max the value for RUN, ACC, and DEC. Maxing the value for

  //  HOLD may result in excessive power dissipation when the motor is not running.

#define  dSPIN_KVAL_HOLD   0x09

#define  dSPIN_KVAL_RUN    0x0A

#define  dSPIN_KVAL_ACC    0x0B

#define  dSPIN_KVAL_DEC    0x0C

  // INT_SPD, ST_SLP, FN_SLP_ACC and FN_SLP_DEC are all related to the back EMF

  //  compensation functionality. Please see the data sheet for details of this

  //  function- it is too complex to discuss here. Default values seem to work

  //  well enough.

#define  dSPIN_INT_SPD     0x0D

#define  dSPIN_ST_SLP      0x0E

#define  dSPIN_FN_SLP_ACC  0x0F

#define  dSPIN_FN_SLP_DEC  0x10

  // K_THERM is motor winding thermal drift compensation. Please see the data sheet

  //  for full details on operation- the default value should be OK for most users.

#define  dSPIN_K_THERM     0x11

  // ADC_OUT is a read-only register containing the result of the ADC measurements.

  //  This is less useful than it sounds; see the datasheet for more information.

#define  dSPIN_ADC_OUT     0x12

  // Set the over current threshold. Ranges from 375mA to 6A in steps of 375mA.

  //  A set of defined constants is provided for the user's convenience. Default

  //  value is 3.375A- 0x08. This is a 4-bit value.

#define  dSPIN_OCD_TH      0x13

  // Stall current threshold. Defaults to 0x40, or 2.03A. Value is from 31.25mA to

  //  4A in 31.25mA steps. This is a 7-bit value.

#define  dSPIN_STALL_TH    0x14

  // FS_SPD register contains a threshold value above which micro-stepping is disabled

  //  and the dSPIN operates in full-step mode. Defaults to 0x027 on power up.

  // FSCalc() function exists to convert steps/s value into 10-bit integer for this

  //  register.

#define  dSPIN_FS_SPD      0x15

  // STEP_MODE controls the micro stepping settings, as well as the generation of an

  //  output signal from the dSPIN. Bits 2:0 control the number of micro steps per

  //  step the part will generate. Bit 7 controls whether the BUSY/SYNC pin outputs

  //  a BUSY signal or a step synchronization signal. Bits 6:4 control the frequency

  //  of the output signal relative to the full-step frequency; see datasheet for

  //  that relationship as it is too complex to reproduce here.

  // Most likely, only the microsteps per step value will be needed; there is a set

  //  of constants provided for ease of use of these values.

#define  dSPIN_STEP_MODE   0x16

  // ALARM_EN controls which alarms will cause the FLAG pin to fall. A set of constants

  //  is provided to make this easy to interpret. By default, ALL alarms will trigger the

  //  FLAG pin.

#define  dSPIN_ALARM_EN    0x17

  // CONFIG contains some assorted configuration bits and fields. A fairly comprehensive

  //  set of reasonably self-explanatory constants is provided, but users should refer

  //  to the data sheet before modifying the contents of this register to be certain they

  //  understand the implications of their modifications. Value on boot is 0x2E88; this

  //  can be a useful way to verify proper start up and operation of the dSPIN chip.

#define  dSPIN_CONFIG      0x18

  // STATUS contains read-only information about the current condition of the chip. A

  //  comprehensive set of constants for masking and testing this register is provided, but

  //  users should refer to the data sheet to ensure that they fully understand each one of

  //  the bits in the register.

#define  dSPIN_STATUS      0x19


#define Bits4      0x00000F

#define Bits5      0x00001F

#define Bits7      0x00007F

#define Bits8      0x0000FF

#define Bits9      0x0001FF

#define Bits10     0x0003FF

#define Bits12     0x000FFF

#define Bits13     0x001FFF

#define Bits14     0x003FFF

#define Bits16     0x00FFFF

#define Bits20     0x0FFFFF

#define Bits22     0x3FFFFF


static const uint32_t registerMask[] = {

  0,

  Bits22, // ABS_POS

  Bits9,  // EL_POS

  Bits22, // MARK

  Bits20, // SPEED

  Bits12, // ACC

  Bits12, // DEC

  Bits10, // MAX_SPEED

  Bits13, // MIN_SPEED

  Bits10, // FS_SPD

  Bits8,  // KVAL_HOLD

  Bits8,  // KVAL_RUN

  Bits8,  // KVAL_ACC

  Bits8,  // KVAL_DEC

  Bits14, // INT_SPEED

  Bits8,  // ST_SLP

  Bits8,  // FN_SLP_ACC

  Bits8,  // FN_SLP_DEC

  Bits4,  // K_THERM

  Bits5,  // ADC_OUT

  Bits4,  // OCD_TH

  Bits7,  // STALL_TH

  Bits8,  // STEP_MODE

  Bits8,  // ALARM_EN

  Bits16, // CONFIG

  Bits16 }; // STATUS

  

//dSPIN commands

#define dSPIN_NOP             0x00

#define dSPIN_SET_PARAM       0x00

#define dSPIN_GET_PARAM       0x20

#define dSPIN_RUN             0x50

#define dSPIN_STEP_CLOCK      0x58

#define dSPIN_MOVE            0x40

#define dSPIN_GOTO            0x60

#define dSPIN_GOTO_DIR        0x68

#define dSPIN_GO_UNTIL        0x82

#define dSPIN_RELEASE_SW      0x92

#define dSPIN_GO_HOME         0x70

#define dSPIN_GO_MARK         0x78

#define dSPIN_RESET_POS       0xD8

#define dSPIN_RESET_DEVICE    0xC0

#define dSPIN_SOFT_STOP       0xB0

#define dSPIN_HARD_STOP       0xB8

#define dSPIN_SOFT_HIZ        0xA0

#define dSPIN_HARD_HIZ        0xA8

#define dSPIN_GET_STATUS      0xD0


/* dSPIN direction options */

#define FWD                   0x01

#define REV                0x00


/* dSPIN action options */

#define ACTION_RESET           0x00

#define ACTION_COPY           0x01


// The value in the MIN_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is

//  250ns (datasheet value)- 0x000 on boot.

#define MinSpeedConversionFactor      4.1943


// The value in the MAX_SPD register is [(steps/s)*(tick)]/(2^-18) where tick is

//  250ns (datasheet value)- 0x041 on boot.

#define MaxSpeedSetConversionFactor   0.065536


//  The 20-bit speed is (steps/s)*(tick)/(2^-28) where tick is

//  250ns (datasheet value). resolution 0.0149

#define SpeedConversionFactor         0.01490116

#define SpeedSetConversionFactor      67.108864


// The value in the INT_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is

//  250ns (datasheet value)- 0x408 on boot.


// The value in the ACC register is [(steps/s/s)*(tick^2)]/(2^-40) where tick is

//  250ns (datasheet value)- 0x08A on boot.

#define AccelerationConversionFactor  0.137438


#endif