/******************************************************//**
  * @file    l6208.h 
  * @author  IPC Rennes
  * @version V1.5.0
  * @date    June 1st, 2018
  * @brief   Header for l6208.c module
  * @note    (C) COPYRIGHT 2016 STMicroelectronics
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _L6208_H_INCLUDED
#define _L6208_H_INCLUDED

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "l6208_target_config.h"
#include "motor.h"
   
/** @addtogroup BSP
  * @{
  */
   
/** @addtogroup L6208
  * @{
  */

/* Exported Constants --------------------------------------------------------*/

/** @addtogroup L6208_Exported_Constants
  * @{
  */
/// Current FW major version
#define L6208_FW_MAJOR_VERSION (uint8_t)(1)
/// Current FW minor version
#define L6208_FW_MINOR_VERSION (uint8_t)(4)
/// Current FW patch version
#define L6208_FW_PATCH_VERSION (uint8_t)(0)
/// Current FW version
#define L6208_FW_VERSION       (uint32_t)((L6208_FW_MAJOR_VERSION<<16)|\
                                          (L6208_FW_MINOR_VERSION<<8)|\
                                          (L6208_FW_PATCH_VERSION))

/// Max position
#define L6208_MAX_POSITION           (0x7FFFFFFF)

/// Min position
#define L6208_MIN_POSITION           (0x80000000)

/// Position range
#define L6208_POSITION_RANGE         ((uint32_t)(L6208_MAX_POSITION -\
                                                        L6208_MIN_POSITION))
/// micro step samples per period/4 
#define L6208_USTEPS_PER_QUARTER_PERIOD        (16)

/// minimum speed
#define L6208_MIN_SPEED                        (16)

/// minimum acceleration and deceleration rate
#define L6208_MIN_ACC_DEC_RATE                 (24)

/// Mask for HiZ bit in motorDecayMode_t enum
#define L6208_FAST_DECAY_MODE_MASK             (0x1)

/// L6208 error base number
#define L6208_ERROR_BASE                       (0x9000)
/**
  * @}
  */

/* Exported types ------------------------------------------------------------*/

/** @defgroup Error_Types Error Types
  * @{
  */
/// Errors
typedef enum {
  L6208_ERROR_SET_HOME         = L6208_ERROR_BASE,     /// Error while setting home position
  L6208_ERROR_SET_MAX_SPEED    = L6208_ERROR_BASE + 1, /// Error while setting max speed
  L6208_ERROR_SET_MIN_SPEED    = L6208_ERROR_BASE + 2, /// Error while setting min speed
  L6208_ERROR_SET_ACCELERATION = L6208_ERROR_BASE + 3, /// Error while setting acceleration
  L6208_ERROR_SET_DECELERATION = L6208_ERROR_BASE + 4, /// Error while setting decelaration
  L6208_ERROR_MCU_OSC_CONFIG   = L6208_ERROR_BASE + 5, /// Error while configuring mcu oscillator
  L6208_ERROR_MCU_CLOCK_CONFIG = L6208_ERROR_BASE + 6, /// Error while configuring mcu clock
  L6208_ERROR_POSITION         = L6208_ERROR_BASE + 7, /// Unexpected current position (wrong number of steps)
  L6208_ERROR_SPEED            = L6208_ERROR_BASE + 8, /// Unexpected current speed
  L6208_ERROR_INIT             = L6208_ERROR_BASE + 9, /// Unexpected number of devices
  L6208_ERROR_SET_DIRECTION    = L6208_ERROR_BASE + 10,/// Error while setting direction
  L6208_ERROR_SET_STEP_MODE    = L6208_ERROR_BASE + 11,/// Attempt to set an unsupported step mode
  L6208_ERROR_SET_PWM          = L6208_ERROR_BASE + 12,/// Error while setting a PWM parameter
}errorTypes_t;
/**
  * @}
  */

/** @defgroup Device_Parameters Device Parameters
  * @{
  */
