Slightly altered version of Arduino OneStep

This library is specific to the ST L6474 stepper driver.

OneStep.h

Committer:
jonebuckman
Date:
2015-09-02
Revision:
0:92e1b5622620

File content as of revision 0:92e1b5622620:

/**
 * @file OneStep.h
 *
 * @author Jon Buckman
 * 
 * @section LICENSE
 *
 * Copyright (c) 2014 Jon Buckman
 *
 * Copyright (C) 2009-2013 Mike McCauley
 * $Id: AccelStepper.cpp,v 1.19 2014/10/31 06:05:27 mikem Exp mikem $
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * @section DESCRIPTION
 *
 * OneStep stepper motor accelerate and manipulate.
 *
 * Datasheet:
 *
 *
 *
 * Example:
 * @code
 * #include "mbed.h"
 * #include "OneStep.h"
 *
 * Serial pc(USBTX, USBRX); // tx, rx
 *
 * OneStep stepper(D11, D12, D13, D10, D9, D7, D8, D2);   // mosi, miso, sck, nCS_(cs), step, direction, reset, flag
 * 
 * int main() {
 *    while(1)
 *    {
 *       if (stepper.distanceToGo() == 0)
 *       {
 *          // Random change to speed, position and acceleration
 *          // Make sure we dont get 0 speed or accelerations
 *          wait_us(1000);
 *          stepper.moveTo(rand() % 200);
 *          stepper.setMaxSpeed((rand() % 200) + 1);
 *          stepper.setAcceleration((rand() % 200) + 1);
 *          if(stepper.getAlarm() == 0) {
 *              pc.printf("alarm\r\n");
 *          }
 *       }
 *       stepper.run();
 *    }
 * }
 * @endcode
 */

#ifndef ONESTEP_H
#define ONESTEP_H

/**
 * Includes
 */
#include <mbed.h>

/**
 * Defines
 */
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))

/** 
 * @brief easySPIN Init structure definition
 */
typedef struct {
    uint32_t ABS_POS;
    uint16_t EL_POS;
    uint32_t MARK;
    uint8_t TVAL;
    uint8_t T_FAST;
    uint8_t TON_MIN;
    uint8_t TOFF_MIN;
    uint8_t ADC_OUT;
    uint8_t OCD_TH;
    uint8_t STEP_MODE;
    uint8_t ALARM_EN;
    uint16_t CONFIG;
} RegsStruct_TypeDef;

