Slightly altered version of Arduino OneStep

This library is specific to the ST L6474 stepper driver.

Files at this revision

API Documentation at this revision

Comitter:
jonebuckman
Date:
Wed Sep 02 15:43:40 2015 +0000
Commit message:
Slightly altered version of Arduino OneStep

Changed in this revision

OneStep.cpp Show annotated file Show diff for this revision Revisions of this file
OneStep.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OneStep.cpp	Wed Sep 02 15:43:40 2015 +0000
@@ -0,0 +1,458 @@
+/**
+ * @file OneStep.cpp
+ *
+ * @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:
+ *
+ *
+ */
+ 
+/**
+ * Includes
+ */
+#include "OneStep.h"
+
+/**
+ * Methods
+ */
+OneStep::OneStep(PinName mosi, 
+                PinName miso, 
+                PinName sck, 
+                PinName csn,
+                PinName step,
+                PinName dir,
+                PinName reset,
+                PinName flag) : spi_(mosi, miso, sck), nCS_(csn), step_(step), dir_(dir), reset_(reset), flag_(flag)   // step, direction, reset, flag
+{
+    //5MHz, see page 13 of datasheet for max clock.  May need to be reduces if using long wires
+    spi_.frequency(5000000);
+    spi_.format(8,3);
+
+    nCS_ = 1;
+
+    wait_us(500);
+
+    _currentPos = 0;
+    _targetPos = 0;
+    _speed = 0.0;
+    _maxSpeed = 1.0;
+    _acceleration = 0.0;
+    _sqrt_twoa = 1.0;
+    _stepInterval = 0;
+    _minPulseWidth = 1;
+    _lastStepTime = 0;
+
+    // NEW
+    _n = 0;
+    _c0 = 0.0;
+    _cn = 0.0;
+    _cmin = 1.0;
+    _direction = dir_ = DIRECTION_CCW;
+    reset_ = 0;
+    t_.start();
+}
+
+// No operation.
+void OneStep::nop(void) {
+    wait_us(1);
+    nCS_ = 0;
+    spi_.write(0x00);
+    nCS_ = 1;
+}
+
+// Enable driver.
+void OneStep::enable(void) {
+    wait_us(1);
+    nCS_ = 0;
+    spi_.write(ENBL);
+    nCS_ = 1;
+}
+
+// Disable driver.
+void OneStep::disable(void) {
+    wait_us(1);
+    nCS_ = 0;
+    spi_.write(DSBL);
+    nCS_ = 1;
+}
+
+// Set parameter value;
+void OneStep::set_param(char parameter, int length, int value) {
+    char val[3];
+    switch (length) {
+        case 1:
+            val[0] = (value & 0x0000ffUL)      ;
+            break;
+        case 2:
+            val[0] = (value & 0x00ff00UL) >>  8;
+            val[1] = (value & 0x0000ffUL)      ;
+            break;
+        case 3:
+            val[0] = (value & 0xff0000UL) >> 16;
+            val[1] = (value & 0x00ff00UL) >>  8;
+            val[2] = (value & 0x0000ffUL)      ;
+            break;
+    }
+    wait_us(1);
+    nCS_ = 0;
+    spi_.write(parameter);
+    nCS_ = 1;
+    for (int i = 0; i < length; i++) {
+        wait_us(1);
+        nCS_ = 0;
+        spi_.write(val[i]);
+        nCS_ = 1;
+    }
+}
+
+// Get parameter value.
+int OneStep::get_param(char parameter, int length) {
+    char output = 0x20 | parameter;
+    char buf[3] = {0, 0, 0};
+    wait_us(1);
+    nCS_ = 0;
+    spi_.write(output);
+    nCS_ = 1;
+    for (int i = 0; i < length; i++) {
+        wait_us(1);
+        nCS_ = 0;
+        buf[i] = spi_.write(0x00);
+        nCS_ = 1;
+    }
+    switch (length) {
+        case 1:
+            return buf[0];
+        case 2:
+            return buf[0] << 8 | buf[1];
+        case 3:
+            return buf[0] << 16 | buf[1] << 8 | buf[2];
+    }
+    return 0;
+}
+
+// Get status.
+int OneStep::get_status() {
+    int ret_bytes[2];
+    wait_us(1);
+    nCS_ = 0;
+    spi_.write(0xD0); //write request for status return
+    nCS_ = 1;
+    wait_us(1);
+    nCS_ = 0;
+    ret_bytes[0] = spi_.write(0x00);  //read first byte
+    nCS_ = 1;
+    wait_us(1);
+    nCS_ = 0;
+    ret_bytes[1] = spi_.write(0x00);  //read second byte
+    nCS_ = 1;
+    return ret_bytes[0] << 8 | ret_bytes[1];  //return i16 response
+}
+
+void OneStep::moveTo(long absolute)
+{
+    if (_targetPos != absolute)
+    {
+    _targetPos = absolute;
+    computeNewSpeed();
+    }
+}
+
+void OneStep::move(long relative)
+{
+    moveTo(_currentPos + relative);
+}
+
+// Implements steps according to the current step interval.
+// You must call this at least once per step
+// returns true if a step occurred.
+bool OneStep::runSpeed()
+{
+    // Dont do anything unless we actually have a step interval
+    if (!_stepInterval)
+        return false;
+
+    unsigned long time = t_.read_us();
+    // Gymnastics to detect wrapping of either the nextStepTime and/or the current time
+    unsigned long nextStepTime = _lastStepTime + _stepInterval;
+    if (   ((nextStepTime >= _lastStepTime) && ((time >= nextStepTime) || (time < _lastStepTime)))
+        || ((nextStepTime < _lastStepTime) && ((time >= nextStepTime) && (time < _lastStepTime))))
+
+    {
+        if (_direction == DIRECTION_CW)
+        {
+            // Clockwise
+            _currentPos += 1;
+        }
+        else
+        {
+            // Anticlockwise  
+            _currentPos -= 1;
+        }
+        step();
+
+        _lastStepTime = time;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+long OneStep::distanceToGo()
+{
+    return _targetPos - _currentPos;
+}
+
+long OneStep::targetPosition()
+{
+    return _targetPos;
+}
+
+long OneStep::currentPosition()
+{
+    return _currentPos;
+}
+
+// Useful during initialisations or after initial positioning
+// Sets speed to 0
+void OneStep::setCurrentPosition(long position)
+{
+    _targetPos = _currentPos = position;
+    _n = 0;
+    _stepInterval = 0;
+}
+
+void OneStep::computeNewSpeed()
+{
+    long distanceTo = distanceToGo(); // +ve is clockwise from curent location
+
+    long stepsToStop = (long)((_speed * _speed) / (2.0f * _acceleration)); // Equation 16
+
+    if (distanceTo == 0 && stepsToStop <= 1)
+    {
+    // We are at the target and its time to stop
+    _stepInterval = 0;
+    _speed = 0.0;
+    _n = 0;
+    return;
+    }
+
+    if (distanceTo > 0)
+    {
+    // We are anticlockwise from the target
+    // Need to go clockwise from here, maybe decelerate now
+    if (_n > 0)
+    {
+        // Currently accelerating, need to decel now? Or maybe going the wrong way?
+        if ((stepsToStop >= distanceTo) || _direction == DIRECTION_CCW)
+        _n = -stepsToStop; // Start deceleration
+    }
+    else if (_n < 0)
+    {
+        // Currently decelerating, need to accel again?
+        if ((stepsToStop < distanceTo) && _direction == DIRECTION_CW)
+        _n = -_n; // Start accceleration
+    }
+    }
+    else if (distanceTo < 0)
+    {
+    // We are clockwise from the target
+    // Need to go anticlockwise from here, maybe decelerate
+    if (_n > 0)
+    {
+        // Currently accelerating, need to decel now? Or maybe going the wrong way?
+        if ((stepsToStop >= -distanceTo) || _direction == DIRECTION_CW)
+        _n = -stepsToStop; // Start deceleration
+    }
+    else if (_n < 0)
+    {
+        // Currently decelerating, need to accel again?
+        if ((stepsToStop < -distanceTo) && _direction == DIRECTION_CCW)
+        _n = -_n; // Start accceleration
+    }
+    }
+
+    // Need to accelerate or decelerate
+    if (_n == 0)
+    {
+    // First step from stopped
+    _cn = _c0;
+    _direction = dir_ = (distanceTo > 0) ? DIRECTION_CW : DIRECTION_CCW;
+    }
+    else
+    {
+    // Subsequent step. Works for accel (n is +_ve) and decel (n is -ve).
+    _cn = _cn - ((2.0f * _cn) / ((4.0f * _n) + 1)); // Equation 13
+    _cn = max(_cn, _cmin); 
+    }
+    _n++;
+    _stepInterval = _cn;
+    _speed = 1000000.0f / _cn;
+    if (_direction == DIRECTION_CCW)
+    _speed = -_speed;
+}
+
+// Run the motor to implement speed and acceleration in order to proceed to the target position
+// You must call this at least once per step, preferably in your main loop
+// If the motor is in the desired position, the cost is very small
+// returns true if the motor is still running to the target position.
+bool OneStep::run()
+{
+    if (runSpeed())
+    computeNewSpeed();
+    return _speed != 0.0f || distanceToGo() != 0;
+}
+
+// Step once.
+void OneStep::step()
+{
+    step_ = 1;
+    wait_us(5);
+    step_ = 0;
+}
+
+// Set the max speed.
+void OneStep::setMaxSpeed(float speed)
+{
+    if (_maxSpeed != speed)
+    {
+        _maxSpeed = speed;
+        _cmin = 1000000.0f / speed;
+        // Recompute _n from current speed and adjust speed if accelerating or cruising
+        if (_n > 0)
+        {
+            _n = (long)((_speed * _speed) / (2.0f * _acceleration)); // Equation 16
+            computeNewSpeed();
+        }
+    }
+}
+
+// Set the acceleration.
+void OneStep::setAcceleration(float acceleration)
+{
+    if (acceleration == 0.0f)
+        return;
+    if (_acceleration != acceleration)
+    {
+        // Recompute _n per Equation 17
+        _n = _n * (_acceleration / acceleration);
+        // New c0 per Equation 7
+        //_c0 = sqrt(2.0 / acceleration) * 1000000.0; // Accelerates at half the expected rate. Why?
+        _c0 = sqrt(1.0f/acceleration) * 1000000.0f;
+        _acceleration = acceleration;
+        computeNewSpeed();
+    }
+}
+
+// Set the speed.
+void OneStep::setSpeed(float speed)
+{
+    if (speed == _speed)
+        return;
+    speed = constrain(speed, -_maxSpeed, _maxSpeed);
+    if (speed == 0.0f)
+        _stepInterval = 0;
+    else
+    {
+        _stepInterval = fabs(1000000.0f / speed);
+        _direction = dir_ = (speed > 0.0f) ? DIRECTION_CW : DIRECTION_CCW;
+    }
+    _speed = speed;
+}
+
+// Get current speed.
+float OneStep::speed()
+{
+    return _speed;
+}
+
+// Set the minimum pulse width.
+void OneStep::setMinPulseWidth(unsigned int minWidth)
+{
+    _minPulseWidth = minWidth;
+}
+
+// System reset enable.
+void OneStep::enableReset()
+{
+    reset_ = 0;
+}
+
+// System reset disable.
+void OneStep::disableReset()
+{
+    reset_ = 1;
+}
+
+// Blocks until the target position is reached and stopped.
+void OneStep::runToPosition()
+{
+    while (run())
+    ;
+}
+
+// Run at speed to a position.
+bool OneStep::runSpeedToPosition()
+{
+    if (_targetPos == _currentPos)
+    return false;
+    if (_targetPos >_currentPos)
+    _direction = dir_ = DIRECTION_CW;
+    else
+    _direction = dir_ = DIRECTION_CCW;
+    return runSpeed();
+}
+
+// Blocks until the new target position is reached.
+void OneStep::runToNewPosition(long position)
+{
+    moveTo(position);
+    runToPosition();
+}
+
+void OneStep::stop()
+{
+    if (_speed != 0.0f)
+    {    
+    long stepsToStop = (long)((_speed * _speed) / (2.0f * _acceleration)) + 1; // Equation 16 (+integer rounding)
+    if (_speed > 0)
+        move(stepsToStop);
+    else
+        move(-stepsToStop);
+    }
+}
+
+// Get the alarm flag state.
+int OneStep::getAlarm()
+{
+    return(flag_);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OneStep.h	Wed Sep 02 15:43:40 2015 +0000
@@ -0,0 +1,801 @@
+/**
+ * @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
\ No newline at end of file