/// Device Parameters Structure Type
typedef struct
{
  /// dwelling waiting time counter (tick)
  volatile uint32_t dwellCounter;
  /// motor position indicator (tick)
  uint32_t ticks;
  /// LSByte copy of the previous position (tick)
  uint8_t lsbOldTicks;
  /// LSByte copy of the previous position (tick) ( micro stepping )
  uint8_t lsbOldUSteppingTicks;
  /// LSByte copy of the current position (tick)
  uint8_t lsbTicks;
  /// P1 = acceleration phase steps number (motor position control mode)
  uint32_t positionTarget1;
  /// P2 = constant speed steps number (motor position control mode)
  uint32_t positionTarget2;
  /// P3 = deceleration phase steps number (motor position control mode)
  uint32_t positionTarget3;
  /// P = total move distance in steps (motor position control mode)
  uint32_t positionTarget;
  /// absolute motor position in microsteps (motor position control mode)
  volatile int32_t absolutePos;
  /// mark position in microsteps (motor position control mode)
  volatile int32_t markPos;
  /// motor position in microsteps (motor position control mode)
  volatile uint32_t step;
  /// dwelling time after position got (ms)
  volatile uint16_t moveDwellTime;
  /// number of micro stepping waveform samples to be rescaled according to selected torque value
  volatile uint8_t uStepsample2scale;
  /// number of micro stepping waveform samples to be updated into the waveform scanning table  
  volatile uint8_t uStepsample2update;
  /// microstepping waveform sample index  
  volatile uint8_t uStepSample;
  /// system status flags
  volatile uint32_t flags;
  /// current stepper state machine index
  volatile motorState_t motionState;
  /// current step mode
  volatile motorStepMode_t stepMode;
  /// micro stepping waveform scanning sample index increment
  uint8_t uStepInc;
  /// frequency of the VREFA and VREFB PWM
  uint32_t vrefPwmFreq;
  /// current selected torque value
  volatile uint8_t curTorqueScaler;
  /// constant speed phase torque value (%)
  volatile uint8_t runTorque;
  /// acceleration phase torque value (%)
  volatile uint8_t accelTorque;
  /// deceleration phase torque value (%)
  volatile uint8_t decelTorque;
  /// holding phase torque value (%)
  volatile uint8_t holdTorque;
  /// acceleration (steps/s^2)
  volatile uint16_t accelerationSps2;
  /// deceleration (steps/s^2)
  volatile uint16_t decelerationSps2;
  /// acceleration (steps/tick^2)
  volatile uint16_t accelerationSpt2;
  /// deceleration (steps/tick^2)
  volatile uint16_t decelerationSpt2;
  /// maximum speed (steps/s)
  volatile uint16_t maxSpeedSps;
  /// minimum speed (steps/s)
  volatile uint16_t minSpeedSps;
  /// current speed (steps/s)
  volatile uint16_t speedSps;
  /// maximum speed (steps/tick)
  volatile uint32_t maxSpeedSpt;
  /// minimum speed (steps/tick)
  volatile uint32_t minSpeedSpt;
  /// current speed (steps/tick) 
  volatile uint32_t speedSpt;
}deviceParams_t;
/**
  * @}
  */

/// Motor driver initialization structure definition  
typedef struct
{
  /// acceleration (steps/s^2)
  uint16_t accelerationSps2;
  /// acceleration phase torque value (%)
  uint8_t accelTorque;
  /// deceleration (steps/s^2)
  uint16_t decelerationSps2;
  /// deceleration phase torque value (%)
  uint8_t decelTorque;
  /// maximum speed (steps/s)
  uint16_t maxSpeedSps;
  /// constant speed phase torque value (%)
  uint8_t runTorque;
  /// holding phase torque value (%)
  uint8_t holdTorque;
  /// current step mode
  motorStepMode_t stepMode;
  /// current decay mode (SLOW_DECAY or FAST_DECAY)
  motorDecayMode_t decayMode;
  /// dwelling time after position got (ms)
  uint16_t moveDwellTime;
  /// automatic HiZ on stop
  bool autoHiZstop;
  /// frequency of the VREFA and VREFB PWM
  uint32_t vrefPwmFreq;
} l6208_Init_t;



/* Exported functions --------------------------------------------------------*/

/** @defgroup L6208_Exported_Functions L6208 Exported Functions
  * @{
  */