/* easySPIN TVAL register options */
typedef enum {
    TVAL_31_25mA    = ((uint8_t) 0x00),
    TVAL_62_5mA     = ((uint8_t) 0x01),
    TVAL_93_75mA    = ((uint8_t) 0x02),
    TVAL_125mA      = ((uint8_t) 0x03),
    TVAL_156_25mA   = ((uint8_t) 0x04),
    TVAL_187_5mA    = ((uint8_t) 0x05),
    TVAL_218_75mA   = ((uint8_t) 0x06),
    TVAL_250mA      = ((uint8_t) 0x07),
    TVAL_281_25mA   = ((uint8_t) 0x08),
    TVAL_312_5mA    = ((uint8_t) 0x09),
    TVAL_343_75mA   = ((uint8_t) 0x0A),
    TVAL_375mA      = ((uint8_t) 0x0B),
    TVAL_406_25mA   = ((uint8_t) 0x0C),
    TVAL_437_5mA    = ((uint8_t) 0x0D),
    TVAL_468_75mA   = ((uint8_t) 0x0E),
    TVAL_500mA      = ((uint8_t) 0x0F),
    TVAL_531_25mA   = ((uint8_t) 0x10),
    TVAL_562_5mA    = ((uint8_t) 0x11),
    TVAL_593_75mA   = ((uint8_t) 0x12),
    TVAL_625mA      = ((uint8_t) 0x13),
    TVAL_656_25mA   = ((uint8_t) 0x14),
    TVAL_687_5mA    = ((uint8_t) 0x15),
    TVAL_718_75mA   = ((uint8_t) 0x16),
    TVAL_750mA      = ((uint8_t) 0x17),
    TVAL_781_25mA   = ((uint8_t) 0x18),
    TVAL_812_5mA    = ((uint8_t) 0x19),
    TVAL_843_75mA   = ((uint8_t) 0x1A),
    TVAL_875mA      = ((uint8_t) 0x1B),
    TVAL_906_25mA   = ((uint8_t) 0x1C),
    TVAL_937_5mA    = ((uint8_t) 0x1D),
    TVAL_968_75mA   = ((uint8_t) 0x1E),
    TVAL_1000mA     = ((uint8_t) 0x1F),
    TVAL_1031_25mA  = ((uint8_t) 0x20),
    TVAL_1062_5mA   = ((uint8_t) 0x21),
    TVAL_1093_75mA  = ((uint8_t) 0x22),
    TVAL_1125mA     = ((uint8_t) 0x23),
    TVAL_1156_25mA  = ((uint8_t) 0x24),
    TVAL_1187_5mA   = ((uint8_t) 0x25),
    TVAL_1218_75mA  = ((uint8_t) 0x26),
    TVAL_1250mA     = ((uint8_t) 0x27),
    TVAL_1281_25mA  = ((uint8_t) 0x28),
    TVAL_1312_5mA   = ((uint8_t) 0x29),
    TVAL_1343_75mA  = ((uint8_t) 0x2A),
    TVAL_1375mA     = ((uint8_t) 0x2B),
    TVAL_1406_25mA  = ((uint8_t) 0x2C),
    TVAL_1437_5mA   = ((uint8_t) 0x2D),
    TVAL_1468_75mA  = ((uint8_t) 0x2E),
    TVAL_1500mA     = ((uint8_t) 0x2F),
    TVAL_1531_25mA  = ((uint8_t) 0x30),
    TVAL_1562_5mA   = ((uint8_t) 0x31),
    TVAL_1593_75mA  = ((uint8_t) 0x32),
    TVAL_1625mA     = ((uint8_t) 0x33),
    TVAL_1656_25mA  = ((uint8_t) 0x34),
    TVAL_1687_5mA   = ((uint8_t) 0x35),
    TVAL_1718_75mA  = ((uint8_t) 0x36),
    TVAL_1750mA     = ((uint8_t) 0x37),
    TVAL_1781_25mA  = ((uint8_t) 0x38),
    TVAL_1812_5mA   = ((uint8_t) 0x39),
    TVAL_1843_75mA  = ((uint8_t) 0x3A),
    TVAL_1875mA     = ((uint8_t) 0x3B),
    TVAL_1906_25mA  = ((uint8_t) 0x3C),
    TVAL_1937_5mA   = ((uint8_t) 0x3D),
    TVAL_1968_75mA  = ((uint8_t) 0x3E),
    TVAL_2000mA     = ((uint8_t) 0x3F),
    TVAL_2031_25mA  = ((uint8_t) 0x40),
    TVAL_2062_5mA   = ((uint8_t) 0x41),
    TVAL_2093_75mA  = ((uint8_t) 0x42),
    TVAL_2125mA     = ((uint8_t) 0x43),
    TVAL_2156_25mA  = ((uint8_t) 0x44),
    TVAL_2187_5mA   = ((uint8_t) 0x45),
    TVAL_2218_75mA  = ((uint8_t) 0x46),
    TVAL_2250mA     = ((uint8_t) 0x47),
    TVAL_2281_25mA  = ((uint8_t) 0x48),
    TVAL_2312_5mA   = ((uint8_t) 0x49),
    TVAL_2343_75mA  = ((uint8_t) 0x4A),
    TVAL_2375mA     = ((uint8_t) 0x4B),
    TVAL_2406_25mA  = ((uint8_t) 0x4C),
    TVAL_2437_5mA   = ((uint8_t) 0x4D),
    TVAL_2468_75mA  = ((uint8_t) 0x4E),
    TVAL_2500mA     = ((uint8_t) 0x4F),
    TVAL_2531_25mA  = ((uint8_t) 0x50),
    TVAL_2562_5mA   = ((uint8_t) 0x51),
    TVAL_2593_75mA  = ((uint8_t) 0x52),
    TVAL_2625mA     = ((uint8_t) 0x53),
    TVAL_2656_25mA  = ((uint8_t) 0x54),
    TVAL_2687_5mA   = ((uint8_t) 0x55),
    TVAL_2718_75mA  = ((uint8_t) 0x56),
    TVAL_2750mA     = ((uint8_t) 0x57),
    TVAL_2781_25mA  = ((uint8_t) 0x58),
    TVAL_2812_5mA   = ((uint8_t) 0x59),
    TVAL_2843_75mA  = ((uint8_t) 0x5A),
    TVAL_2875mA     = ((uint8_t) 0x5B),
    TVAL_2906_25mA  = ((uint8_t) 0x5C),
    TVAL_2937_5mA   = ((uint8_t) 0x5D),
    TVAL_2968_75mA  = ((uint8_t) 0x5E),
    TVAL_3000mA     = ((uint8_t) 0x5F),
    TVAL_3031_25mA  = ((uint8_t) 0x60),
    TVAL_3062_5mA   = ((uint8_t) 0x61),
    TVAL_3093_75mA  = ((uint8_t) 0x62),
    TVAL_3125mA     = ((uint8_t) 0x63),
    TVAL_3156_25mA  = ((uint8_t) 0x64),
    TVAL_3187_5mA   = ((uint8_t) 0x65),
    TVAL_3218_75mA  = ((uint8_t) 0x66),
    TVAL_3250mA     = ((uint8_t) 0x67),
    TVAL_3281_25mA  = ((uint8_t) 0x68),
    TVAL_3312_5mA   = ((uint8_t) 0x69),
    TVAL_3343_75mA  = ((uint8_t) 0x6A),
    TVAL_3375mA     = ((uint8_t) 0x6B),
    TVAL_3406_25mA  = ((uint8_t) 0x6C),
    TVAL_3437_5mA   = ((uint8_t) 0x6D),
    TVAL_3468_75mA  = ((uint8_t) 0x6E),
    TVAL_3500mA     = ((uint8_t) 0x6F),
    TVAL_3531_25mA  = ((uint8_t) 0x70),
    TVAL_3562_5mA   = ((uint8_t) 0x71),
    TVAL_3593_75mA  = ((uint8_t) 0x72),
    TVAL_3625mA     = ((uint8_t) 0x73),
    TVAL_3656_25mA  = ((uint8_t) 0x74),
    TVAL_3687_5mA   = ((uint8_t) 0x75),
    TVAL_3718_75mA  = ((uint8_t) 0x76),
    TVAL_3750mA     = ((uint8_t) 0x77),
    TVAL_3781_25mA  = ((uint8_t) 0x78),
    TVAL_3812_5mA   = ((uint8_t) 0x79),
    TVAL_3843_75mA  = ((uint8_t) 0x7A),
    TVAL_3875mA     = ((uint8_t) 0x7B),
    TVAL_3906_25mA  = ((uint8_t) 0x7C),
    TVAL_3937_5mA   = ((uint8_t) 0x7D),
    TVAL_3968_75mA  = ((uint8_t) 0x7E),
    TVAL_4000mA     = ((uint8_t) 0x7F)
} TVAL_TypeDef;

