Personal fork of the library for direct control instead of library control

Dependencies:   X_NUCLEO_COMMON

Dependents:   Thesis_Rotating_Platform

Fork of X_NUCLEO_IHM01A1 by Arkadi Rafalovich

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers l6474_class.cpp Source File

l6474_class.cpp

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    l6474_class.cpp
00004   * @author  IPC Rennes
00005   * @version V1.5.0
00006   * @date    November 12, 2014
00007   * @brief   L6474 driver (fully integrated microstepping motor driver)
00008   * @note    (C) COPYRIGHT 2014 STMicroelectronics
00009   ******************************************************************************
00010   * @attention
00011   *
00012   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
00013   *
00014   * Redistribution and use in source and binary forms, with or without modification,
00015   * are permitted provided that the following conditions are met:
00016   *   1. Redistributions of source code must retain the above copyright notice,
00017   *      this list of conditions and the following disclaimer.
00018   *   2. Redistributions in binary form must reproduce the above copyright notice,
00019   *      this list of conditions and the following disclaimer in the documentation
00020   *      and/or other materials provided with the distribution.
00021   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00022   *      may be used to endorse or promote products derived from this software
00023   *      without specific prior written permission.
00024   *
00025   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00029   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00030   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00031   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00033   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035   *
00036   ******************************************************************************
00037   */
00038 
00039 
00040 /* Generated with STM32CubeTOO -----------------------------------------------*/
00041 
00042 
00043 /* Revision ------------------------------------------------------------------*/
00044 /*
00045     Repository:       http://svn.x-nucleodev.codex.cro.st.com/svnroot/X-NucleoDev
00046     Branch/Trunk/Tag: trunk
00047     Based on:         X-CUBE-SPN1/trunk/Drivers/BSP/Components/l6474/l6474.c
00048     Revision:         0
00049 */
00050 
00051 
00052 /* Includes ------------------------------------------------------------------*/
00053 
00054 #include "l6474_class.h"
00055 
00056     
00057 /* Definitions ---------------------------------------------------------------*/
00058 
00059 /* Error while initialising the SPI. */
00060 #define L6474_ERROR_0        (0x8000)   
00061 
00062 /* Error of bad SPI transaction. */
00063 #define L6474_ERROR_1        (0x8001)
00064     
00065 /* Maximum number of steps. */
00066 #define MAX_STEPS            (0x7FFFFFFF)
00067 
00068 /* Maximum frequency of the PWMs in Hz. */
00069 #define L6474_MAX_PWM_FREQ   (10000)
00070 
00071 /* Minimum frequency of the PWMs in Hz. */
00072 #define L6474_MIN_PWM_FREQ   (2)
00073 
00074 
00075 /* Variables  ----------------------------------------------------------------*/
00076 
00077 /* Number of devices. */
00078 uint8_t L6474::number_of_devices = 0;
00079 
00080 /* ISR flags used to restart an interrupted SPI transfer when an error is reported. */
00081 bool L6474::spi_preemtion_by_isr = FALSE;
00082 bool L6474::isr_flag = FALSE;
00083 
00084 /* SPI Transmission for Daisy-Chain Configuration. */
00085 uint8_t L6474::spi_tx_bursts[L6474_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_DEVICES];
00086 uint8_t L6474::spi_rx_bursts[L6474_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_DEVICES];
00087 
00088 
00089 /* Methods -------------------------------------------------------------------*/
00090 
00091 /**********************************************************
00092  * @brief  Attaches a user callback to the error Handler.
00093  * The call back will be then called each time the library 
00094  * detects an error
00095  * @param[in] callback Name of the callback to attach 
00096  * to the error Hanlder
00097  * @retval None
00098  **********************************************************/
00099 void L6474::L6474_AttachErrorHandler(void (*callback)(uint16_t error))
00100 {
00101   error_handler_callback = (void (*)(uint16_t error)) callback;
00102 }
00103 
00104 /**********************************************************
00105  * @brief Starts the L6474 library
00106  * @param  init Initialization structure.
00107  * @retval COMPONENT_OK in case of success.
00108  **********************************************************/
00109 Status_t L6474::L6474_Init(void *init)
00110 {
00111   /* Initialise the PWMs used for the Step clocks ----------------------------*/
00112   
00113   ///////////////////////////////////////////////////////// !!!!!!!!!!!!!!!!!!!!!!!!!!!
00114   // Disable Library control
00115   //L6474_PwmInit();
00116   // Disable Library control
00117   ////////////////////////////////////////////////////////// !!!!!!!!!!!!!!!!!!!!!!!!!!
00118     
00119   /* Initialise the L6474s ------------------------------------------------*/
00120   
00121   /* Standby-reset deactivation */
00122   L6474_ReleaseReset();
00123   
00124   /* Let a delay after reset */
00125   L6474_Delay(0.25); // original 1sec delay
00126 
00127   /* Set device parameters to the predefined values from "l6474_target_config.h". */
00128   L6474_SetDeviceParamsToPredefinedValues();
00129   
00130   if (init == NULL)
00131     /* Set device registers to the predefined values from "l6474_target_config.h". */
00132     L6474_SetRegisterToPredefinedValues();
00133   else
00134     /* Set device registers to the passed initialization values. */
00135     L6474_SetRegisterToInitializationValues((L6474_Init_t *) init);
00136   
00137   /* Disable L6474 powerstage */
00138   L6474_CmdDisable();
00139 
00140   /* Get Status to clear flags after start up */
00141   L6474_CmdGetStatus();
00142   
00143   return COMPONENT_OK;
00144 }
00145 
00146 /**********************************************************
00147  * @brief Read id
00148  * @param id pointer to the identifier to be read.
00149  * @retval COMPONENT_OK in case of success.
00150  **********************************************************/
00151 Status_t L6474::L6474_ReadID(uint8_t *id)
00152 {
00153   *id = device_instance;
00154 
00155   return COMPONENT_OK;
00156 }
00157 
00158 /**********************************************************
00159  * @brief Returns the acceleration of the specified device
00160  * @retval Acceleration in pps^2
00161  **********************************************************/
00162 uint16_t L6474::L6474_GetAcceleration(void)
00163 {
00164   return (device_prm.acceleration);
00165 }            
00166 
00167 /**********************************************************
00168  * @brief Returns the current speed of the specified device
00169  * @retval Speed in pps
00170  **********************************************************/
00171 uint16_t L6474::L6474_GetCurrentSpeed(void)
00172 {
00173   return device_prm.speed;
00174 }
00175 
00176 /**********************************************************
00177  * @brief Returns the deceleration of the specified device
00178  * @retval Deceleration in pps^2
00179  **********************************************************/
00180 uint16_t L6474::L6474_GetDeceleration(void)
00181 {                                                  
00182   return (device_prm.deceleration);
00183 }          
00184 
00185 /**********************************************************
00186  * @brief Returns the device state
00187  * @retval State (ACCELERATING, DECELERATING, STEADY or INACTIVE)
00188  **********************************************************/
00189 motorState_t L6474::L6474_GetDeviceState(void)
00190 {
00191   return device_prm.motionState;
00192 }
00193 
00194 /**********************************************************
00195  * @brief Returns the FW version of the library
00196  * @param None
00197  * @retval L6474_FW_VERSION
00198  **********************************************************/
00199 uint8_t L6474::L6474_GetFwVersion(void)
00200 {
00201   return (L6474_FW_VERSION);
00202 }
00203 
00204 /**********************************************************
00205  * @brief  Returns the mark position  of the specified device
00206  * @retval Mark register value converted in a 32b signed integer 
00207  **********************************************************/
00208 int32_t L6474::L6474_GetMark(void)
00209 {
00210   return L6474_ConvertPosition(L6474_CmdGetParam(L6474_MARK));
00211 }
00212 
00213 /**********************************************************
00214  * @brief  Returns the max speed of the specified device
00215  * @retval maxSpeed in pps
00216  **********************************************************/
00217 uint16_t L6474::L6474_GetMaxSpeed(void)
00218 {                                                  
00219   return (device_prm.maxSpeed);
00220 }
00221 
00222 /**********************************************************
00223  * @brief  Returns the min speed of the specified device
00224  * @retval minSpeed in pps
00225  **********************************************************/
00226 uint16_t L6474::L6474_GetMinSpeed(void)
00227 {                                                  
00228   return (device_prm.minSpeed);
00229 }                                                     
00230 
00231 /**********************************************************
00232  * @brief  Returns the ABS_POSITION of the specified device
00233  * @retval ABS_POSITION register value converted in a 32b signed integer
00234  **********************************************************/
00235 int32_t L6474::L6474_GetPosition(void)
00236 {
00237   return L6474_ConvertPosition(L6474_CmdGetParam(L6474_ABS_POS));
00238 }
00239 
00240 /**********************************************************
00241  * @brief  Requests the motor to move to the home position (ABS_POSITION = 0)
00242  * @retval None
00243  **********************************************************/
00244 void L6474::L6474_GoHome(void)
00245 {
00246   L6474_GoTo(0);
00247 } 
00248   
00249 /**********************************************************
00250  * @brief  Requests the motor to move to the mark position 
00251  * @retval None
00252  **********************************************************/
00253 void L6474::L6474_GoMark(void)
00254 {
00255     uint32_t mark;
00256 
00257     mark = L6474_ConvertPosition(L6474_CmdGetParam(L6474_MARK));
00258     L6474_GoTo(mark);  
00259 }
00260 
00261 /**********************************************************
00262  * @brief  Requests the motor to move to the specified position 
00263  * @param[in] targetPosition absolute position in steps
00264  * @retval None
00265  **********************************************************/
00266 void L6474::L6474_GoTo(int32_t targetPosition)
00267 {
00268   motorDir_t direction;
00269   int32_t steps;
00270   
00271   /* Eventually deactivate motor */
00272   if (device_prm.motionState != INACTIVE) 
00273   {
00274     L6474_HardStop();
00275   }
00276 
00277   /* Get current position */
00278   device_prm.currentPosition = L6474_ConvertPosition(L6474_CmdGetParam(L6474_ABS_POS));
00279   
00280   /* Compute the number of steps to perform */
00281   steps = targetPosition - device_prm.currentPosition;
00282   
00283   if (steps >= 0) 
00284   {
00285     device_prm.stepsToTake = steps;
00286     direction = FORWARD;
00287   } 
00288   else 
00289   {
00290     device_prm.stepsToTake = -steps;
00291     direction = BACKWARD;
00292   }
00293   
00294   if (steps != 0) 
00295   {
00296     device_prm.commandExecuted = MOVE_CMD;
00297         
00298     /* Direction setup */
00299     L6474_SetDirection(direction);
00300 
00301     L6474_ComputeSpeedProfile(device_prm.stepsToTake);
00302     
00303     /* Motor activation */
00304     L6474_StartMovement();
00305   }  
00306 }
00307 
00308 /**********************************************************
00309  * @brief  Immediatly stops the motor and disable the power bridge
00310  * @retval None
00311  **********************************************************/
00312 void L6474::L6474_HardStop(void) 
00313 {
00314   /* Disable corresponding PWM */
00315   L6474_PwmStop();
00316 
00317   /* Set inactive state */
00318   device_prm.motionState = INACTIVE;
00319   device_prm.commandExecuted = NO_CMD;
00320   device_prm.stepsToTake = MAX_STEPS;  
00321 }
00322 
00323 /**********************************************************
00324  * @brief  Moves the motor of the specified number of steps
00325  * @param[in] direction FORWARD or BACKWARD
00326  * @param[in] stepCount Number of steps to perform
00327  * @retval None
00328  **********************************************************/
00329 void L6474::L6474_Move(motorDir_t direction, uint32_t stepCount)
00330 {
00331   /* Eventually deactivate motor */
00332   if (device_prm.motionState != INACTIVE) 
00333   {
00334     L6474_HardStop();
00335   }
00336   
00337   if (stepCount != 0) 
00338   {
00339     device_prm.stepsToTake = stepCount;
00340     
00341     device_prm.commandExecuted = MOVE_CMD;
00342     
00343     device_prm.currentPosition = L6474_ConvertPosition(L6474_CmdGetParam(L6474_ABS_POS));
00344     
00345     /* Direction setup */
00346     L6474_SetDirection(direction);
00347 
00348     L6474_ComputeSpeedProfile(stepCount);
00349     
00350     /* Motor activation */
00351     L6474_StartMovement();
00352   }  
00353 }
00354 
00355 /**********************************************************
00356  * @brief  Runs the motor. It will accelerate from the min 
00357  * speed up to the max speed by using the device acceleration.
00358  * @param[in] direction FORWARD or BACKWARD
00359  * @retval None
00360  **********************************************************/
00361 void L6474::L6474_Run(motorDir_t direction)
00362 {
00363   /* Eventually deactivate motor */
00364   if (device_prm.motionState != INACTIVE) 
00365   {
00366     L6474_HardStop();
00367   }
00368   
00369   /* Direction setup */
00370   L6474_SetDirection(direction);
00371 
00372   device_prm.commandExecuted = RUN_CMD;
00373 
00374   /* Motor activation */
00375   L6474_StartMovement(); 
00376 }
00377 
00378 /**********************************************************
00379  * @brief  Changes the acceleration of the specified device
00380  * @param[in] newAcc New acceleration to apply in pps^2
00381  * @retval true if the command is successfully executed, else false
00382  * @note The command is not performed is the device is executing 
00383  * a MOVE or GOTO command (but it can be used during a RUN command)
00384  **********************************************************/
00385 bool L6474::L6474_SetAcceleration(uint16_t newAcc)
00386 {                                                  
00387   bool cmdExecuted = FALSE;
00388   if ((newAcc != 0)&&
00389       ((device_prm.motionState == INACTIVE)||
00390        (device_prm.commandExecuted == RUN_CMD)))
00391   {
00392     device_prm.acceleration = newAcc;
00393     cmdExecuted = TRUE;
00394   }    
00395   return cmdExecuted;
00396 }            
00397 
00398 /**********************************************************
00399  * @brief  Changes the deceleration of the specified device
00400  * @param[in] newDec New deceleration to apply in pps^2
00401  * @retval true if the command is successfully executed, else false
00402  * @note The command is not performed is the device is executing 
00403  * a MOVE or GOTO command (but it can be used during a RUN command)
00404  **********************************************************/
00405 bool L6474::L6474_SetDeceleration(uint16_t newDec)
00406 {                                                  
00407   bool cmdExecuted = FALSE;
00408   if ((newDec != 0)&& 
00409       ((device_prm.motionState == INACTIVE)||
00410        (device_prm.commandExecuted == RUN_CMD)))
00411   {
00412     device_prm.deceleration = newDec;
00413     cmdExecuted = TRUE;
00414   }      
00415   return cmdExecuted;
00416 }        
00417 
00418 /**********************************************************
00419  * @brief  Set current position to be the Home position (ABS pos set to 0)
00420  * @retval None
00421  **********************************************************/
00422 void L6474::L6474_SetHome(void)
00423 {
00424   L6474_CmdSetParam(L6474_ABS_POS, 0);
00425 }
00426  
00427 /**********************************************************
00428  * @brief  Sets current position to be the Mark position 
00429  * @retval None
00430  **********************************************************/
00431 void L6474::L6474_SetMark(void)
00432 {
00433   uint32_t mark = L6474_CmdGetParam(L6474_ABS_POS);
00434   L6474_CmdSetParam(L6474_MARK, mark);
00435 }
00436 
00437 /**********************************************************
00438  * @brief  Changes the max speed of the specified device
00439  * @param[in] newMaxSpeed New max speed  to apply in pps
00440  * @retval true if the command is successfully executed, else false
00441  * @note The command is not performed is the device is executing 
00442  * a MOVE or GOTO command (but it can be used during a RUN command).
00443  **********************************************************/
00444 bool L6474::L6474_SetMaxSpeed(uint16_t newMaxSpeed)
00445 {                                                  
00446   bool cmdExecuted = FALSE;
00447   if ((newMaxSpeed >= L6474_MIN_PWM_FREQ)&&
00448       (newMaxSpeed <= L6474_MAX_PWM_FREQ) &&
00449       (device_prm.minSpeed <= newMaxSpeed) &&
00450       ((device_prm.motionState == INACTIVE)||
00451        (device_prm.commandExecuted == RUN_CMD)))
00452   {
00453     device_prm.maxSpeed = newMaxSpeed;
00454     cmdExecuted = TRUE;
00455   }
00456   return cmdExecuted;
00457 }                                                     
00458 
00459 /**********************************************************
00460  * @brief  Changes the min speed of the specified device
00461  * @param[in] newMinSpeed New min speed  to apply in pps
00462  * @retval true if the command is successfully executed, else false
00463  * @note The command is not performed is the device is executing 
00464  * a MOVE or GOTO command (but it can be used during a RUN command).
00465  **********************************************************/
00466 bool L6474::L6474_SetMinSpeed(uint16_t newMinSpeed)
00467 {                                                  
00468   bool cmdExecuted = FALSE;
00469   if ((newMinSpeed >= L6474_MIN_PWM_FREQ)&&
00470       (newMinSpeed <= L6474_MAX_PWM_FREQ) &&
00471       (newMinSpeed <= device_prm.maxSpeed) && 
00472       ((device_prm.motionState == INACTIVE)||
00473        (device_prm.commandExecuted == RUN_CMD)))
00474   {
00475     device_prm.minSpeed = newMinSpeed;
00476     cmdExecuted = TRUE;
00477   }  
00478   return cmdExecuted;
00479 }                 
00480 
00481 /**********************************************************
00482  * @brief  Stops the motor by using the device deceleration
00483  * @retval true if the command is successfully executed, else false
00484  * @note The command is not performed is the device is in INACTIVE state.
00485  **********************************************************/
00486 bool L6474::L6474_SoftStop(void)
00487 {   
00488   bool cmdExecuted = FALSE;
00489   if (device_prm.motionState != INACTIVE)
00490   {
00491     device_prm.commandExecuted = SOFT_STOP_CMD;
00492     cmdExecuted = TRUE;
00493   }
00494   return (cmdExecuted);
00495 }
00496 
00497 /**********************************************************
00498  * @brief  Locks until the device state becomes Inactive
00499  * @retval None
00500  **********************************************************/
00501 void L6474::L6474_WaitWhileActive(void)
00502 {
00503   /* Wait while motor is running */
00504   while (L6474_GetDeviceState() != INACTIVE);
00505 }
00506 
00507 /**********************************************************
00508  * @brief  Issue the Disable command to the L6474 of the specified device
00509  * @retval None
00510  **********************************************************/
00511 void L6474::L6474_CmdDisable(void)
00512 {
00513   L6474_SendCommand(L6474_DISABLE);
00514 }
00515 
00516 /**********************************************************
00517  * @brief  Issues the Enable command to the L6474 of the specified device
00518  * @retval None
00519  **********************************************************/
00520 void L6474::L6474_CmdEnable(void)
00521 {
00522   L6474_SendCommand(L6474_ENABLE);
00523 }
00524 
00525 /**********************************************************
00526  * @brief  Issues the GetParam command to the L6474 of the specified device
00527  * @param[in] parameter Register adress (L6474_ABS_POS, L6474_MARK,...)
00528  * @retval Register value
00529  **********************************************************/
00530 uint32_t L6474::L6474_CmdGetParam(L6474_Registers_t parameter)
00531 {
00532   uint32_t i;
00533   uint32_t spiRxData;
00534   uint8_t maxArgumentNbBytes = 0;
00535   uint8_t spiIndex = number_of_devices - device_instance - 1;
00536   bool itDisable = FALSE;  
00537   
00538   do
00539   {
00540     spi_preemtion_by_isr = FALSE;
00541     if (itDisable)
00542     {
00543       /* re-enable L6474_EnableIrq if disable in previous iteration */
00544       L6474_EnableIrq();
00545       itDisable = FALSE;
00546     }
00547   
00548     for (i = 0; i < number_of_devices; i++)
00549     {
00550       spi_tx_bursts[0][i] = L6474_NOP;
00551       spi_tx_bursts[1][i] = L6474_NOP;
00552       spi_tx_bursts[2][i] = L6474_NOP;
00553       spi_tx_bursts[3][i] = L6474_NOP;
00554       spi_rx_bursts[1][i] = 0;
00555       spi_rx_bursts[2][i] = 0;
00556       spi_rx_bursts[3][i] = 0;    
00557     }
00558 
00559     switch (parameter)
00560     {
00561       case L6474_ABS_POS: ;
00562       case L6474_MARK:
00563         spi_tx_bursts[0][spiIndex] = ((uint8_t)L6474_GET_PARAM )| (parameter);
00564         maxArgumentNbBytes = 3;
00565         break;
00566       case L6474_EL_POS: ;
00567       case L6474_CONFIG: ;
00568       case L6474_STATUS:
00569         spi_tx_bursts[1][spiIndex] = ((uint8_t)L6474_GET_PARAM )| (parameter);
00570         maxArgumentNbBytes = 2;
00571         break;
00572       default:
00573         spi_tx_bursts[2][spiIndex] = ((uint8_t)L6474_GET_PARAM )| (parameter);
00574         maxArgumentNbBytes = 1;
00575     }
00576     
00577     /* Disable interruption before checking */
00578     /* pre-emption by ISR and SPI transfers*/
00579     L6474_DisableIrq();
00580     itDisable = TRUE;
00581   } while (spi_preemtion_by_isr); // check pre-emption by ISR
00582     
00583   for (i = L6474_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes;
00584        i < L6474_CMD_ARG_MAX_NB_BYTES;
00585        i++)
00586   {
00587      L6474_WriteBytes(&spi_tx_bursts[i][0], &spi_rx_bursts[i][0]);
00588   }
00589   
00590   spiRxData = ((uint32_t)spi_rx_bursts[1][spiIndex] << 16) |
00591               (spi_rx_bursts[2][spiIndex] << 8) |
00592               (spi_rx_bursts[3][spiIndex]);
00593   
00594   /* re-enable L6474_EnableIrq after SPI transfers*/
00595   L6474_EnableIrq();
00596     
00597   return (spiRxData);
00598 }
00599 
00600 /**********************************************************
00601  * @brief  Issues the GetStatus command to the L6474 of the specified device
00602  * @retval Status Register value
00603  * @note Once the GetStatus command is performed, the flags of the status register
00604  * are reset. This is not the case when the status register is read with the
00605  * GetParam command (via the functions L6474ReadStatusRegister or L6474_CmdGetParam).
00606  **********************************************************/
00607 uint16_t L6474::L6474_CmdGetStatus(void)
00608 {
00609   uint32_t i;
00610   uint16_t status;
00611   uint8_t spiIndex = number_of_devices - device_instance - 1;
00612   bool itDisable = FALSE;  
00613   
00614   do
00615   {
00616     spi_preemtion_by_isr = FALSE;
00617     if (itDisable)
00618     {
00619       /* re-enable L6474_EnableIrq if disable in previous iteration */
00620       L6474_EnableIrq();
00621       itDisable = FALSE;
00622     }
00623 
00624     for (i = 0; i < number_of_devices; i++)
00625     {
00626        spi_tx_bursts[0][i] = L6474_NOP;
00627        spi_tx_bursts[1][i] = L6474_NOP;
00628        spi_tx_bursts[2][i] = L6474_NOP;
00629        spi_rx_bursts[1][i] = 0;
00630        spi_rx_bursts[2][i] = 0;
00631     }
00632     spi_tx_bursts[0][spiIndex] = L6474_GET_STATUS;
00633 
00634     /* Disable interruption before checking */
00635     /* pre-emption by ISR and SPI transfers*/
00636     L6474_DisableIrq();
00637     itDisable = TRUE;
00638   } while (spi_preemtion_by_isr); // check pre-emption by ISR
00639 
00640   for (i = 0; i < L6474_CMD_ARG_NB_BYTES_GET_STATUS + L6474_RSP_NB_BYTES_GET_STATUS; i++)
00641   {
00642      L6474_WriteBytes(&spi_tx_bursts[i][0], &spi_rx_bursts[i][0]);
00643   }
00644   status = (spi_rx_bursts[1][spiIndex] << 8) | (spi_rx_bursts[2][spiIndex]);
00645   
00646   /* re-enable L6474_EnableIrq after SPI transfers*/
00647   L6474_EnableIrq();
00648   
00649   return (status);
00650 }
00651 
00652 /**********************************************************
00653  * @brief  Issues the Nop command to the L6474 of the specified device
00654  * @retval None
00655  **********************************************************/
00656 void L6474::L6474_CmdNop(void)
00657 {
00658   L6474_SendCommand(L6474_NOP);
00659 }
00660 
00661 /**********************************************************
00662  * @brief  Issues the SetParam command to the L6474 of the specified device
00663  * @param[in] parameter Register adress (L6474_ABS_POS, L6474_MARK,...)
00664  * @param[in] value Value to set in the register
00665  * @retval None
00666  **********************************************************/
00667 void L6474::L6474_CmdSetParam(L6474_Registers_t parameter, uint32_t value)
00668 {
00669   uint32_t i;
00670   uint8_t maxArgumentNbBytes = 0;
00671   uint8_t spiIndex = number_of_devices - device_instance - 1;
00672   bool itDisable = FALSE;  
00673   do
00674   {
00675     spi_preemtion_by_isr = FALSE;
00676     if (itDisable)
00677     {
00678       /* re-enable L6474_EnableIrq if disable in previous iteration */
00679       L6474_EnableIrq();
00680       itDisable = FALSE;
00681     }
00682 
00683     for (i = 0; i < number_of_devices; i++)
00684     {
00685       spi_tx_bursts[0][i] = L6474_NOP;
00686       spi_tx_bursts[1][i] = L6474_NOP;
00687       spi_tx_bursts[2][i] = L6474_NOP;
00688       spi_tx_bursts[3][i] = L6474_NOP;
00689     }
00690 
00691     switch (parameter)
00692     {
00693       case L6474_ABS_POS: ;
00694       case L6474_MARK:
00695           spi_tx_bursts[0][spiIndex] = parameter;
00696           spi_tx_bursts[1][spiIndex] = (uint8_t)(value >> 16);
00697           spi_tx_bursts[2][spiIndex] = (uint8_t)(value >> 8);
00698           maxArgumentNbBytes = 3;
00699           break;
00700       case L6474_EL_POS: ;
00701       case L6474_CONFIG:
00702           spi_tx_bursts[1][spiIndex] = parameter;
00703           spi_tx_bursts[2][spiIndex] = (uint8_t)(value >> 8);
00704           maxArgumentNbBytes = 2;
00705           break;
00706       default:
00707           spi_tx_bursts[2][spiIndex] = parameter;
00708           maxArgumentNbBytes = 1;
00709           break;
00710     }
00711     spi_tx_bursts[3][spiIndex] = (uint8_t)(value);
00712     
00713     /* Disable interruption before checking */
00714     /* pre-emption by ISR and SPI transfers*/
00715     L6474_DisableIrq();
00716     itDisable = TRUE;
00717   } while (spi_preemtion_by_isr); // check pre-emption by ISR
00718  
00719   /* SPI transfer */
00720   for (i = L6474_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes;
00721        i < L6474_CMD_ARG_MAX_NB_BYTES;
00722        i++)
00723   {
00724      L6474_WriteBytes(&spi_tx_bursts[i][0],&spi_rx_bursts[i][0]);
00725   }
00726   /* re-enable L6474_EnableIrq after SPI transfers*/
00727   L6474_EnableIrq();
00728 }
00729 
00730 /**********************************************************
00731  * @brief  Reads the Status Register value
00732  * @retval Status register valued
00733  * @note The status register flags are not cleared 
00734  * at the difference with L6474CmdGetStatus()
00735  **********************************************************/
00736 uint16_t L6474::L6474_ReadStatusRegister(void)
00737 {
00738   return (L6474_CmdGetParam(L6474_STATUS));
00739 }
00740 
00741 /**********************************************************
00742  * @brief  Set the stepping mode 
00743  * @param[in] stepMod from full step to 1/16 microstep as specified in enum motorStepMode_t
00744  * @retval None
00745  **********************************************************/
00746 void L6474::L6474_SelectStepMode(motorStepMode_t stepMod)
00747 {
00748   uint8_t stepModeRegister;
00749   L6474_STEP_SEL_t l6474StepMod;
00750   
00751   switch (stepMod)
00752   {
00753     case STEP_MODE_FULL:
00754       l6474StepMod = L6474_STEP_SEL_1;
00755       break;
00756     case STEP_MODE_HALF:
00757       l6474StepMod = L6474_STEP_SEL_1_2;
00758       break;    
00759     case STEP_MODE_1_4:
00760       l6474StepMod = L6474_STEP_SEL_1_4;
00761       break;        
00762     case STEP_MODE_1_8:
00763       l6474StepMod = L6474_STEP_SEL_1_8;
00764       break;       
00765     case STEP_MODE_1_16:
00766     default:
00767       l6474StepMod = L6474_STEP_SEL_1_16;
00768       break;       
00769   }
00770 
00771   /* Eventually deactivate motor */
00772   if (device_prm.motionState != INACTIVE) 
00773   {
00774     L6474_HardStop();
00775   }
00776   
00777   /* Read Step mode register and clear STEP_SEL field */
00778   stepModeRegister = (uint8_t)(0xF8 & L6474_CmdGetParam(L6474_STEP_MODE)) ;
00779   
00780   /* Apply new step mode */
00781   L6474_CmdSetParam(L6474_STEP_MODE, stepModeRegister | (uint8_t)l6474StepMod);
00782 
00783   /* Reset abs pos register */
00784   L6474_SetHome();
00785 }
00786 
00787 /**********************************************************
00788  * @brief  Get the direction
00789  * @param  None
00790  * @retval direction FORWARD or BACKWARD
00791  **********************************************************/
00792 motorDir_t L6474::L6474_GetDirection(void)
00793 {
00794   return device_prm.direction;
00795 }
00796 
00797 /**********************************************************
00798  * @brief  Specifies the direction 
00799  * @param[in] dir FORWARD or BACKWARD
00800  * @note The direction change is only applied if the device 
00801  * is in INACTIVE state
00802  * @retval None
00803  **********************************************************/
00804 void L6474::L6474_SetDirection(motorDir_t direction)
00805 {
00806   if (device_prm.motionState == INACTIVE)
00807   {
00808     device_prm.direction = direction;
00809     L6474_SetDirectionGpio(direction);
00810   }
00811 }
00812 
00813 /**********************************************************
00814  * @brief  Updates the current speed of the device
00815  * @param[in] newSpeed in pps
00816  * @retval None
00817  **********************************************************/
00818 void L6474::L6474_ApplySpeed(uint16_t newSpeed)
00819 {
00820   if (newSpeed < L6474_MIN_PWM_FREQ)
00821   {
00822     newSpeed = L6474_MIN_PWM_FREQ;  
00823   }
00824   if (newSpeed > L6474_MAX_PWM_FREQ)
00825   {
00826     newSpeed = L6474_MAX_PWM_FREQ;
00827   }
00828   
00829   device_prm.speed = newSpeed;
00830 
00831   L6474_PwmSetFreq(newSpeed);
00832 }
00833 
00834 /**********************************************************
00835  * @brief  Computes the speed profile according to the number of steps to move
00836  * @param[in] nbSteps number of steps to perform
00837  * @retval None
00838  * @note Using the acceleration and deceleration of the device,
00839  * this function determines the duration in steps of the acceleration,
00840  * steady and deceleration phases.
00841  * If the total number of steps to perform is big enough, a trapezoidal move
00842  * is performed (i.e. there is a steady phase where the motor runs at the maximum
00843  * speed.
00844  * Else, a triangular move is performed (no steady phase: the maximum speed is never
00845  * reached.
00846  **********************************************************/
00847 void L6474::L6474_ComputeSpeedProfile(uint32_t nbSteps)
00848 {
00849   uint32_t reqAccSteps; 
00850   uint32_t reqDecSteps;
00851    
00852   /* compute the number of steps to get the targeted speed */
00853   uint16_t minSpeed = device_prm.minSpeed;
00854   reqAccSteps = (device_prm.maxSpeed - minSpeed);
00855   reqAccSteps *= (device_prm.maxSpeed + minSpeed);
00856   reqDecSteps = reqAccSteps;
00857   reqAccSteps /= (uint32_t)device_prm.acceleration;
00858   reqAccSteps /= 2;
00859 
00860   /* compute the number of steps to stop */
00861   reqDecSteps /= (uint32_t)device_prm.deceleration;
00862   reqDecSteps /= 2;
00863 
00864   if(( reqAccSteps + reqDecSteps ) > nbSteps)
00865   { 
00866     /* Triangular move  */
00867     /* reqDecSteps = (Pos * Dec) /(Dec+Acc) */
00868     uint32_t dec = device_prm.deceleration;
00869     uint32_t acc = device_prm.acceleration;
00870     
00871     reqDecSteps =  ((uint32_t) dec * nbSteps) / (acc + dec);
00872     if (reqDecSteps > 1)
00873     {
00874       reqAccSteps = reqDecSteps - 1;
00875       if(reqAccSteps == 0)
00876       {
00877         reqAccSteps = 1;
00878       }      
00879     }
00880     else
00881     {
00882       reqAccSteps = 0;
00883     }
00884     device_prm.endAccPos = reqAccSteps;
00885     device_prm.startDecPos = reqDecSteps;
00886   }
00887   else
00888   {  
00889     /* Trapezoidal move */
00890     /* accelerating phase to endAccPos */
00891     /* steady phase from  endAccPos to startDecPos */
00892     /* decelerating from startDecPos to stepsToTake*/
00893     device_prm.endAccPos = reqAccSteps;
00894     device_prm.startDecPos = nbSteps - reqDecSteps - 1;
00895   }
00896 }
00897 
00898 /**********************************************************
00899  * @brief  Converts the ABS_POSITION register value to a 32b signed integer
00900  * @param[in] abs_position_reg value of the ABS_POSITION register
00901  * @retval operation_result 32b signed integer corresponding to the absolute position 
00902  **********************************************************/
00903 int32_t L6474::L6474_ConvertPosition(uint32_t abs_position_reg)
00904 {
00905   int32_t operation_result;
00906 
00907   if (abs_position_reg & L6474_ABS_POS_SIGN_BIT_MASK) 
00908   {
00909     /* Negative register value */
00910     abs_position_reg = ~abs_position_reg;
00911     abs_position_reg += 1;
00912 
00913     operation_result = (int32_t) (abs_position_reg & L6474_ABS_POS_VALUE_MASK);
00914     operation_result = -operation_result;
00915   } 
00916   else 
00917   {
00918     operation_result = (int32_t) abs_position_reg;
00919   }
00920 
00921   return operation_result;
00922 }
00923 
00924 /**********************************************************
00925  * @brief Error handler which calls the user callback (if defined)
00926  * @param[in] error Number of the error
00927  * @retval None
00928  **********************************************************/
00929 void L6474::L6474_ErrorHandler(uint16_t error)
00930 {
00931   if (error_handler_callback != 0)
00932   {
00933     (void) error_handler_callback(error);
00934   }
00935   else   
00936   {
00937     /* Aborting the program. */
00938     exit(EXIT_FAILURE);
00939   }
00940 }
00941 
00942 /**********************************************************
00943  * @brief  Sends a command without arguments to the L6474 via the SPI
00944  * @param[in] param Command to send 
00945  * @retval None
00946  **********************************************************/
00947 void L6474::L6474_SendCommand(uint8_t param)
00948 {
00949   uint32_t i;
00950   bool itDisable = FALSE;
00951   uint8_t spiIndex = number_of_devices - device_instance - 1;
00952   
00953   do
00954   {
00955     spi_preemtion_by_isr = FALSE;
00956     if (itDisable)
00957     {
00958       /* re-enable L6474_EnableIrq if disable in previous iteration */
00959       L6474_EnableIrq();
00960       itDisable = FALSE;
00961     }
00962   
00963     for (i = 0; i < number_of_devices; i++)
00964     {
00965       spi_tx_bursts[3][i] = L6474_NOP;     
00966     }
00967     spi_tx_bursts[3][spiIndex] = param;
00968     
00969     /* Disable interruption before checking */
00970     /* pre-emption by ISR and SPI transfers*/
00971     L6474_DisableIrq();
00972     itDisable = TRUE;
00973   } while (spi_preemtion_by_isr); // check pre-emption by ISR
00974 
00975   L6474_WriteBytes(&spi_tx_bursts[3][0], &spi_rx_bursts[3][0]); 
00976   
00977   /* re-enable L6474_EnableIrq after SPI transfers*/
00978   L6474_EnableIrq();
00979 }
00980 
00981 /**********************************************************
00982  * @brief  Sets the registers of the L6474 to their predefined values 
00983  * from l6474_target_config.h
00984  * @retval None
00985  **********************************************************/
00986 void L6474::L6474_SetRegisterToPredefinedValues(void)
00987 {
00988   L6474_CmdSetParam(
00989                     L6474_ABS_POS,
00990                     0);
00991   L6474_CmdSetParam(
00992                     L6474_EL_POS,
00993                     0);
00994   L6474_CmdSetParam(
00995                     L6474_MARK,
00996                     0);
00997   switch (device_instance)
00998   {
00999     case 0:
01000       L6474_CmdSetParam(
01001                         L6474_TVAL,
01002                         L6474_Tval_Current_to_Par(L6474_CONF_PARAM_TVAL_DEVICE_0));
01003       L6474_CmdSetParam(
01004                         L6474_T_FAST,
01005                         (uint8_t)L6474_CONF_PARAM_TOFF_FAST_DEVICE_0 |
01006                         (uint8_t)L6474_CONF_PARAM_FAST_STEP_DEVICE_0);
01007       L6474_CmdSetParam(
01008                         L6474_TON_MIN,
01009                         L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TON_MIN_DEVICE_0)
01010                         );
01011       L6474_CmdSetParam(
01012                         L6474_TOFF_MIN,
01013                         L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TOFF_MIN_DEVICE_0));
01014       L6474_CmdSetParam(
01015                         L6474_OCD_TH,
01016                         L6474_CONF_PARAM_OCD_TH_DEVICE_0);
01017       L6474_CmdSetParam(
01018                         L6474_STEP_MODE,
01019                         (uint8_t)L6474_CONF_PARAM_STEP_SEL_DEVICE_0 |
01020                         (uint8_t)L6474_CONF_PARAM_SYNC_SEL_DEVICE_0);
01021       L6474_CmdSetParam(
01022                         L6474_ALARM_EN,
01023                         L6474_CONF_PARAM_ALARM_EN_DEVICE_0);
01024       L6474_CmdSetParam(
01025                         L6474_CONFIG,
01026                         (uint16_t)L6474_CONF_PARAM_CLOCK_SETTING_DEVICE_0 |
01027                         (uint16_t)L6474_CONF_PARAM_TQ_REG_DEVICE_0 |
01028                         (uint16_t)L6474_CONF_PARAM_OC_SD_DEVICE_0 |
01029                         (uint16_t)L6474_CONF_PARAM_SR_DEVICE_0 |
01030                         (uint16_t)L6474_CONF_PARAM_TOFF_DEVICE_0);
01031       break;
01032     case 1:
01033       L6474_CmdSetParam(
01034                         L6474_TVAL,
01035                         L6474_Tval_Current_to_Par(L6474_CONF_PARAM_TVAL_DEVICE_1));
01036       L6474_CmdSetParam(
01037                         L6474_T_FAST,
01038                         (uint8_t)L6474_CONF_PARAM_TOFF_FAST_DEVICE_1 |
01039                         (uint8_t)L6474_CONF_PARAM_FAST_STEP_DEVICE_1);
01040       L6474_CmdSetParam(
01041                         L6474_TON_MIN,
01042                         L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TON_MIN_DEVICE_1));
01043       L6474_CmdSetParam(
01044                         L6474_TOFF_MIN,
01045                         L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TOFF_MIN_DEVICE_1));
01046       L6474_CmdSetParam(
01047                         L6474_OCD_TH,
01048                         L6474_CONF_PARAM_OCD_TH_DEVICE_1);
01049       L6474_CmdSetParam(
01050                         L6474_STEP_MODE,
01051                         (uint8_t)L6474_CONF_PARAM_STEP_SEL_DEVICE_1 |
01052                         (uint8_t)L6474_CONF_PARAM_SYNC_SEL_DEVICE_1);
01053       L6474_CmdSetParam(
01054                         L6474_ALARM_EN,
01055                         L6474_CONF_PARAM_ALARM_EN_DEVICE_1);
01056       L6474_CmdSetParam(
01057                         L6474_CONFIG,
01058                         (uint16_t)L6474_CONF_PARAM_CLOCK_SETTING_DEVICE_1 |
01059                         (uint16_t)L6474_CONF_PARAM_TQ_REG_DEVICE_1 |
01060                         (uint16_t)L6474_CONF_PARAM_OC_SD_DEVICE_1 |
01061                         (uint16_t)L6474_CONF_PARAM_SR_DEVICE_1 |
01062                         (uint16_t)L6474_CONF_PARAM_TOFF_DEVICE_1);
01063       break;
01064     case 2:
01065       L6474_CmdSetParam(
01066                         L6474_TVAL,
01067                         L6474_Tval_Current_to_Par(L6474_CONF_PARAM_TVAL_DEVICE_2));
01068       L6474_CmdSetParam(
01069                         L6474_T_FAST,
01070                         (uint8_t)L6474_CONF_PARAM_TOFF_FAST_DEVICE_2 |
01071                         (uint8_t)L6474_CONF_PARAM_FAST_STEP_DEVICE_2);
01072       L6474_CmdSetParam(
01073                         L6474_TON_MIN,
01074                         L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TON_MIN_DEVICE_2));
01075       L6474_CmdSetParam(
01076                         L6474_TOFF_MIN,
01077                         L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TOFF_MIN_DEVICE_2));
01078       L6474_CmdSetParam(
01079                         L6474_OCD_TH,
01080                         L6474_CONF_PARAM_OCD_TH_DEVICE_2);
01081       L6474_CmdSetParam(
01082                         L6474_STEP_MODE,
01083                         (uint8_t)L6474_CONF_PARAM_STEP_SEL_DEVICE_2 |
01084                         (uint8_t)L6474_CONF_PARAM_SYNC_SEL_DEVICE_2);
01085       L6474_CmdSetParam(
01086                         L6474_ALARM_EN,
01087                         L6474_CONF_PARAM_ALARM_EN_DEVICE_2);
01088       L6474_CmdSetParam(
01089                         L6474_CONFIG,
01090                         (uint16_t)L6474_CONF_PARAM_CLOCK_SETTING_DEVICE_2 |
01091                         (uint16_t)L6474_CONF_PARAM_TQ_REG_DEVICE_2 |
01092                         (uint16_t)L6474_CONF_PARAM_OC_SD_DEVICE_2 |
01093                         (uint16_t)L6474_CONF_PARAM_SR_DEVICE_2 |
01094                         (uint16_t)L6474_CONF_PARAM_TOFF_DEVICE_2);
01095       break;
01096     default: ;
01097   }
01098 }
01099 
01100 /**********************************************************
01101  * @brief  Sets the registers of the L6474 to initialization values.
01102  * @param  init Initialization structure.
01103  * @retval None.
01104  **********************************************************/
01105 void L6474::L6474_SetRegisterToInitializationValues(L6474_Init_t *init)
01106 {
01107   L6474_CmdSetParam(
01108                     L6474_ABS_POS,
01109                     0
01110                     );
01111   L6474_CmdSetParam(
01112                     L6474_EL_POS,
01113                     0
01114                     );
01115   L6474_CmdSetParam(
01116                     L6474_MARK,
01117                     0
01118                     );
01119   L6474_CmdSetParam(
01120                     L6474_TVAL,
01121                     L6474_Tval_Current_to_Par(init->torque_regulation_current_mA)
01122                     );
01123   L6474_CmdSetParam(
01124                     L6474_T_FAST,
01125                     (uint8_t) init->maximum_fast_decay_time |
01126                     (uint8_t) init->fall_time
01127                     );
01128   L6474_CmdSetParam(
01129                     L6474_TON_MIN,
01130                     L6474_Tmin_Time_to_Par(init->minimum_ON_time_us)
01131                     );
01132   L6474_CmdSetParam(
01133                     L6474_TOFF_MIN,
01134                     L6474_Tmin_Time_to_Par(init->minimum_OFF_time_us)
01135                     );
01136   L6474_CmdSetParam(
01137                     L6474_OCD_TH,
01138                     init->overcurrent_threshold
01139                     );
01140   L6474_CmdSetParam(
01141                     L6474_STEP_MODE,
01142                     (uint8_t) init->step_selection |
01143                     (uint8_t) init->sync_selection
01144                     );
01145   L6474_CmdSetParam(
01146                     L6474_ALARM_EN,
01147                     init->alarm
01148                     );
01149   L6474_CmdSetParam(
01150                     L6474_CONFIG,
01151                     (uint16_t) init->clock |
01152                     (uint16_t) init->torque_regulation_method |
01153                     (uint16_t) init->overcurrent_shutwdown |
01154                     (uint16_t) init->slew_rate |
01155                     (uint16_t) init->target_swicthing_period
01156                     );
01157 }
01158 
01159 /**********************************************************
01160  * @brief  Sets the parameters of the device to predefined values
01161  * from l6474_target_config.h
01162  * @param None
01163  * @retval None
01164  **********************************************************/
01165 void L6474::L6474_SetDeviceParamsToPredefinedValues(void)
01166 {
01167   switch (device_instance)
01168   {
01169     case 0:
01170       device_prm.acceleration = L6474_CONF_PARAM_ACC_DEVICE_0;
01171       device_prm.deceleration = L6474_CONF_PARAM_DEC_DEVICE_0;
01172       device_prm.maxSpeed = L6474_CONF_PARAM_MAX_SPEED_DEVICE_0;
01173       device_prm.minSpeed = L6474_CONF_PARAM_MIN_SPEED_DEVICE_0;
01174       break;
01175 
01176     case 1:
01177       device_prm.acceleration = L6474_CONF_PARAM_ACC_DEVICE_1;
01178       device_prm.deceleration = L6474_CONF_PARAM_DEC_DEVICE_1;
01179       device_prm.maxSpeed = L6474_CONF_PARAM_MAX_SPEED_DEVICE_1;
01180       device_prm.minSpeed = L6474_CONF_PARAM_MIN_SPEED_DEVICE_1;
01181       break;
01182 
01183     case 2:
01184       device_prm.acceleration = L6474_CONF_PARAM_ACC_DEVICE_2;
01185       device_prm.deceleration = L6474_CONF_PARAM_DEC_DEVICE_2;
01186       device_prm.maxSpeed = L6474_CONF_PARAM_MAX_SPEED_DEVICE_2;
01187       device_prm.minSpeed = L6474_CONF_PARAM_MIN_SPEED_DEVICE_2;
01188       break;
01189   }
01190 
01191   device_prm.accu = 0;
01192   device_prm.currentPosition = 0;
01193   device_prm.endAccPos = 0;
01194   device_prm.relativePos = 0;
01195   device_prm.startDecPos = 0;
01196   device_prm.stepsToTake = 0;
01197   device_prm.speed = 0;
01198   device_prm.commandExecuted = NO_CMD;
01199   device_prm.direction = FORWARD;
01200   device_prm.motionState = INACTIVE;
01201 }
01202 
01203 /**********************************************************
01204  * @brief Initialises the bridge parameters to start the movement
01205  * and enable the power bridge
01206  * @retval None
01207  **********************************************************/
01208 void L6474::L6474_StartMovement(void)  
01209 {
01210   /* Enable L6474 powerstage */
01211   L6474_CmdEnable();
01212   if (device_prm.endAccPos != 0)
01213   {
01214     device_prm.motionState = ACCELERATING;
01215   }
01216   else
01217   {
01218     device_prm.motionState = DECELERATING;    
01219   }
01220   device_prm.accu = 0;
01221   device_prm.relativePos = 0;
01222   L6474_ApplySpeed(device_prm.minSpeed);
01223 }
01224 
01225 /**********************************************************
01226  * @brief  Handles the device state machine at each ste
01227  * @retval None
01228  * @note Must only be called by the timer ISR
01229  **********************************************************/
01230 void L6474::L6474_StepClockHandler(void)
01231 {
01232   /* Set isr flag */
01233   isr_flag = TRUE;
01234   
01235   /* Incrementation of the relative position */
01236   device_prm.relativePos++;
01237 
01238   switch (device_prm.motionState) 
01239   {
01240     case ACCELERATING: 
01241     {
01242         uint32_t relPos = device_prm.relativePos;
01243         uint32_t endAccPos = device_prm.endAccPos;
01244         uint16_t speed = device_prm.speed;
01245         uint32_t acc = ((uint32_t)device_prm.acceleration << 16);
01246         
01247         if ((device_prm.commandExecuted == SOFT_STOP_CMD)||
01248             ((device_prm.commandExecuted != RUN_CMD)&&  
01249              (relPos == device_prm.startDecPos)))
01250         {
01251           device_prm.motionState = DECELERATING;
01252           device_prm.accu = 0;
01253         }
01254         else if ((speed >= device_prm.maxSpeed)||
01255                  ((device_prm.commandExecuted != RUN_CMD)&&
01256                   (relPos == endAccPos)))
01257         {
01258           device_prm.motionState = STEADY;
01259         }
01260         else
01261         {
01262           bool speedUpdated = FALSE;
01263           /* Go on accelerating */
01264           if (speed == 0) speed =1;
01265           device_prm.accu += acc / speed;
01266           while (device_prm.accu >= (0X10000L))
01267           {
01268             device_prm.accu -= (0X10000L);
01269             speed +=1;
01270             speedUpdated = TRUE;
01271           }
01272           
01273           if (speedUpdated)
01274           {
01275             if (speed > device_prm.maxSpeed)
01276             {
01277               speed = device_prm.maxSpeed;
01278             }    
01279             device_prm.speed = speed;
01280             L6474_ApplySpeed(device_prm.speed);
01281           }
01282         }
01283         break;
01284     }
01285     case STEADY: 
01286     {
01287       uint16_t maxSpeed = device_prm.maxSpeed;
01288       uint32_t relativePos = device_prm.relativePos;
01289       if  ((device_prm.commandExecuted == SOFT_STOP_CMD)||
01290            ((device_prm.commandExecuted != RUN_CMD)&&
01291             (relativePos >= (device_prm.startDecPos))) ||
01292            ((device_prm.commandExecuted == RUN_CMD)&&
01293             (device_prm.speed > maxSpeed)))
01294       {
01295         device_prm.motionState = DECELERATING;
01296         device_prm.accu = 0;
01297       }
01298       else if ((device_prm.commandExecuted == RUN_CMD)&&
01299                (device_prm.speed < maxSpeed))
01300       {
01301         device_prm.motionState = ACCELERATING;
01302         device_prm.accu = 0;
01303       }
01304       break;
01305     }
01306     case DECELERATING: 
01307     {
01308       uint32_t relativePos = device_prm.relativePos;
01309       uint16_t speed = device_prm.speed;
01310       uint32_t deceleration = ((uint32_t)device_prm.deceleration << 16);
01311       if (((device_prm.commandExecuted == SOFT_STOP_CMD)&&(speed <=  device_prm.minSpeed))||
01312           ((device_prm.commandExecuted != RUN_CMD)&&
01313            (relativePos >= device_prm.stepsToTake)))
01314       {
01315         /* Motion process complete */
01316         L6474_HardStop();
01317       }
01318       else if ((device_prm.commandExecuted == RUN_CMD)&&
01319                (speed <= device_prm.maxSpeed))
01320       {
01321         device_prm.motionState = STEADY;
01322       }
01323       else
01324       {
01325         /* Go on decelerating */
01326         if (speed > device_prm.minSpeed)
01327         {
01328           bool speedUpdated = FALSE;
01329           if (speed == 0) speed =1;
01330           device_prm.accu += deceleration / speed;
01331           while (device_prm.accu >= (0X10000L))
01332           {
01333             device_prm.accu -= (0X10000L);
01334             if (speed > 1)
01335             {  
01336               speed -=1;
01337             }
01338             speedUpdated = TRUE;
01339           }
01340         
01341           if (speedUpdated)
01342           {
01343             if (speed < device_prm.minSpeed)
01344             {
01345               speed = device_prm.minSpeed;
01346             }  
01347             device_prm.speed = speed;
01348             L6474_ApplySpeed(device_prm.speed);
01349           }
01350         }
01351       }
01352       break;
01353     }
01354     default: 
01355     {
01356       break;
01357     }
01358   }  
01359   /* Set isr flag */
01360   isr_flag = FALSE;
01361 }
01362 
01363 /**********************************************************
01364  * @brief Converts current in mA to values for TVAL register 
01365  * @param[in] current_mA current in mA
01366  * @retval value for TVAL register
01367  **********************************************************/
01368 float L6474::L6474_Tval_Current_to_Par(float current_mA)
01369 {
01370   return ((float)(((current_mA - 31.25f) / 31.25f) + 0.5f));
01371 }
01372 
01373 /**********************************************************
01374  * @brief Converts values from TVAL register to mA
01375  * @param[in] Tval value from TVAL register
01376  * @retval current in mA
01377  **********************************************************/
01378 float L6474::L6474_Par_to_Tval_Current(float Tval)
01379 {
01380   return ((float)((Tval - 0.5f) * 31.25f + 31.25f));
01381 }
01382 
01383 /**********************************************************
01384  * @brief Convert time in us to values for TON_MIN register
01385  * @param[in] ton_min_us time in us
01386  * @retval value for TON_MIN register
01387  **********************************************************/
01388 float L6474::L6474_Tmin_Time_to_Par(float ton_min_us)
01389 {
01390   return ((float)(((ton_min_us - 0.5f) * 2.0f) + 0.5f));
01391 }
01392 
01393 /**********************************************************
01394  * @brief Convert values for TON_MIN register to time in us
01395  * @param[in] Tmin value from TON_MIN register
01396  * @retval time in us
01397  **********************************************************/
01398 float L6474::L6474_Par_to_Tmin_Time(float Tmin)
01399 {
01400   return ((float)(((Tmin - 0.5f) / 2.0f) + 0.5f));
01401 }
01402 
01403 /**********************************************************
01404  * @brief  Write and receive a byte via SPI
01405  * @param[in] pByteToTransmit pointer to the byte to transmit
01406  * @param[in] pReceivedByte pointer to the received byte
01407  * @retval None
01408  **********************************************************/
01409 void L6474::L6474_WriteBytes(uint8_t *pByteToTransmit, uint8_t *pReceivedByte)
01410 {
01411   if (L6474_SpiWriteBytes(pByteToTransmit, pReceivedByte) != 0)
01412   {
01413     L6474_ErrorHandler(L6474_ERROR_1);
01414   }
01415   
01416   if (isr_flag)
01417   {
01418     spi_preemtion_by_isr = TRUE;
01419   }
01420 }
01421 
01422 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/