motorDrv_t* L6208_GetMotorHandle(void);                                      //Return handle of the motor driver handle
void L6208_Init(void* pInit);                                                //Start the L6208 library
uint16_t L6208_ReadId(void);                                                 //Read Id to get driver instance
void L6208_AttachErrorHandler(void (*callback)(uint16_t error));             //Attach a user callback to the error Handler
void L6208_AttachFlagInterrupt(void (*callback)(void));                      //Attach a user callback to the flag Interrupt
uint8_t L6208_CheckStatusHw(void);                                           //Check if L6208 has a fault by reading EN pin position
void L6208_Disable(uint8_t deviceId);                                        //Disable the power bridge
void L6208_ErrorHandler(uint16_t error);                                     //Error handler which calls the user callback
void L6208_Enable(uint8_t deviceId);                                         //Enable the power bridge
void L6208_FlagInterruptHandler(void);                                       //Handler of the flag interrupt which calls the user callback (if defined)
uint16_t L6208_GetAcceleration(uint8_t deviceId);                            //Return the acceleration in pps^2
uint16_t L6208_GetCurrentSpeed(uint8_t deviceId);                            //Return the current speed in pps
motorDecayMode_t L6208_GetDecayMode(uint8_t deviceId);                       //Get the motor decay mode
uint16_t L6208_GetDeceleration(uint8_t deviceId);                            //Return the deceleration in pps^2
motorDir_t L6208_GetDirection(uint8_t deviceId);                             //Get the motor current direction
uint32_t L6208_GetFwVersion(void);                                           //Return the FW version
int32_t L6208_GetMark(uint8_t deviceId);                                     //Get the mark position (32b signed)
uint16_t L6208_GetMaxSpeed(uint8_t deviceId);                                //Return the max speed in pps
uint16_t L6208_GetMinSpeed(uint8_t deviceId);                                //Return the min speed in pps
motorState_t L6208_GetMotionState(uint8_t deviceId);                         //Return the motion state
int32_t L6208_GetPosition(uint8_t deviceId);                                 //Get the current position (32b signed)
motorStepMode_t L6208_GetStepMode(uint8_t deviceId);                         //Get the motor step mode
motorStopMode_t L6208_GetStopMode(uint8_t deviceId);                         //Get the selected mode to stop the motor
uint8_t L6208_GetTorque(uint8_t deviceId, motorTorqueMode_t torqueMode);     //Get the torque value according to the torque mode
void L6208_GoHome(uint8_t deviceId);                                         //Go to the home position
void L6208_GoMark(uint8_t deviceId);                                         //Go to the Mark position
void L6208_GoTo(uint8_t deviceId, int32_t abs_pos);                          //Go to the specified position
void L6208_GoToDir(uint8_t deviceId, motorDir_t direction, int32_t abs_pos); //Go to the specified position using the specified direction
void L6208_HardHiZ(uint8_t deviceId);                                        //Stop the motor by using the device deceleration and disables the power bridges
void L6208_HardStop(uint8_t deviceId);                                       //Stop the motor and keeps holding torque
void L6208_Move(uint8_t deviceId, motorDir_t direction, uint32_t stepCount); //Move the motor by the specified number of steps in the specified direction
void L6208_ReleaseReset(uint8_t deviceId);                                   //Release the reset pin 
void L6208_Reset(uint8_t deviceId);                                          //Set the reset pin 
void L6208_ResetDevice(void);                                                //Reset L6208 device
void L6208_Run(uint8_t deviceId, motorDir_t direction);                      //Run the motor in the specified direction
bool L6208_SetAcceleration(uint8_t deviceId, uint16_t newAcc);               //Set the acceleration in pps^2
void L6208_SetDecayMode(uint8_t deviceId, motorDecayMode_t decayMode);       //Set the motor decay mode
bool L6208_SetDeceleration(uint8_t deviceId, uint16_t newDec);               //Set the deceleration in pps^2
void L6208_SetDirection(uint8_t deviceId, motorDir_t direction);             //Set the motor direction
void L6208_SetHome(uint8_t deviceId, int32_t homePos);                       //Set the home position
void L6208_SetMark(uint8_t deviceId, int32_t markPos);                       //Set  the mark position
bool L6208_SetMaxSpeed(uint8_t deviceId, uint16_t volatile newSpeed);        //Set the max speed value in pps
bool L6208_SetMinSpeed(uint8_t deviceId, uint16_t volatile newSpeed);        //Set the max speed value in pps
bool L6208_SetNbDevices(uint8_t nbDevices);                                  //Set the number of devices
bool L6208_SetStepMode(uint8_t deviceId, motorStepMode_t stepMode);          //Set the motor step mode
void L6208_SetStopMode(uint8_t deviceId, motorStopMode_t stopMode);          //Select the mode to stop the motor
void L6208_SetTorque(uint8_t deviceId, motorTorqueMode_t torqueMode, uint8_t torqueValue); //Set the torque value according to the torque mode
bool L6208_SoftStop(uint8_t deviceId);                                       //Progressively stop the motor by using the device deceleration and set deceleration torque
void L6208_TickHandler(uint8_t deviceId);                                    //Handle the device state machine at each tick timer pulse end
uint32_t L6208_VrefPwmGetFreq(uint8_t deviceId);                             //Get the frequency of VREFA and VREFB PWM
void L6208_VrefPwmSetFreq(uint8_t deviceId, uint32_t newFreq);               //Set the frequency of the VREFA and VREFB PWM
void L6208_WaitWhileActive(uint8_t deviceId);                                //Wait for the device state becomes Inactive