/* easySPIN T_FAST register options */
typedef enum {
    TOFF_FAST_0_5_us = ((uint8_t) 0x00 << 4),
    TOFF_FAST_1_0_us = ((uint8_t) 0x01 << 4),
    TOFF_FAST_1_5_us = ((uint8_t) 0x02 << 4),
    TOFF_FAST_2_0_us = ((uint8_t) 0x03 << 4),
    TOFF_FAST_2_5_us = ((uint8_t) 0x04 << 4),
    TOFF_FAST_3_0_us = ((uint8_t) 0x05 << 4),
    TOFF_FAST_3_5_us = ((uint8_t) 0x06 << 4),
    TOFF_FAST_4_0_us = ((uint8_t) 0x07 << 4),
    TOFF_FAST_4_5_us = ((uint8_t) 0x08 << 4),
    TOFF_FAST_5_0_us = ((uint8_t) 0x09 << 4),
    TOFF_FAST_5_5_us = ((uint8_t) 0x0A << 4),
    TOFF_FAST_6_0_us = ((uint8_t) 0x0B << 4),
    TOFF_FAST_6_5_us = ((uint8_t) 0x0C << 4),
    TOFF_FAST_7_0_us = ((uint8_t) 0x0D << 4),
    TOFF_FAST_7_5_us = ((uint8_t) 0x0E << 4),
    TOFF_FAST_8_0_us = ((uint8_t) 0x0F << 4)
} TOFF_FAST_TypeDef;

typedef enum {
    FAST_STEP_0_5_us = ((uint8_t) 0x00),
    FAST_STEP_1_0_us = ((uint8_t) 0x01),
    FAST_STEP_1_5_us = ((uint8_t) 0x02),
    FAST_STEP_2_0_us = ((uint8_t) 0x03),
    FAST_STEP_2_5_us = ((uint8_t) 0x04),
    FAST_STEP_3_0_us = ((uint8_t) 0x05),
    FAST_STEP_3_5_us = ((uint8_t) 0x06),
    FAST_STEP_4_0_us = ((uint8_t) 0x07),
    FAST_STEP_4_5_us = ((uint8_t) 0x08),
    FAST_STEP_5_0_us = ((uint8_t) 0x09),
    FAST_STEP_5_5_us = ((uint8_t) 0x0A),
    FAST_STEP_6_0_us = ((uint8_t) 0x0B),
    FAST_STEP_6_5_us = ((uint8_t) 0x0C),
    FAST_STEP_7_0_us = ((uint8_t) 0x0D),
    FAST_STEP_7_5_us = ((uint8_t) 0x0E),
    FAST_STEP_8_0_us = ((uint8_t) 0x0F)
} FAST_STEP_TypeDef;

/* easySPIN overcurrent threshold options */
typedef enum {
    OCD_TH_375mA  = ((uint8_t) 0x00),
    OCD_TH_750mA  = ((uint8_t) 0x01),
    OCD_TH_1125mA = ((uint8_t) 0x02),
    OCD_TH_1500mA = ((uint8_t) 0x03),
    OCD_TH_1875mA = ((uint8_t) 0x04),
    OCD_TH_2250mA = ((uint8_t) 0x05),
    OCD_TH_2625mA = ((uint8_t) 0x06),
    OCD_TH_3000mA = ((uint8_t) 0x07),
    OCD_TH_3375mA = ((uint8_t) 0x08),
    OCD_TH_3750mA = ((uint8_t) 0x09),
    OCD_TH_4125mA = ((uint8_t) 0x0A),
    OCD_TH_4500mA = ((uint8_t) 0x0B),
    OCD_TH_4875mA = ((uint8_t) 0x0C),
    OCD_TH_5250mA = ((uint8_t) 0x0D),
    OCD_TH_5625mA = ((uint8_t) 0x0E),
    OCD_TH_6000mA = ((uint8_t) 0x0F)
} OCD_TH_TypeDef;

/* easySPIN STEP_MODE register masks */
typedef enum {
    STEP_MODE_STEP_SEL = ((uint8_t) 0x07),
    STEP_MODE_SYNC_SEL = ((uint8_t) 0x70)
} STEP_MODE_Masks_TypeDef;

/* easySPIN STEP_MODE register options */
/* easySPIN STEP_SEL options */
typedef enum {
    STEP_SEL_1    = ((uint8_t) 0x08),
    STEP_SEL_1_2  = ((uint8_t) 0x09),
    STEP_SEL_1_4  = ((uint8_t) 0x0A),
    STEP_SEL_1_8  = ((uint8_t) 0x0B),
    STEP_SEL_1_16 = ((uint8_t) 0x0C)
} STEP_SEL_TypeDef;