/**
  * @}
  */

/** @defgroup MotorControl_Board_Linked_Functions MotorControl Board Linked Functions
  * @{
  */
///Delay of the requested number of milliseconds
extern void L6208_Board_Delay(uint32_t delay);
///Enable Irq
extern void L6208_Board_EnableIrq(void);
///Disable Irq
extern void L6208_Board_DisableIrq(void);
///Initialise GPIOs used for L6208
extern void L6208_Board_GpioInit(void);
//Initialize the VREFA or VREFB PWM
extern bool L6208_Board_VrefPwmInit(uint8_t bridgeId, uint32_t pwmFreq);
///Set duty cycle of VREFA or VREFB PWM
extern bool L6208_Board_VrefPwmSetDutyCycle(uint8_t bridgeId,\
       uint16_t value,\
       bool valueIsPwmDutyCycle);
///Start the timer for the VREFA or VREFB PWM
extern bool L6208_Board_VrefPwmStart(uint8_t bridgeId,\
       uint32_t pwmFreq);
///Stop the timer for the VREFA or VREFB PWM
extern bool L6208_Board_VrefPwmStop(uint8_t bridgeId);
///Get the period of VREFA and VREFB PWM
extern uint32_t L6208_Board_VrefPwmGetPeriod(void);
///Check that the new VREFA and VREFB PWM frequency is nor too low nor too high
bool L6208_Board_VrefPwmFreqCheck(uint32_t newFreq);          
///Initialize the tick
extern void L6208_Board_TickInit(void);
///Start the timer for the tick by using the set tick frequency
extern void L6208_Board_TickStart(void);
///Stop the timer for the tick
extern void L6208_Board_TickStop(void);
///Get the tick frequency in Hz
extern uint32_t L6208_Board_TickGetFreq(void);
///Release the reset pin 
extern void L6208_Board_ReleaseReset(void);
///Set the reset pin
extern void L6208_Board_Reset(void);
///Set the control pin
extern void L6208_Board_CONTROL_PIN_Set(void);
///Reset the control pin
extern void L6208_Board_CONTROL_PIN_Reset(void);
///Set the clock pin
extern void L6208_Board_CLOCK_PIN_Set(void);
///Reset the clock pin
extern void L6208_Board_CLOCK_PIN_Reset(void);
///Set the half full pin
extern void L6208_Board_HALF_FULL_PIN_Set(void);
///Reset the half full pin
extern void L6208_Board_HALF_FULL_PIN_Reset(void);
///Set the dir pin
extern void L6208_Board_DIR_PIN_Set(void);
///Reset the dir pin
extern void L6208_Board_DIR_PIN_Reset(void);
///Returns the EN pin state
extern uint32_t L6208_Board_FLAG_PIN_GetState(void);
///Enable the power bridges (leave the output bridges HiZ)
extern void L6208_Board_Enable(void);
///Disable the power bridges (leave the output bridges HiZ)
extern void L6208_Board_Disable(void);
/**
  * @}
  */

  /**
  * @}
  */

/**
  * @}
  */

#ifdef __cplusplus
  }
#endif

#endif /* __L6208_H */

/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/