/* easySPIN SYNC_SEL options */
typedef enum {
    SYNC_SEL_1_2    = ((uint8_t) 0x80),
    SYNC_SEL_1      = ((uint8_t) 0x90),
    SYNC_SEL_2      = ((uint8_t) 0xA0),
    SYNC_SEL_4      = ((uint8_t) 0xB0),
    SYNC_SEL_8      = ((uint8_t) 0xC0),
    SYNC_SEL_UNUSED = ((uint8_t) 0xD0)
} SYNC_SEL_TypeDef;

/* easySPIN ALARM_EN register options */
typedef enum {
    ALARM_EN_OVERCURRENT      = ((uint8_t) 0x01),
    ALARM_EN_THERMAL_SHUTDOWN = ((uint8_t) 0x02),
    ALARM_EN_THERMAL_WARNING  = ((uint8_t) 0x04),
    ALARM_EN_UNDERVOLTAGE     = ((uint8_t) 0x08),
    ALARM_EN_SW_TURN_ON       = ((uint8_t) 0x40),
    ALARM_EN_WRONG_NPERF_CMD  = ((uint8_t) 0x80)
} ALARM_EN_TypeDef;

/* easySPIN Config register masks */
typedef enum {
    CONFIG_OSC_SEL  = ((uint16_t) 0x0007),
    CONFIG_EXT_CLK  = ((uint16_t) 0x0008),
    CONFIG_EN_TQREG = ((uint16_t) 0x0020),
    CONFIG_OC_SD    = ((uint16_t) 0x0080),
    CONFIG_POW_SR   = ((uint16_t) 0x0300),
    CONFIG_TSW      = ((uint16_t) 0x7C00)
} CONFIG_Masks_TypeDef;

/* easySPIN Config register options */
typedef enum {
    CONFIG_INT_16MHZ = ((uint16_t) 0x0000),
    CONFIG_INT_16MHZ_OSCOUT_2MHZ   = ((uint16_t) 0x0008),
    CONFIG_INT_16MHZ_OSCOUT_4MHZ   = ((uint16_t) 0x0009),
    CONFIG_INT_16MHZ_OSCOUT_8MHZ   = ((uint16_t) 0x000A),
    CONFIG_INT_16MHZ_OSCOUT_16MHZ  = ((uint16_t) 0x000B),
    CONFIG_EXT_8MHZ_XTAL_DRIVE     = ((uint16_t) 0x0004),
    CONFIG_EXT_16MHZ_XTAL_DRIVE    = ((uint16_t) 0x0005),
    CONFIG_EXT_24MHZ_XTAL_DRIVE    = ((uint16_t) 0x0006),
    CONFIG_EXT_32MHZ_XTAL_DRIVE    = ((uint16_t) 0x0007),
    CONFIG_EXT_8MHZ_OSCOUT_INVERT  = ((uint16_t) 0x000C),
    CONFIG_EXT_16MHZ_OSCOUT_INVERT = ((uint16_t) 0x000D),
    CONFIG_EXT_24MHZ_OSCOUT_INVERT = ((uint16_t) 0x000E),
    CONFIG_EXT_32MHZ_OSCOUT_INVERT = ((uint16_t) 0x000F)
} CONFIG_OSC_MGMT_TypeDef;

typedef enum {
    CONFIG_EN_TQREG_INT_REG = ((uint16_t) 0x0000),
    CONFIG_EN_TQREG_ADC_IN  = ((uint16_t) 0x0020)
} CONFIG_EN_TQREG_TypeDef;

typedef enum {
    CONFIG_OC_SD_DISABLE = ((uint16_t) 0x0000),
    CONFIG_OC_SD_ENABLE  = ((uint16_t) 0x0080)
} CONFIG_OC_SD_TypeDef;

typedef enum {
    CONFIG_SR_180V_us = ((uint16_t) 0x0000),
    CONFIG_SR_290V_us = ((uint16_t) 0x0200),
    CONFIG_SR_530V_us = ((uint16_t) 0x0300)
} CONFIG_POW_SR_TypeDef;

typedef enum {
    CONFIG_TSW_4_us   = (((uint16_t) 0x01) << 10),
    CONFIG_TSW_8_us   = (((uint16_t) 0x02) << 10),
    CONFIG_TSW_12_us  = (((uint16_t) 0x03) << 10),
    CONFIG_TSW_16_us  = (((uint16_t) 0x04) << 10),
    CONFIG_TSW_20_us  = (((uint16_t) 0x05) << 10),
    CONFIG_TSW_24_us  = (((uint16_t) 0x06) << 10),
    CONFIG_TSW_28_us  = (((uint16_t) 0x07) << 10),
    CONFIG_TSW_32_us  = (((uint16_t) 0x08) << 10),
    CONFIG_TSW_36_us  = (((uint16_t) 0x09) << 10),
    CONFIG_TSW_40_us  = (((uint16_t) 0x0A) << 10),
    CONFIG_TSW_44_us  = (((uint16_t) 0x0B) << 10),
    CONFIG_TSW_48_us  = (((uint16_t) 0x0C) << 10),
    CONFIG_TSW_52_us  = (((uint16_t) 0x0D) << 10),
    CONFIG_TSW_56_us  = (((uint16_t) 0x0E) << 10),
    CONFIG_TSW_60_us  = (((uint16_t) 0x0F) << 10),
    CONFIG_TSW_64_us  = (((uint16_t) 0x10) << 10),
    CONFIG_TSW_68_us  = (((uint16_t) 0x11) << 10),
    CONFIG_TSW_72_us  = (((uint16_t) 0x12) << 10),
    CONFIG_TSW_76_us  = (((uint16_t) 0x13) << 10),
    CONFIG_TSW_80_us  = (((uint16_t) 0x14) << 10),
    CONFIG_TSW_84_us  = (((uint16_t) 0x15) << 10),
    CONFIG_TSW_88_us  = (((uint16_t) 0x16) << 10),
    CONFIG_TSW_92_us  = (((uint16_t) 0x17) << 10),
    CONFIG_TSW_96_us  = (((uint16_t) 0x18) << 10),
    CONFIG_TSW_100_us = (((uint16_t) 0x19) << 10),
    CONFIG_TSW_104_us = (((uint16_t) 0x1A) << 10),
    CONFIG_TSW_108_us = (((uint16_t) 0x1B) << 10),
    CONFIG_TSW_112_us = (((uint16_t) 0x1C) << 10),
    CONFIG_TSW_116_us = (((uint16_t) 0x1D) << 10),
    CONFIG_TSW_120_us = (((uint16_t) 0x1E) << 10),
    CONFIG_TSW_124_us = (((uint16_t) 0x1F) << 10)
} CONFIG_TSW_TypeDef;

/* Status Register bit masks */
typedef enum {
    STATUS_HIZ         = (((uint16_t) 0x0001)),
    STATUS_DIR         = (((uint16_t) 0x0010)),
    STATUS_NOTPERF_CMD = (((uint16_t) 0x0080)),
    STATUS_WRONG_CMD   = (((uint16_t) 0x0100)),
    STATUS_UVLO        = (((uint16_t) 0x0200)),
    STATUS_TH_WRN      = (((uint16_t) 0x0400)),
    STATUS_TH_SD       = (((uint16_t) 0x0800)),
    STATUS_OCD         = (((uint16_t) 0x1000))
} STATUS_Masks_TypeDef;

/* Status Register options */
typedef enum {
    STATUS_DIR_FORWARD = (((uint16_t) 0x0001) << 4),
    STATUS_DIR_REVERSE = (((uint16_t) 0x0000) << 4)
} STATUS_DIR_TypeDef;

/* easySPIN internal register addresses */
typedef enum {
    ABS_POS        = ((uint8_t) 0x01),
    EL_POS         = ((uint8_t) 0x02),
    MARK           = ((uint8_t) 0x03),
    RESERVED_REG01 = ((uint8_t) 0x04),
    RESERVED_REG02 = ((uint8_t) 0x05),
    RESERVED_REG03 = ((uint8_t) 0x06),
    RESERVED_REG04 = ((uint8_t) 0x07),
    RESERVED_REG05 = ((uint8_t) 0x08),
    RESERVED_REG06 = ((uint8_t) 0x15),
    TVAL           = ((uint8_t) 0x09),
    RESERVED_REG07 = ((uint8_t) 0x0A),
    RESERVED_REG08 = ((uint8_t) 0x0B),
    RESERVED_REG09 = ((uint8_t) 0x0C),
    RESERVED_REG10 = ((uint8_t) 0x0D),
    T_FAST         = ((uint8_t) 0x0E),
    TON_MIN        = ((uint8_t) 0x0F),
    TOFF_MIN       = ((uint8_t) 0x10),
    RESERVED_REG11 = ((uint8_t) 0x11),
    ADC_OUT        = ((uint8_t) 0x12),
    OCD_TH         = ((uint8_t) 0x13),
    RESERVED_REG12 = ((uint8_t) 0x14),
    STEP_MODE      = ((uint8_t) 0x16),
    ALARM_EN       = ((uint8_t) 0x17),
    CONFIG         = ((uint8_t) 0x18),
    STATUS         = ((uint8_t) 0x19),
    RESERVED_REG13 = ((uint8_t) 0x1A),
    RESERVED_REG14 = ((uint8_t) 0x1B)
} Registers_TypeDef;

/* easySPIN command set */
typedef enum {
    NOP           = ((uint8_t) 0x00),
    SET_PARAM     = ((uint8_t) 0x00),
    GET_PARAM     = ((uint8_t) 0x20),
    ENBL          = ((uint8_t) 0xB8),
    DSBL          = ((uint8_t) 0xA8),
    GET_STATUS    = ((uint8_t) 0xD0),
    RESERVED_CMD1 = ((uint8_t) 0xEB),
    RESERVED_CMD2 = ((uint8_t) 0xF8)
} Commands_TypeDef;

/* easySPIN movement direction options */
typedef enum {
    DIR_Forward = ((uint8_t) 0x01), DIR_Reverse = ((uint8_t) 0x00)
} Direction_TypeDef;

/* easySPIN action options */
typedef enum {
    ACTION_RESET = ((uint8_t) 0x00), ACTION_COPY = ((uint8_t) 0x01)
} Action_TypeDef;

/**
 * OneStep stepper motor accelerate and manipulate.
 */
class OneStep {

public:

    /**
     * Constructor.
     *
     * @param step mbed pin to use for stepper motor interface.
     * @param direction mbed pin to use for stepper motor interface.
     * @param enable mbed pin to use for stepper motor interface.
     */
    OneStep(PinName mosi, 
                PinName miso, 
                PinName sck, 
                PinName csn,
                PinName step,
                PinName dir,
                PinName reset,
                PinName flag);

    /**
     * No operation.
     *
     */
    void nop(void);

    /**
     * Enable driver
     *
     */
    void enable(void);

    /**
     * Disable driver
     *
     */
    void disable(void);

    /**
     * Move to a position.
     *
     * @param parameter Parameter.
     * @param length The length of the parameter.
     * @param value The value of the parameter.
     */
    void set_param(char parameter, int length, int value);

    /**
     * Get parameter value.
     *
     * @param parameter Parameter.
     * @param length The length of the parameter.
     * @return Returns parameter.
     */
    int get_param(char parameter, int length);

    /**
     * Get status.
     *
     * @return Returns status word.
     */
    int get_status(void);

    /**
     * Move to a position.
     *
     * @param absolute Absolute step count.
     */
    void moveTo(long absolute);

    /**
     * Move to a position relative to the current position.
     *
     * @param relative Relative step count.
     */
    void move(long relative);

    /**
     * Implements steps according to the current step interval.
     *
     * @return Returns true if a step occurred.
     */
    bool runSpeed();

    /**
     * Get distance yet to go.
     *
     * @return The distance count.
     */
    long distanceToGo();

    /**
     * Get target position.
     *
     * @return The target position count.
     */
    long targetPosition();

    /**
     * Get current position.
     *
     * @return The current position count.
     */
    long currentPosition();

    /**
     * Set current position to a count. Set speed to 0.
     *
     * @param position The count at the current position.
     */
    void setCurrentPosition(long position);

    /**
     * Calculate the new speed.
     *
     */
    void computeNewSpeed();

    /**
     * Run the motor to implement speed and acceleration in order to proceed to the target position.
     *
     * @return Returns true if the motor is still running to the target position.
     */
    bool run();

    /**
     * Step once.
     *
     */
    void step();

    /**
     * Set the max speed.
     *
     * @param speed Speed maximum.
     */
    void setMaxSpeed(float speed);

    /**
     * Set the acceleration.
     *
     * @param acceleration Acceleration.
     */
    void setAcceleration(float acceleration);

    /**
     * Set the speed.
     *
     * @param speed Speed.
     */
    void setSpeed(float speed);

    /**
     * Get current speed.
     *
     * @return The speed.
     */
    float speed();

    /**
     * Set the minimum pulse width.
     *
     * @param minWidth MinWidth pulse width.
     */
    void setMinPulseWidth(unsigned int minWidth);

    /**
     * System reset enable.
     *
     */
    void enableReset();

    /**
     * System reset disable.
     *
     */
    void disableReset();

    /**
     * Blocks until the target position is reached and stopped.
     *
     */
    void runToPosition();

    /**
     * Run at speed to a position.
     *
     * @return The run speed.
     */
    bool runSpeedToPosition();

    /**
     * Blocks until the new target position is reached.
     *
     * @param position Position.
     */
    void runToNewPosition(long position);

    /**
     * Stop run to position.
     *
     */
    void stop();

    /**
     * Get the alarm flag state.
     *
     * @return The alarm flag state.
     */
    int getAlarm();

protected:

    /**
     * Symbolic names for the direction the motor is turning.
     *
     */
    typedef enum
    {
        DIRECTION_CCW = 0,  ///< Clockwise
        DIRECTION_CW  = 1   ///< Counter-Clockwise
    } Direction;

private:

    /**
     * The current absolution position in steps.
     *
     */
    long           _currentPos;    // Steps

    /**
     * The current interval between steps in microseconds.
     * 0 means the motor is currently stopped with _speed == 0
     *
     */
    unsigned long  _stepInterval;

    /**
     * The last step time in microseconds.
     *
     */
    unsigned long  _lastStepTime;

    /**
     * The minimum allowed pulse width in microseconds.
     *
     */
    unsigned int   _minPulseWidth;

    /**
     * The target position in steps. The AccelStepper library will move the
     * motor from the _currentPos to the _targetPos, taking into account the
     * max speed, acceleration and deceleration.
     *
     */
    long           _targetPos;     // Steps

    /**
     * The current motos speed in steps per second.
     * Positive is clockwise.
     *
     */
    float          _speed;         // Steps per second

    /**
     * The acceleration to use to accelerate or decelerate the motor in steps
     * per second per second. Must be > 0.
     *
     */
    float          _acceleration;
    float          _sqrt_twoa; // Precomputed sqrt(2*_acceleration)

    /**
     * The maximum permitted speed in steps per second. Must be > 0.
     *
     */
    float          _maxSpeed;

    /**
     * Min step size in microseconds based on maxSpeed.
     *
     */
    float _cmin; // at max speed

    /**
     * Initial step size in microseconds.
     *
     */
    float _c0;

    /**
     * Last step size in microseconds.
     *
     */
    float _cn;

    /**
     * The step counter for speed calculations.
     *
     */
    long _n;

    /**
     * Current direction motor is spinning in.
     *
     */
    bool _direction; // 1 == CW

    SPI spi_;
    Timer t_;
    DigitalOut nCS_;
    DigitalOut step_;
    DigitalOut dir_;
    DigitalOut reset_;
    DigitalIn flag_;
};

#endif