Expansion SW library to control a bipolar stepper motor using X-NUCLEO-IHM05A1 expansion board based on L6208.

Dependencies:   ST_INTERFACES

Dependents:   HelloWorld_IHM05A1 TAU_ROTATING_PLATFORM_IHM05A1 Amaldi_13_Exercise_IHM05A1 Amaldi_13_Exercise_IHM05A1motore ... more

Fork of X-NUCLEO-IHM05A1 by ST Expansion SW Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers L6208.cpp Source File

L6208.cpp

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    L6208.cpp
00004   * @author  IPC Rennes
00005   * @version V1.1.0
00006   * @date    February 11th, 2016
00007   * @brief   L6208 product related routines
00008   * @note    (C) COPYRIGHT 2016 STMicroelectronics
00009   ******************************************************************************
00010   * @attention
00011   *
00012   * <h2><center>&copy; COPYRIGHT(c) 2016 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 /* Includes ------------------------------------------------------------------*/
00040 #include "L6208.h"
00041 
00042 /* Definitions ---------------------------------------------------------------*/
00043 /// Bridge A
00044 #define BRIDGE_A                     (0)
00045 /// Bridge B
00046 #define BRIDGE_B                     (1)
00047 
00048 /// Bitmaps for system flags
00049 #define EN_A_set              0x00000001    ///< EN_A pin status
00050 #define HiZstop               0x00000002    ///< motor has to be left in HiZ after stopping
00051 #define busy                  0x00000004    ///< stepper position command executing flag
00052 #define running               0x00000008    ///< running motor flag
00053 #define velocitymode          0x00000010    ///< velocity controlled stepper motor
00054 #define positionmode          0x00000020    ///< position controlled stepper motor
00055 #define fullstep              0x00000040    ///< full step mode controlled    
00056 #define halfstep              0x00000080    ///< half step mode controlled    
00057 #define microstep             0x00000100    ///< micro step mode controlled
00058 #define forward               0x00000200    ///< forward running motor
00059 #define dir2change            0x00000400    ///< direction has to be changed while the motor is running
00060 #define fastdecaymode         0x00000800    ///< decay mode is fast
00061 #define wavestep              0x00001000    ///< wave step mode controlled
00062 
00063 /* Variables  ----------------------------------------------------------------*/
00064 /* Number of devices. */
00065 uint8_t L6208::numberOfDevices = 0;
00066 
00067 /// RefMicroTable values are 2^L6208_SINE_WAVEFORM_POWER_OF_TWO_MAX_VALUE*|sin(n/16*PI/2)|
00068 /// where n is the index in the table
00069 const uint16_t L6208::RefMicroTable[L6208_USTEPS_PER_QUARTER_PERIOD*3] =
00070 {
00071   0,3212,6393,9512,12540,15447,18205,20788,23170,25330,27246,28899,30274,31357,32138,32610,
00072   32768,32610,32138,31357,30274,28899,27246,25330,23170,20788,18205,15447,12540,9512,6393,3212,
00073   0,3212,6393,9512,12540,15447,18205,20788,23170,25330,27246,28899,30274,31357,32138,32610
00074 };
00075 
00076 /* Methods -------------------------------------------------------------------*/
00077 /******************************************************//**
00078  * @brief Start the L6208 library
00079  * @param[in] pInit pointer to the initialization data
00080  * @retval COMPONENT_OK in case of success.
00081  **********************************************************/
00082 status_t L6208::L6208_Init(void* pInit)
00083 { 
00084   if (pInit == NULL)
00085   {
00086     /* Set context variables to the predefined values from l6208_target_config.h */
00087     /* Set GPIO according to these values */
00088     L6208_SetDeviceParamsToPredefinedValues();
00089   }
00090   else
00091   {
00092     L6208_SetDeviceParamsToGivenValues((l6208_init_t*) pInit);
00093   }
00094   
00095   /* Initialise the PWMs */
00096   L6208_Board_VrefPwmInit(BRIDGE_A, devicePrm.vrefPwmPeriod);
00097   L6208_Board_VrefPwmInit(BRIDGE_B, devicePrm.vrefPwmPeriod);
00098 
00099   /* Initialise the tick */
00100   L6208_Board_TickInit();
00101   
00102   /* Reset L6208 */
00103   L6208_ResetDevice();
00104   
00105   /* Align motor mechanical position to driver position */
00106   L6208_Board_VrefPwmStart(BRIDGE_A, devicePrm.vrefPwmPeriod);
00107   L6208_Board_VrefPwmStart(BRIDGE_B, devicePrm.vrefPwmPeriod);
00108   //L6208_Enable();
00109   
00110   return COMPONENT_OK;
00111 }
00112 
00113 /**********************************************************
00114  * @brief Read id
00115  * @param id pointer to the identifier to be read.
00116  * @retval COMPONENT_OK in case of success.
00117  **********************************************************/
00118 status_t L6208::L6208_ReadID(uint8_t *id)
00119 {
00120   *id = deviceInstance;
00121 
00122   return COMPONENT_OK;
00123 }
00124 
00125 /**********************************************************
00126  * @brief  Attaches a user callback to the error Handler.
00127  * The call back will be then called each time the library 
00128  * detects an error
00129  * @param[in] callback Name of the callback to attach 
00130  * to the error Hanlder
00131  * @retval None
00132  **********************************************************/
00133 void L6208::L6208_AttachErrorHandler(void (*callback)(uint16_t error))
00134 {
00135   errorHandlerCallback = (void (*)(uint16_t error)) callback;
00136 }
00137 
00138 /******************************************************//**
00139  * @brief Disable the power bridges (leave the output bridges HiZ)
00140  * @retval None
00141  **********************************************************/
00142 void L6208::L6208_Disable(void)
00143 {
00144   L6208_Board_Disable();
00145   L6208_ClearSysFlag(EN_A_set);
00146 }
00147 
00148 /******************************************************//**
00149  * @brief Error handler which calls the user callback (if defined)
00150  * @param[in] error Number of the error
00151  * @retval None
00152  **********************************************************/
00153 void L6208::L6208_ErrorHandler(uint16_t error)
00154 {
00155   if (errorHandlerCallback != 0)
00156   {
00157     errorHandlerCallback(error);
00158   }
00159   else   
00160   {
00161     while(1)
00162     {
00163       /* Infinite loop */
00164     }
00165   }
00166 }
00167 
00168 /******************************************************//**
00169  * @brief Enable the power bridges
00170  * @retval None
00171  **********************************************************/
00172 void L6208::L6208_Enable(void)
00173 {
00174   L6208_Board_Enable();
00175   L6208_SetSysFlag(EN_A_set);
00176 }
00177 
00178 /******************************************************//**
00179  * @brief Get the stepper acceleration rate
00180  * in step/s^2 for full, half and wave modes
00181  * in microsteps/s^2 for microstep modes
00182  * @retval the stepper acceleration rate in step/s^2 or microstep/s^2
00183  * @note
00184  **********************************************************/
00185 uint16_t L6208::L6208_GetAcceleration(void)
00186 {
00187     return devicePrm.accelerationSps2;
00188 }
00189 
00190 /******************************************************//**
00191  * @brief Get the current speed
00192  * in step/s for full, half and wave modes
00193  * in microsteps/s for microstep modes
00194  * @retval return the current speed in step/s or microstep/s
00195  * @note
00196  **********************************************************/
00197 uint16_t L6208::L6208_GetCurrentSpeed(void)
00198 {
00199   uint64_t tmp64 = (uint64_t) devicePrm.speedSpt * L6208_Board_TickGetFreq();
00200   
00201   devicePrm.speedSps = (uint16_t)(tmp64 >> 23);
00202   if (devicePrm.speedSps & 0x1)
00203   {
00204     devicePrm.speedSps = (devicePrm.speedSps >> 1) + 1;
00205   }
00206   else
00207   {
00208     devicePrm.speedSps = devicePrm.speedSps >> 1;
00209   }
00210   return devicePrm.speedSps;
00211 }
00212 
00213 /******************************************************//**
00214  * @brief Get the motor decay mode
00215  * @retval decay mode
00216  **********************************************************/
00217 motorDecayMode_t L6208::L6208_get_decay_mode(void)
00218 {
00219   if (L6208_IsSysFlag(fastdecaymode))
00220   {
00221       return (FAST_DECAY);
00222   }
00223   else
00224   {
00225       return (SLOW_DECAY);
00226   }
00227 }
00228 
00229 /******************************************************//**
00230  * @brief Get the stepper deceleration rate
00231  * in step/s^2 for full, half and wave modes
00232  * in microsteps/s^2 for microstep modes
00233  * @retval the stepper deceleration rate in step/s^2 or microstep/s^2
00234  * @note
00235  **********************************************************/
00236 uint16_t L6208::L6208_GetDeceleration(void)
00237 {
00238     return devicePrm.decelerationSps2;
00239 }
00240 
00241 /******************************************************//**
00242  * @brief Get the motor current direction
00243  * @retval direction
00244  **********************************************************/
00245 motorDir_t L6208::L6208_GetDirection(void)
00246 {
00247   if (L6208_IsSysFlag(forward))
00248   {
00249     return FORWARD;
00250   }
00251   else
00252   {
00253     return BACKWARD;
00254   }
00255 }
00256 
00257 /******************************************************//**
00258  * @brief Return the FW version.
00259  * @retval FW version
00260  **********************************************************/
00261 uint32_t L6208::L6208_GetFwVersion(void)
00262 {
00263   return L6208_FW_VERSION;
00264 }
00265 
00266 /******************************************************//**
00267  * @brief Get the mark position (32b signed) 
00268  * @retval mark position
00269  **********************************************************/
00270 int32_t L6208::L6208_GetMark(void)
00271 {
00272   return devicePrm.markPos;
00273 }
00274 
00275 /******************************************************//**
00276  * @brief Get the max speed
00277  * in step/s for full, half and wave modes
00278  * in microsteps/s for microstep modes
00279  * @retval return the max speed in step/s or microstep/s
00280  * @note
00281  **********************************************************/
00282 uint16_t L6208::L6208_GetMaxSpeed(void)
00283 {
00284   return devicePrm.maxSpeedSps;
00285 }
00286 
00287 /******************************************************//**
00288  * @brief Get the min speed
00289  * in step/s for full, half and wave modes
00290  * in microsteps/s for microstep modes
00291  * @retval return the min speed in step/s or microstep/s
00292  * @note
00293  **********************************************************/
00294 uint16_t L6208::L6208_GetMinSpeed(void)
00295 {
00296   return devicePrm.minSpeedSps;
00297 }
00298 
00299 /******************************************************//**
00300  * @brief Get the stepper state machine index
00301  * @retval one of the stepper state machine index in the motorState_t enum
00302  **********************************************************/
00303 motorState_t L6208::L6208_GetMotionState(void)
00304 {
00305   // gets the new stepper state machine index
00306   return devicePrm.motionState;    
00307 }
00308 
00309 /******************************************************//**
00310  * @brief Get the current position (32b signed) 
00311  * @retval current absoulte position
00312  **********************************************************/
00313 int32_t L6208::L6208_GetPosition(void)
00314 {
00315   return devicePrm.absolutePos;
00316 }
00317 
00318 /******************************************************//**
00319  * @brief Get the motor step mode
00320  * @retval step mode
00321  **********************************************************/
00322 motorStepMode_t L6208::L6208_GetStepMode(void)
00323 {
00324   return devicePrm.stepMode;
00325 }
00326 
00327 /******************************************************//**
00328  * @brief Get the selected stop mode
00329  * @retval the selected stop mode
00330  **********************************************************/
00331 motorStopMode_t L6208::L6208_GetStopMode(void)
00332 {
00333   if (L6208_IsSysFlag(HiZstop) == FALSE)
00334   {
00335       return (HOLD_MODE);
00336   }
00337   else
00338   {
00339       return (HIZ_MODE);
00340   }
00341 }
00342 
00343 /******************************************************//**
00344  * @brief Go to the home position
00345  * @retval None
00346  **********************************************************/
00347 void L6208::L6208_GoHome(void)
00348 {
00349   L6208_GoTo(0);
00350 }
00351 
00352 /******************************************************//**
00353  * @brief Go to the Mark position
00354  * @retval None
00355  **********************************************************/
00356 void L6208::L6208_GoMark(void)
00357 {
00358   L6208_GoTo(devicePrm.markPos);
00359 }
00360 
00361 /******************************************************//**
00362  * @brief move the motor to the absolute position using the shortest path
00363  * @param[in] abs_pos 32 bit signed value position
00364  * @retval None
00365  * @note The position is at the resolution corresponding to the
00366  * selected step mode.
00367  * STEP_MODE_FULL or STEP_MODE_WAVE : step
00368  * STEP_MODE_HALF                     : 1/2 step
00369  * STEP_MODE_1_4              : 1/4 step
00370  * STEP_MODE_1_8              : 1/8 step
00371  * STEP_MODE_1_16             : 1/16 step 
00372  **********************************************************/
00373 void L6208::L6208_GoTo(int32_t abs_pos)
00374 {
00375   uint32_t steps = 0;
00376   
00377   if(L6208_IsSysFlag(running))
00378   {
00379     L6208_HardStop();
00380   }
00381   
00382   if (abs_pos > devicePrm.absolutePos)
00383   {
00384     steps = abs_pos - devicePrm.absolutePos;
00385     if (steps < (L6208_POSITION_RANGE>>1))
00386     {
00387       L6208_Move(FORWARD, steps);
00388     }
00389     else
00390     {
00391       L6208_Move(BACKWARD, (L6208_POSITION_RANGE - steps));
00392     }
00393   }
00394   else
00395   {
00396     steps = devicePrm.absolutePos - abs_pos;
00397     if (steps < (L6208_POSITION_RANGE>>1))
00398     {
00399       L6208_Move(BACKWARD, steps);
00400     }
00401     else
00402     {
00403       L6208_Move(FORWARD, (L6208_POSITION_RANGE - steps));
00404     }
00405   }
00406 }
00407 
00408 /******************************************************//**
00409  * @brief move the motor to the absolute position
00410  * @param[in] direction FORWARD or BACKWARD
00411  * @param[in] abs_pos 32 bit signed value position
00412  * @retval None
00413  * @note The position is at the resolution corresponding to the
00414  * selected step mode.
00415  * STEP_MODE_FULL or STEP_MODE_WAVE : step
00416  * STEP_MODE_HALF                     : 1/2 step
00417  * STEP_MODE_1_4              : 1/4 step
00418  * STEP_MODE_1_8              : 1/8 step
00419  * STEP_MODE_1_16             : 1/16 step 
00420  **********************************************************/
00421 void L6208::L6208_GoToDir(motorDir_t direction, int32_t abs_pos)
00422 {
00423   uint32_t steps = 0;
00424   
00425   if(L6208_IsSysFlag(running))
00426   {
00427     L6208_HardStop();
00428   }
00429   
00430   if (direction != BACKWARD)
00431   {
00432     if (abs_pos > devicePrm.absolutePos)
00433     {
00434       steps = abs_pos - devicePrm.absolutePos;
00435     }
00436     else
00437     {
00438       steps = L6208_POSITION_RANGE + (abs_pos - devicePrm.absolutePos);
00439     }
00440   }
00441   else
00442   {
00443     if (abs_pos > devicePrm.absolutePos)
00444     {
00445       steps = L6208_POSITION_RANGE + (devicePrm.absolutePos - abs_pos);
00446     }
00447     else
00448     {
00449       steps = devicePrm.absolutePos - abs_pos;
00450     }
00451   }
00452   L6208_Move(direction, steps);
00453 }
00454 
00455 /******************************************************//**
00456  * @brief Immediately stop the motor and disables the power bridges
00457  * @retval None
00458  **********************************************************/
00459 void L6208::L6208_HardHiZ(void)
00460 {
00461   /* Disables power stage */
00462   L6208_Disable();
00463   
00464   /* Sets inactive state */
00465   L6208_SetMotionState(INACTIVE);
00466   
00467   /* Clears the running motor and the position */
00468   L6208_ClearSysFlag(running);
00469  
00470   /* Disables PWMs */
00471   L6208_Board_VrefPwmStop(BRIDGE_A);
00472   L6208_Board_VrefPwmStop(BRIDGE_B);
00473   
00474   /* Disables tick timer */
00475   L6208_Board_TickStop();
00476 }
00477 
00478 /******************************************************//**
00479  * @brief Immediately stop the motor and keeps holding torque
00480  * @retval None
00481  **********************************************************/
00482 void L6208::L6208_HardStop(void) 
00483 {
00484   /* Sets inactive state */
00485   L6208_SetMotionState(INACTIVE);
00486   
00487   /* Clears the running motor and the position */
00488   L6208_ClearSysFlag(running);
00489   L6208_VectorCalc(devicePrm.holdTorque);
00490     
00491   /* Disables tick timer */
00492   L6208_Board_TickStop();
00493 }
00494 
00495 /******************************************************//**
00496  * @brief move the motor by the specified number of steps
00497  * in the specified direction
00498  * @param[in] direction FORWARD or BACKWARD
00499  * @param[in] stepCount 32 bit unsigned step count
00500  * @retval None
00501  * @note The step count resolution is corresponding to the
00502  * selected step mode.
00503  * STEP_MODE_FULL or STEP_MODE_WAVE : step
00504  * STEP_MODE_HALF                   : 1/2 step
00505  * STEP_MODE_1_4                    : 1/4 step
00506  * STEP_MODE_1_8                    : 1/8 step
00507  * STEP_MODE_1_16                   : 1/16 step 
00508  **********************************************************/
00509 void L6208::L6208_Move(motorDir_t direction, uint32_t stepCount)
00510 {
00511   if(L6208_IsSysFlag(running))
00512   {
00513     L6208_HardStop();
00514   }
00515 
00516   /* clear the velocity driving mode flag */
00517   L6208_ClearSysFlag(velocitymode);
00518   
00519   /* Set the indexing driving mode flag */
00520   /* and the user command executing flag */
00521   L6208_SetSysFlag(positionmode);
00522   
00523   /* store relative number of steps to move */
00524   devicePrm.positionTarget = stepCount;
00525 
00526   L6208_SetDirection(direction); 
00527   
00528   /* Motor activation */
00529   L6208_StartMovement(); 
00530 }
00531 
00532 /******************************************************//**
00533  * @brief  Release the L6208 reset (Reset pin set to high level)
00534  * @retval None
00535  **********************************************************/
00536 void L6208::L6208_ReleaseReset(void)
00537 { 
00538   L6208_Board_ReleaseReset(); 
00539 }
00540 
00541 /******************************************************//**
00542  * @brief Reset the L6208 (Reset pin set to low level)
00543  * @retval None
00544  **********************************************************/
00545 void L6208::L6208_Reset(void)
00546 {
00547   L6208_Board_Reset();
00548 }
00549 
00550 
00551 /******************************************************//**
00552  * @brief Call L6208_SetStepMode with current step mode, 
00553  * the L6208_SetStepMode function along with setting the step mode resets
00554  * the L6208 device
00555  * @retval None
00556  **********************************************************/
00557 void L6208::L6208_ResetDevice(void)
00558 {
00559   L6208_SetStepMode(L6208_GetStepMode());
00560 }
00561 
00562 /******************************************************//**
00563  * @brief run the motor in the specified direction
00564  * according to the speed profile defined by the minimum speed,
00565  * maximum speed, and acceleration parameters. 
00566  * The device accelerates from the minimum speed up to the maximum
00567  * speed by using the device acceleration.
00568  * @param[in] direction FORWARD or BACKWARD
00569  * @retval None
00570  **********************************************************/
00571 void L6208::L6208_Run(motorDir_t direction)
00572 {
00573   if(L6208_IsSysFlag(running))
00574   {
00575     L6208_HardStop();
00576   }
00577   L6208_SetDirection(direction);
00578   /* Clear the indexing driving mode flag */
00579   L6208_ClearSysFlag(positionmode);
00580   /* Set the velocity driving mode flag */
00581   L6208_SetSysFlag(velocitymode);
00582   /* Motor activation */
00583   L6208_StartMovement(); 
00584 }
00585 
00586 /******************************************************//**
00587  * @brief Set the stepper acceleration rate
00588  * in step/s^2 and step/tick^2 for full, half and wave modes
00589  * in microsteps/s^2 and microsteps/tick^2 for microstep modes
00590  * @param[in] newAcc new acceleration rate in step/s^2 or microstep/s^2
00591  * @retval TRUE
00592  * @note
00593  **********************************************************/
00594 bool L6208::L6208_SetAcceleration(uint16_t newAcc)
00595 {
00596   uint16_t newAccSpt2 = L6208_ConvertAcceDecelRateValue(newAcc);
00597   if (newAccSpt2)
00598   {
00599     devicePrm.accelerationSps2 = newAcc;
00600     devicePrm.accelerationSpt2 = newAccSpt2; 
00601   }
00602   else
00603   {
00604     L6208_ErrorHandler(L6208_ERROR_SET_ACCELERATION);
00605   }
00606   return TRUE;
00607 }
00608 
00609 /******************************************************//**
00610  * @brief Select the motor decay mode
00611  * @param[in] decayMode (SLOW_DECAY or FAST_DECAY)
00612  * @retval None
00613  **********************************************************/
00614 void L6208::L6208_SetDecayMode(motorDecayMode_t decayMode)
00615 {
00616   if ((decayMode & L6208_FAST_DECAY_MODE_MASK) == L6208_FAST_DECAY_MODE_MASK)
00617   {
00618     L6208_Board_CONTROL_PIN_Set();
00619     L6208_SetSysFlag(fastdecaymode);
00620   }
00621   else 
00622   {
00623     L6208_Board_CONTROL_PIN_Reset();
00624     L6208_ClearSysFlag(fastdecaymode);
00625   }
00626 }
00627 
00628 /******************************************************//**
00629  * @brief Set the stepper deceleration rate
00630  * in step/s^2 and step/tick^2 for full, half and wave modes
00631  * in microsteps/s^2 and microsteps/tick^2 for microstep modes
00632  * @param[in] newDec new deceleration rate in step/s^2 or microstep/s^2
00633  * @retval TRUE
00634  * @note
00635  **********************************************************/
00636 bool L6208::L6208_SetDeceleration(uint16_t newDec)
00637 {
00638   uint16_t newDecSpt2 = L6208_ConvertAcceDecelRateValue(newDec);
00639   if (newDecSpt2)
00640   {
00641     devicePrm.decelerationSps2 = newDec;
00642     devicePrm.decelerationSpt2 = newDecSpt2;
00643   }
00644   else
00645   {
00646     L6208_ErrorHandler(L6208_ERROR_SET_DECELERATION);
00647   }
00648   return TRUE;
00649 }
00650 
00651 /******************************************************//**
00652  * @brief Specify the direction
00653  * @param[in] dir FORWARD or BACKWARD
00654  * @note In velocity mode a direction change forces the device to stop and 
00655  * then run in the new direction. In position mode, if the device is 
00656  * running, a direction change will generate an error.
00657  * @retval None
00658  **********************************************************/
00659 void L6208::L6208_SetDirection(motorDir_t dir)
00660 {
00661   L6208_ClearSysFlag(dir2change);
00662   if (dir == FORWARD)
00663   {
00664     if (!L6208_IsSysFlag(forward))
00665     {
00666       if (L6208_IsSysFlag(running))
00667       {
00668         /* motor is running */
00669         if (L6208_IsSysFlag(positionmode))
00670         {
00671           L6208_ErrorHandler(L6208_ERROR_SET_DIRECTION);
00672         }
00673         else
00674         {
00675           /* set the rotation direction to change flag */
00676           L6208_SetSysFlag(dir2change);
00677         }
00678       }
00679       else /* the motor is stopped, cw direction selected */
00680       {
00681         L6208_SetSysFlag(forward);
00682         L6208_Board_DIR_PIN_Set();
00683       }
00684     }
00685   }
00686   else
00687   {
00688     if (L6208_IsSysFlag(forward))
00689    {
00690       if (L6208_IsSysFlag(running))
00691       {
00692         /* motor is running */
00693         if (L6208_IsSysFlag(positionmode))
00694         {
00695           L6208_ErrorHandler(L6208_ERROR_SET_DIRECTION);
00696         }
00697         else
00698         {
00699           /* set the rotation direction to change flag */
00700           L6208_SetSysFlag(dir2change);
00701         }
00702       }
00703       else /* the motor is stopped, ccw direction selected */
00704       {
00705         L6208_ClearSysFlag(forward);
00706         L6208_Board_DIR_PIN_Reset();
00707       }
00708     }
00709   }
00710   if(L6208_IsSysFlag(dir2change))
00711   {
00712     L6208_VectorCalc(devicePrm.decelTorque);     
00713     L6208_SetMotionState(DECELERATINGTOSTOP);  
00714   }
00715 }
00716 
00717 /******************************************************//**
00718  * @brief Set current position to be the home position
00719  * @retval None
00720  **********************************************************/
00721 void L6208::L6208_SetHome(void)
00722 {
00723   if (!L6208_IsSysFlag(running))
00724   {
00725       devicePrm.absolutePos = 0;
00726   }
00727   else
00728   {
00729       L6208_ErrorHandler(L6208_ERROR_SET_HOME);
00730   }
00731 }
00732 
00733 /******************************************************//**
00734  * @brief Set current position to be the mark position 
00735  * @retval None
00736  **********************************************************/
00737 void L6208::L6208_SetMark(void)
00738 {
00739   devicePrm.markPos = devicePrm.absolutePos;
00740 }
00741 
00742 /******************************************************//**
00743  * @brief Set the user selected maximum speed 
00744  * in step/s and step/tick for full, half and wave modes
00745  * in microsteps/s and microsteps/tick for microstep modes
00746  * @param[in] newSpeed speed value (step/s or microstep/s)
00747  * @retval TRUE
00748  * @note One microstep is 1/16 step
00749  **********************************************************/
00750 bool L6208::L6208_SetMaxSpeed(uint16_t newSpeed)
00751 {
00752   if (L6208_SetSpeed(newSpeed, &devicePrm.maxSpeedSpt))
00753   {
00754     devicePrm.maxSpeedSps = newSpeed;
00755   }
00756   else
00757   {
00758     L6208_ErrorHandler(L6208_ERROR_SET_MAX_SPEED);
00759   }
00760   return TRUE;
00761 }
00762 
00763 /******************************************************//**
00764  * @brief Set the user selected minimum speed 
00765  * in step/s and step/tick for full, half and wave modes
00766  * in microsteps/s and microsteps/tick for microstep modes
00767  * @param[in] newSpeed speed value (step/s or microstep/s)
00768  * @retval TRUE
00769  * @note One microstep is 1/16 step
00770  **********************************************************/
00771 bool L6208::L6208_SetMinSpeed(uint16_t newSpeed)
00772 {
00773   if (L6208_SetSpeed(newSpeed, &devicePrm.minSpeedSpt))
00774   {
00775     devicePrm.minSpeedSps = newSpeed;
00776   }
00777   else
00778   {
00779     L6208_ErrorHandler(L6208_ERROR_SET_MIN_SPEED);
00780   }
00781   return TRUE;
00782 }
00783 
00784 /******************************************************//**
00785  * @brief Set the step mode
00786  * @param[in] stepMode
00787  * @retval true if the command is successfully executed, else false
00788  * @note Every time the step mode is changed, the step state machine is reset
00789  **********************************************************/
00790 bool L6208::L6208_SetStepMode(motorStepMode_t stepMode)
00791 {
00792   devicePrm.stepMode = stepMode;
00793   L6208_ClearSysFlag(fullstep | halfstep | microstep | wavestep);
00794   switch (stepMode)
00795   {
00796     case STEP_MODE_HALF:
00797       /* Set the Half/Full pin low and Reset and the set the Half/Full pin high*/
00798       L6208_Board_HALF_FULL_PIN_Reset(); 
00799       L6208_Board_Reset();
00800       L6208_Board_HALF_FULL_PIN_Set();
00801       /* Set system flag */
00802       L6208_SetSysFlag(halfstep);
00803       break;
00804     case STEP_MODE_FULL:
00805        /* Set the Half/Full pin low and Reset */
00806       L6208_Board_HALF_FULL_PIN_Reset(); 
00807       L6208_Board_Reset();
00808       /* Set system flag */
00809       L6208_SetSysFlag(fullstep);
00810       break;
00811     case STEP_MODE_WAVE:
00812       /* Set the Half/Full pin low and Reset and the set the Half/Full pin high*/
00813       L6208_Board_CLOCK_PIN_Reset();
00814       L6208_Board_HALF_FULL_PIN_Reset();
00815       L6208_Board_Reset();
00816       L6208_Board_CLOCK_PIN_Set();
00817       L6208_Board_HALF_FULL_PIN_Set();
00818       L6208_Board_Delay(2);
00819       L6208_Board_CLOCK_PIN_Reset();
00820       L6208_Board_Delay(2);
00821       L6208_Board_HALF_FULL_PIN_Reset();
00822       /* Set system flag */
00823       L6208_SetSysFlag(wavestep);
00824       break;
00825       case STEP_MODE_1_4:
00826       /* Set the Half/Full pin low and Reset */
00827       L6208_Board_HALF_FULL_PIN_Reset();
00828       L6208_Board_Reset();
00829       /* Set system flag */
00830       L6208_SetSysFlag(microstep);
00831       devicePrm.uStepInc = 4;
00832       break;
00833     case STEP_MODE_1_8:
00834       /* Set the Half/Full pin low and Reset */
00835       L6208_Board_HALF_FULL_PIN_Reset();
00836       L6208_Board_Reset();
00837       /* Set system flag */
00838       L6208_SetSysFlag(microstep);
00839       devicePrm.uStepInc = 2;
00840       break;
00841       case STEP_MODE_1_16:
00842       /* Set the Half/Full pin low and Reset */
00843       L6208_Board_HALF_FULL_PIN_Reset();
00844       L6208_Board_Reset();
00845       /* Set system flag */
00846       L6208_SetSysFlag(microstep);
00847       devicePrm.uStepInc = 1;
00848       break;
00849     default:
00850       return FALSE;
00851     }
00852   L6208_Board_Delay(2);
00853   L6208_Board_ReleaseReset();
00854   L6208_ResetSteps();
00855   return TRUE;
00856 }
00857 
00858 /******************************************************//**
00859  * @brief Select the mode to stop the motor. When the motor
00860  * is stopped, if autoHiZ is TRUE, the power bridges are disabled
00861  * if autoHiZ is FALSE, the power bridges are kept enabled.
00862  * @param[in] stopMode HOLD_MODE to let power bridge enabled
00863  * @retval None
00864  **********************************************************/
00865 void L6208::L6208_SetStopMode(motorStopMode_t stopMode)
00866 {
00867   if (stopMode == HOLD_MODE)
00868   {
00869     L6208_ClearSysFlag(HiZstop);
00870   }
00871   else
00872   {
00873     L6208_SetSysFlag(HiZstop);
00874   }
00875 }
00876 
00877 /******************************************************//**
00878  * @brief  Stop the motor by using the device deceleration and set deceleration torque
00879  * @retval true if the command is successfully executed, else false
00880  * @note .
00881  **********************************************************/
00882 bool L6208::L6208_SoftStop(void)
00883 {   
00884   L6208_VectorCalc(devicePrm.decelTorque);
00885   L6208_SetMotionState(DECELERATINGTOSTOP);
00886   return TRUE;
00887 }
00888 
00889 /******************************************************//**
00890  * @brief  Handle the device state machine at each tick timer pulse end.
00891  * @retval None
00892  **********************************************************/
00893 void L6208::L6208_TickHandler(void)
00894 {
00895   uint32_t locMaxSpeedSpt = devicePrm.maxSpeedSpt;
00896   uint32_t locMinSpeedSpt = devicePrm.minSpeedSpt;
00897   
00898   /* Update state, target speed, acceleration and deceleration rates */
00899   L6208_Board_CLOCK_PIN_Reset();
00900     
00901   switch(L6208_GetMotionState())
00902   {
00903     /* ============ Velocity control mode states ======================== */
00904     case ACCELERATING:
00905       /* velocity mode: acceleration phase */
00906       /* Increase Speed and update position */
00907       L6208_DoAccel();
00908       if(locMaxSpeedSpt < devicePrm.speedSpt)
00909       {  
00910         /*Target speed reached */
00911         devicePrm.speedSpt = locMaxSpeedSpt;
00912         L6208_VectorCalc(devicePrm.runTorque); 
00913         L6208_SetMotionState(STEADY);
00914       }
00915       break;
00916     case STEADY:  
00917       /* velocity mode: constant speed phase */
00918       /* Update position */
00919       L6208_DoRun();  
00920       if(locMaxSpeedSpt != devicePrm.speedSpt)
00921       { 
00922         /* targeted speed  has changed */
00923         if(locMaxSpeedSpt< devicePrm.speedSpt)
00924         { 
00925           /* Slow down the motor */
00926           L6208_VectorCalc(devicePrm.decelTorque);     
00927           L6208_SetMotionState(DECELERATING); 
00928         }
00929         else
00930         { 
00931           /* speed up the motor */
00932           L6208_VectorCalc(devicePrm.accelTorque);     
00933           L6208_SetMotionState(ACCELERATING);
00934         }
00935       }
00936       break;
00937     case DECELERATING:  
00938       /* velocity mode: running motor deceleration phase */
00939       /* Decrease Speed and update position */
00940       L6208_DoDecel();  
00941       if(locMaxSpeedSpt > devicePrm.speedSpt)
00942       { 
00943         /*Target speed reached but motor has still to be run*/
00944         devicePrm.speedSpt = locMaxSpeedSpt;
00945         L6208_VectorCalc(devicePrm.runTorque);   
00946         L6208_SetMotionState(STEADY);  
00947       }
00948       break;
00949     case DECELERATINGTOSTOP: 
00950       /* velocity mode: decelerate to stopped phase */
00951       /* Decrease current speed */
00952       L6208_DoDecel();
00953       if(devicePrm.speedSpt == locMinSpeedSpt)
00954       { 
00955         if (L6208_IsSysFlag(dir2change))
00956         { 
00957           L6208_ClearSysFlag(running);
00958           /* Change direction */
00959           if (L6208_IsSysFlag(forward))
00960           {
00961             /* switch to reverse rotation */
00962             L6208_SetDirection(BACKWARD);
00963           }
00964           else
00965           {
00966             /* switch to forward rotation */
00967             L6208_SetDirection(FORWARD);
00968           }
00969           L6208_SetSysFlag(running);
00970           L6208_SetMotionState(ACCELERATING);
00971           /* Set VRefA and VRefB to the selected acceleration torque */
00972           L6208_VectorCalc(devicePrm.accelTorque);
00973         }
00974         else
00975         {
00976           if (L6208_IsSysFlag(HiZstop))
00977           { 
00978             L6208_HardHiZ();
00979           }
00980           else
00981           {
00982             L6208_HardStop();
00983           }
00984         }
00985       }
00986       break;
00987     
00988     /* ============ Position (indexed) control mode states ======================== */
00989 
00990     case INDEX_ACCEL:
00991       /*  position mode: acceleration state*/
00992       
00993       /* Increase Speed and update position */
00994       L6208_DoAccel();  
00995 
00996       if(devicePrm.positionTarget1 <= devicePrm.step)
00997       { 
00998         /* End of acceleration phase */
00999         L6208_VectorCalc(devicePrm.runTorque); 
01000         L6208_SetMotionState(INDEX_RUN);    
01001       }
01002       break;
01003 
01004       case INDEX_RUN:   
01005         /* position mode: constant speed phase */
01006         
01007         /* Update position */
01008         L6208_DoRun();  
01009 
01010         if(devicePrm.positionTarget2 <= devicePrm.step)
01011         {  
01012           /* reach position targeted for constant speed */
01013           L6208_VectorCalc(devicePrm.decelTorque);   
01014           L6208_SetMotionState(INDEX_DECEL); 
01015         }
01016         break;
01017 
01018       case INDEX_DECEL: 
01019         /* position mode: deceleration phase */
01020         
01021         /* Decrease Speed and update position */
01022         L6208_DoDecel();  
01023 
01024         if(devicePrm.positionTarget3 <= devicePrm.step)
01025         {  
01026           /* reach position targeted for deceleration phase */
01027           /* the motor terminated its run */
01028           /* the torque will be the deceleration one */
01029           devicePrm.step = devicePrm.positionTarget3;
01030           L6208_SetMotionState(INDEX_DWELL);   
01031         }
01032         break;
01033 
01034       case INDEX_DWELL: 
01035         /* position mode: dwelling state */
01036         if(devicePrm.dwellCounter > 0)
01037         {
01038           /* decrease the dwelling wait tick counter */
01039           devicePrm.dwellCounter--;
01040         }
01041         if(devicePrm.dwellCounter == 0)
01042         { 
01043           /* dwelling wait time is elapsed */
01044           /* so stop the motor */
01045           if (L6208_IsSysFlag(HiZstop))
01046           { 
01047             L6208_HardHiZ();
01048           }
01049           else
01050           {
01051             L6208_HardStop();
01052           }
01053         }
01054         break;
01055         
01056     /* ============ stopped state ======================== */
01057     case INACTIVE:
01058     {
01059       if(L6208_IsSysFlag(running))
01060       {
01061         /* clear the user move command executing  */
01062         /* and the motor running flags */
01063         L6208_ClearSysFlag(running);
01064       }
01065       break;
01066     }
01067     default:
01068       break;
01069   } /* switch(L6208_GetMotionState()) */
01070   if(L6208_GetMotionState() != INACTIVE)
01071   {
01072     if (L6208_IsSysFlag(microstep))
01073     { 
01074       /* Microstep handling */     
01075       switch(devicePrm.uStepInc)
01076       {
01077         default:
01078         case 1:  
01079           /* 1 microstep increment */
01080           devicePrm.lsbTicks = (uint8_t)(devicePrm.ticks>>16);
01081           break;
01082 
01083         case 2:  
01084           /* 2 microsteps increment */           
01085           devicePrm.lsbTicks = (uint8_t)(devicePrm.ticks>>17);
01086           break;
01087 
01088         case 4:  
01089           /* 4 microsteps increment */
01090           devicePrm.lsbTicks = (uint8_t)(devicePrm.ticks>>18);
01091           break;
01092       }
01093       devicePrm.lsbTicks &= 0x01;
01094       if(devicePrm.lsbOldUSteppingTicks != devicePrm.lsbTicks)
01095       { 
01096         /*  waveform sample to update */
01097         devicePrm.lsbOldUSteppingTicks = devicePrm.lsbTicks;
01098         devicePrm.step++;
01099         if(L6208_IsSysFlag(forward))
01100         { 
01101           /* the motor is going forward */
01102           devicePrm.absolutePos++;
01103           /* Reset the absolute motor position in step/microsteps */
01104           /* Get next microstep sample */
01105           devicePrm.uStepSample += devicePrm.uStepInc;  
01106           if(devicePrm.uStepSample > 31)
01107           {
01108             devicePrm.uStepSample = 0;
01109           }
01110         }
01111         else
01112         { 
01113          /* the motor is going backward */
01114           devicePrm.absolutePos--;
01115           if(devicePrm.uStepSample >= devicePrm.uStepInc)
01116           {
01117             /* Get previous microstep sample */
01118             devicePrm.uStepSample -= devicePrm.uStepInc; 
01119           }
01120           else
01121           {
01122             devicePrm.uStepSample = 32 - devicePrm.uStepInc;
01123           }
01124         }
01125         /* set the PWM to update VRefs */
01126         L6208_VrefPwmComputePulseWidth(BRIDGE_A, pMicroTable2[devicePrm.uStepSample], FALSE);
01127         L6208_VrefPwmComputePulseWidth(BRIDGE_B, microTable1[devicePrm.uStepSample], FALSE);
01128         if(devicePrm.uStepsample2update > 0)
01129         { 
01130           /*  the waveform samples table has been recalculated 
01131           so update the waveform scanning table */
01132           L6208_UpdateScanWaveformTable();
01133           devicePrm.uStepsample2update = 0;
01134         }
01135       }
01136       /* Microstep: use the bit4 toggling as step clock */
01137       /* this bit is used because there are 16 microstep samples per quarter period */
01138       devicePrm.lsbTicks = (uint8_t)((devicePrm.uStepSample>>4) & 0x01);
01139       if(devicePrm.lsbOldTicks != devicePrm.lsbTicks)
01140       { 
01141         /* the selected bit status changed ==> get the next motor step
01142         save the current masked motor tick position for step setting scope ... */
01143         devicePrm.lsbOldTicks = devicePrm.lsbTicks;
01144         L6208_Board_CLOCK_PIN_Set();
01145       }
01146     }
01147     else
01148     {
01149       /* Full and half step handling code */ 
01150       if(!L6208_IsSysFlag(halfstep))
01151       { 
01152         /* Full step: use the bit 16 toggling as step clock */
01153         devicePrm.lsbTicks = (uint8_t)((devicePrm.ticks>>16) & 0x00000001);
01154       }
01155       else
01156       { 
01157         /* half step: use the bit 15 toggling as step clock */
01158         devicePrm.lsbTicks = (uint8_t)((devicePrm.ticks>>15) & 0x00000001);
01159       }
01160       if(devicePrm.lsbOldTicks != devicePrm.lsbTicks)
01161       { 
01162         /* the selected bit status changed ==> get the next motor step */
01163         devicePrm.step++;
01164         if(L6208_IsSysFlag(forward))
01165         { 
01166           /* the motor is going forward */
01167           devicePrm.absolutePos++;
01168         }
01169         else
01170         {
01171           /* the motor is going backward */
01172           devicePrm.absolutePos--;          
01173         }
01174         /* save the current masked motor tick position for step setting scope ... */
01175         devicePrm.lsbOldTicks = devicePrm.lsbTicks;
01176         L6208_Board_CLOCK_PIN_Set();
01177       }
01178     }
01179   }
01180   L6208_UstepWaveformHandling();
01181   L6208_VrefPwmUpdatePulseWidth();
01182 }
01183 
01184 /******************************************************//**
01185  * @brief Get the frequency of VREFA and VREFB PWM
01186  * @retval the frequency of VREFA and VREFB PWM in Hz
01187  * @note
01188  **********************************************************/
01189 uint32_t L6208::L6208_VrefPwmGetFreq(void)
01190 {
01191   return devicePrm.vrefPwmFreq;
01192 }
01193 
01194 /******************************************************//**
01195  * @brief Set the frequency of the VREFA and VREFB PWM
01196  * @param[in] newFreq in Hz
01197  * @retval None
01198  * @note
01199  **********************************************************/
01200 void L6208::L6208_VrefPwmSetFreq(uint32_t newFreq)
01201 {
01202   devicePrm.vrefPwmFreq = newFreq;
01203   /* Compute the pwm period in 1/256th of a microsecond */
01204   devicePrm.vrefPwmPeriod = (uint16_t)((1000000<<8)/newFreq);
01205   /* Re-Initialise the PWMs -----------------------------------------------------*/
01206   L6208_Board_VrefPwmInit(BRIDGE_A, devicePrm.vrefPwmPeriod);
01207   L6208_Board_VrefPwmInit(BRIDGE_B, devicePrm.vrefPwmPeriod);
01208   /* Recompute the waveform samples according to the new PWM frequency */
01209   L6208_ScaleWaveformTable();
01210   /* Update the waveform scanning table */
01211   L6208_UpdateScanWaveformTable();
01212   if (L6208_IsSysFlag(running))
01213   {
01214     L6208_Board_VrefPwmStart(BRIDGE_A, devicePrm.vrefPwmPeriod);
01215     L6208_Board_VrefPwmStart(BRIDGE_B, devicePrm.vrefPwmPeriod);
01216   }
01217 }
01218 
01219 /******************************************************//**
01220  * @brief Lock while motor is running
01221  * @retval None
01222  **********************************************************/
01223 void L6208::L6208_WaitWhileActive(void)
01224 {
01225   /* Wait while motor is running */
01226   while (L6208_IsSysFlag(running));
01227 }
01228 
01229 /* ------------------------------------------------------------------------- */
01230 /* Private functions ------------------------------------------------------- */
01231 /* ------------------------------------------------------------------------- */
01232 /******************************************************//**
01233  * @brief Clear the bit/s of flags according to the specified mask
01234  * @param[in] mask flag bit mask
01235  * @retval None
01236  **********************************************************/
01237 inline void L6208::L6208_ClearSysFlag(uint32_t mask)
01238 {
01239   devicePrm.flags &= ~mask;    
01240 }
01241 
01242 /******************************************************//**
01243  * @brief Compute the number of steps at the end of the accereration/deceleration phase
01244  * P = position in steps at the end of the acceleration/deceleration phase
01245  * T = acceleration/deceleration time in seconds
01246  * A =  acceleration/deceleration rate in steps per second per second (steps/sec^2)
01247  * V = peak velocity during acceleration/deceleration phase
01248  * V1 = average velocity during acceleration/deceleration phase
01249  * T = V/A
01250  * V1 = V/2
01251  * P = V1*T
01252  * P = V^2/2A
01253  * @param  accOrDecRate acceleration/deceleration rate in steps per second per second (steps/sec^2)
01254  * @retval end position or 0xFFFFFFFF on error 
01255  **********************************************************/
01256 uint32_t L6208::L6208_ComputeNbAccOrDecSteps(uint16_t accOrDecRate)
01257 {
01258   uint32_t nbAccOrDecSteps;
01259   uint32_t locMaxSpeedSps = (uint32_t)devicePrm.maxSpeedSps;
01260   
01261   if (L6208_IsSysFlag(microstep))
01262   {
01263     switch(devicePrm.uStepInc)
01264     {
01265       case 1:  
01266         locMaxSpeedSps = (uint32_t)devicePrm.maxSpeedSps;
01267         break;
01268       case 2:            
01269         locMaxSpeedSps = ((uint32_t)devicePrm.maxSpeedSps)>>1;
01270         accOrDecRate >>= 1;
01271         break;
01272       case 4:  
01273         locMaxSpeedSps = ((uint32_t)devicePrm.maxSpeedSps)>>2;
01274         accOrDecRate >>= 2;
01275         break;
01276       default:
01277         break;
01278     }
01279   }
01280   else if (L6208_IsSysFlag(halfstep))
01281   {
01282     locMaxSpeedSps = ((uint32_t)devicePrm.maxSpeedSps)<<1;
01283     accOrDecRate <<= 1;
01284   }
01285   
01286   if(accOrDecRate == 0)
01287   {
01288     /* division by 0 error */
01289     return 0xFFFFFFFF;
01290   }
01291   nbAccOrDecSteps = locMaxSpeedSps * locMaxSpeedSps;
01292   nbAccOrDecSteps /= (uint32_t)accOrDecRate;
01293   nbAccOrDecSteps /= 2;
01294 
01295   return nbAccOrDecSteps;
01296 }
01297 
01298 /******************************************************//**
01299  * @brief Compute the acceleration/deceleration speed increment value
01300  * @param[in] newAccOrDecRate acceleration or deceleration value (steps/s^2) greater or equal than 24
01301  * @retval the speed (step/tick) increment value
01302  * LSB = 2^-24 step/tick^2 or 2^-20 microstep/tick^2
01303  * @note return 0 if the rate is too low or if the tick frequency is too small
01304  * or if the device is running in position mode
01305  **********************************************************/
01306 uint16_t L6208::L6208_ConvertAcceDecelRateValue(uint16_t newAccOrDecRate)
01307 {
01308   uint64_t tmp64;
01309   uint32_t tmp32;
01310 
01311   if (((L6208_IsSysFlag(running))&&(L6208_IsSysFlag(positionmode)))||\
01312       (newAccOrDecRate < L6208_MIN_ACC_DEC_RATE))
01313   {
01314     return 0;
01315   } 
01316   /* Compute (tick frequency)^2 */
01317   tmp32 = (uint32_t)L6208_Board_TickGetFreq();
01318   tmp32 *= tmp32;
01319   /* Return 0 if the (tick frequency)^2 is too small */
01320   if ( tmp32 < (uint32_t)newAccOrDecRate )
01321   {
01322     return 0;
01323   } 
01324   /* Compute the decimal number of microstep or step per tick^2 */
01325   /* Decimal part is on 32 bits */
01326   tmp64 = (uint64_t)newAccOrDecRate << 32;
01327   tmp64 /= ((uint64_t)tmp32);
01328 
01329   return (uint16_t)((tmp64 & 0x00000000FFFFFFFF)>>8);
01330 }
01331 
01332 /******************************************************//**
01333  * @brief Compute next position and speed according to the acceleration rate
01334  * @retval None
01335  **********************************************************/
01336 void L6208::L6208_DoAccel(void)
01337 {
01338   /* Increase speed by acceleration rate */
01339   uint32_t locAccelerationSpt2 = (uint32_t)devicePrm.accelerationSpt2;
01340   uint32_t locMinSpeedSpt = devicePrm.minSpeedSpt;
01341   if ((devicePrm.speedSpt + locAccelerationSpt2) < locMinSpeedSpt)
01342   {
01343     devicePrm.speedSpt = locMinSpeedSpt;
01344   }
01345   else
01346   {
01347     devicePrm.speedSpt += locAccelerationSpt2;
01348   }
01349   /* Compute next position */
01350   L6208_DoRun();
01351 }
01352 
01353 /******************************************************//**
01354  * @brief Compute next position and speed according to the deceleration rate
01355  * @retval None
01356  **********************************************************/
01357 void L6208::L6208_DoDecel(void)
01358 {
01359   /* Decrease current speed by deceleration rate */
01360   uint32_t locDecelerationSpt2 = (uint32_t)devicePrm.decelerationSpt2;
01361   uint32_t locMinSpeedSpt = devicePrm.minSpeedSpt;
01362   if((devicePrm.speedSpt - locMinSpeedSpt) > (uint32_t)locDecelerationSpt2)  
01363   {
01364     devicePrm.speedSpt -= (uint32_t)locDecelerationSpt2;
01365   }
01366   else
01367   {
01368     /* Set minimum speed */
01369     devicePrm.speedSpt = locMinSpeedSpt;
01370   }
01371   /* Compute next position */
01372   L6208_DoRun(); 
01373 }
01374 
01375 /******************************************************//**
01376  * @brief Compute next position by adding current speed
01377  * @retval None
01378  **********************************************************/
01379 void L6208::L6208_DoRun(void)
01380 {
01381   devicePrm.ticks += (devicePrm.speedSpt >> 8) & 0x0000FFFF;
01382 }
01383 
01384 /******************************************************//**
01385  * @brief Get number of samples to rescale
01386  * @retval uStepsample2scale the number of micro stepping waveform samples to rescale
01387  **********************************************************/
01388 uint8_t L6208::L6208_GetMicrostepSample2Scale(void)
01389 {
01390   return devicePrm.uStepsample2scale;
01391 }
01392 
01393 /******************************************************//**
01394  * @brief  Initialize the system for position mode motor moving command
01395  *  P = total move distance in steps
01396  *  P1 = steps required to accel from 0 to V
01397  *  P2 = steps required to decel from V to 0
01398  *  V = peak velocity in steps per second (steps/sec)
01399  *  V1 = average velocity during accel or decel*
01400  *  A = required accel rate in steps per second per second (steps/sec2)
01401  *  D = required decel rate in steps per second per second (steps/sec2)
01402  *  T1 = acceleration time in seconds
01403  *  T2 = deceleration time in seconds*
01404  *
01405  *  1) T1 = V / A
01406  *  2) V1 = V / 2
01407  *  3) P1 = V1 T1
01408  *  Substituting 1 and 2 into 3 yields:
01409  *  4) P1 = V2 / 2A
01410  *  In the same manner we have:
01411  *  5) P2 = V2 / 2D
01412  *
01413  *  P1 = PD/(D+A)
01414  *
01415  *  \sa Application Note: AN2044  
01416  * @retval None
01417  **********************************************************/
01418 void L6208::L6208_Indexmodeinit(void)
01419 {
01420   uint32_t tmpVal0;
01421   uint32_t tmpVal1;
01422   uint32_t locAccelSteps;
01423   uint32_t locDecSteps;
01424 
01425   /* calculate the number of steps to get the running speed */
01426   locAccelSteps = L6208_ComputeNbAccOrDecSteps(devicePrm.accelerationSps2);
01427   /* calculate the number of steps to get the motor stopped */
01428   locDecSteps = L6208_ComputeNbAccOrDecSteps(devicePrm.decelerationSps2);
01429   if(( locAccelSteps + locDecSteps ) > devicePrm.positionTarget)
01430   { 
01431     /* Triangular move needed */
01432     /* accelsteps = P1 = PD/(D+A) */
01433     tmpVal0 = devicePrm.positionTarget * devicePrm.decelerationSps2;
01434     tmpVal1 = (uint32_t)devicePrm.decelerationSps2;
01435     tmpVal1 += (uint32_t)devicePrm.accelerationSps2;
01436     locAccelSteps = tmpVal0 / tmpVal1;
01437     devicePrm.positionTarget1 = locAccelSteps;
01438     devicePrm.positionTarget2 = devicePrm.positionTarget1 + 1;
01439     devicePrm.positionTarget3 = devicePrm.positionTarget;
01440     if(devicePrm.positionTarget1 == 0)
01441     {
01442       devicePrm.positionTarget1 = 1;
01443     }
01444   }
01445   else
01446   {  
01447     /* trapezoidal move needed */
01448     /* P1 = V^2/2A */
01449     /* P2 = P - V^2/2D */
01450     devicePrm.positionTarget1 = locAccelSteps;
01451     devicePrm.positionTarget2 = devicePrm.positionTarget - locDecSteps;
01452     devicePrm.positionTarget3 = devicePrm.positionTarget;
01453   }
01454   L6208_SetMotionState(INDEX_ACCEL);  
01455 }
01456 
01457 /******************************************************//**
01458  * @brief Check the bit/s of flags according to the specified mask
01459  * @param[in] mask flag bit mask
01460  * @retval TRUE if the bit of the mask are set
01461  **********************************************************/
01462 inline bool L6208::L6208_IsSysFlag(uint32_t mask)
01463 {
01464   return (bool)((devicePrm.flags & mask) == mask);    
01465 }
01466 
01467 /******************************************************//**
01468  * @brief Stepper driver device step state reset subroutine
01469  * @retval None
01470  **********************************************************/
01471 void L6208::L6208_ResetSteps(void)
01472 {
01473   devicePrm.speedSpt = 0;             // reset the current speed value
01474   devicePrm.ticks = 0;                // reset the current ticks counter value
01475   devicePrm.step = 0;                 // reset the current step counter value
01476   devicePrm.lsbOldTicks = 0;          // reset copy of the previous position (tick)
01477   devicePrm.lsbOldUSteppingTicks = 0; // reset copy of the previous position (tick) ( micro stepping )
01478   devicePrm.lsbTicks = 0;             // reset copy of the current position (tick)
01479   devicePrm.absolutePos = 0;          // reset the absolute motor position in step/microsteps
01480   devicePrm.uStepSample = 0;          // reset the microstepping waveform sample index
01481 }
01482 
01483 /******************************************************//**
01484  * @brief Compute the specified micro stepping waveform sample with the
01485  * current selected torque and pwm period
01486  * @param[in] sampleIndex sample Index
01487  * @retval scaled sample value
01488  **********************************************************/
01489 uint32_t L6208::L6208_ScaleWaveformSample(uint8_t sampleIndex)
01490 {
01491   uint32_t sample;
01492 
01493   sample = (uint32_t)RefMicroTable[sampleIndex];
01494   sample *= devicePrm.vrefPwmPeriod;
01495   sample >>= (uint32_t)L6208_SINE_WAVEFORM_POWER_OF_TWO_MAX_VALUE;
01496   
01497   sample *= (uint32_t)devicePrm.curTorqueScaler; // torque val (%)
01498   sample /= (uint32_t)100;
01499   
01500   return sample;
01501 }
01502 
01503 /******************************************************//**
01504  * @brief Compute the micro stepping waveform sample table samples with the
01505  * current selected torque and pwm period
01506  * @retval None
01507  **********************************************************/
01508 void L6208::L6208_ScaleWaveformTable(void)
01509 {
01510   uint8_t index;
01511   for(index=0; index<=L6208_USTEPS_PER_QUARTER_PERIOD; index++)
01512   { 
01513     /* Calculate the scaled sample and save its value into the waveform to update table */
01514     updatedMicroTable[index] = (uint16_t)L6208_ScaleWaveformSample(index);
01515   }
01516 }
01517 
01518 /******************************************************//**
01519  * @brief  Set the parameters of the device to values of the structure pointed
01520  * by pInitDevicePrm. Set GPIO according to these values.
01521  * @param pInitDevicePrm pointer onto the structure containing values to
01522  * initialize the device parameters.
01523  * @retval None
01524  **********************************************************/
01525 void L6208::L6208_SetDeviceParamsToGivenValues(l6208_init_t* pInitDevicePrm)
01526 {
01527   memset(&devicePrm, 0, sizeof(devicePrm));
01528   L6208_SetAcceleration(pInitDevicePrm->accelerationSps2);
01529   L6208_SetDeceleration(pInitDevicePrm->decelerationSps2);
01530   L6208_SetMaxSpeed(pInitDevicePrm->maxSpeedSps);
01531   L6208_SetMinSpeed(L6208_MIN_SPEED);
01532   devicePrm.accelTorque = pInitDevicePrm->accelTorque;
01533   devicePrm.decelTorque = pInitDevicePrm->decelTorque;
01534   devicePrm.runTorque = pInitDevicePrm->runTorque;
01535   devicePrm.holdTorque = pInitDevicePrm->holdTorque;
01536   /* Only once acceleration, deceleration, min speed and max speed have been */
01537   /* initialized, set the step mode */
01538   devicePrm.stepMode = pInitDevicePrm->stepMode;
01539   L6208_SetDecayMode(pInitDevicePrm->decayMode);
01540   devicePrm.moveDwellTime = pInitDevicePrm->moveDwellTime;
01541   if (L6208_CONF_PARAM_AUTO_HIZ_STOP)
01542   {
01543     L6208_SetSysFlag(pInitDevicePrm->autoHiZstop);
01544   }
01545   devicePrm.vrefPwmFreq = pInitDevicePrm->vrefPwmFreq;
01546   devicePrm.vrefPwmPeriod = (uint16_t)((1000000<<8)/pInitDevicePrm->vrefPwmFreq);
01547   /* Initialize current stepper state machine index  */
01548   L6208_SetMotionState(INACTIVE);
01549 }
01550 
01551 /******************************************************//**
01552  * @brief  Set the parameters of the device to predefined values
01553  * Set GPIO according to these values
01554  * from l6208_target_config.h
01555  * @retval None
01556  **********************************************************/
01557 void L6208::L6208_SetDeviceParamsToPredefinedValues(void)
01558 {
01559   memset(&devicePrm, 0, sizeof(devicePrm));
01560   L6208_SetAcceleration(L6208_CONF_PARAM_ACC_RATE);
01561   L6208_SetDeceleration(L6208_CONF_PARAM_DEC_RATE);
01562   L6208_SetMaxSpeed(L6208_CONF_PARAM_RUNNING_SPEED);
01563   L6208_SetMinSpeed(L6208_MIN_SPEED);
01564   devicePrm.accelTorque = L6208_CONF_PARAM_ACC_CURRENT;
01565   devicePrm.decelTorque = L6208_CONF_PARAM_DEC_CURRENT;
01566   devicePrm.runTorque = L6208_CONF_PARAM_RUNNING_CURRENT;
01567   devicePrm.holdTorque = L6208_CONF_PARAM_HOLDING_CURRENT;
01568   /* Only once acceleration, deceleration, min speed and max speed have been */
01569   /* initialized, set the step mode */
01570   devicePrm.stepMode = (motorStepMode_t) L6208_CONF_PARAM_STEP_MODE;
01571   L6208_SetDecayMode(L6208_CONF_PARAM_DECAY_MODE);
01572   devicePrm.moveDwellTime = L6208_CONF_PARAM_DWELL_TIME;
01573   if (L6208_CONF_PARAM_AUTO_HIZ_STOP) 
01574   {
01575     L6208_SetSysFlag(HiZstop);
01576   }
01577   devicePrm.vrefPwmFreq = L6208_CONF_VREF_PWM_FREQUENCY;
01578   devicePrm.vrefPwmPeriod = (uint16_t)((1000000<<8)/L6208_CONF_VREF_PWM_FREQUENCY);
01579   /* Initialize current stepper state machine index  */
01580   L6208_SetMotionState(INACTIVE);
01581 }
01582 
01583 /******************************************************//**
01584  * @brief Set the number of micro stepping waveform samples to rescale
01585  * @param[in] value number of micro stepping waveform samples 
01586  * @retval None
01587  **********************************************************/
01588 void L6208::L6208_SetMicrostepSample2Scale(uint8_t value)
01589 {
01590   if(value > L6208_USTEPS_PER_QUARTER_PERIOD)
01591   {
01592     value = L6208_USTEPS_PER_QUARTER_PERIOD;  // clamp to maximum number of samples per period/4
01593   }
01594   devicePrm.uStepsample2scale = value;    
01595 }
01596 
01597 /******************************************************//**
01598  * @brief Set the number of micro stepping waveform samples to update into scanning
01599  * @param[in] value number of micro stepping waveform samples 
01600  * @retval None
01601  **********************************************************/
01602 void L6208::L6208_SetMicrostepSample2Update(uint8_t value)
01603 {
01604   // clamp to maximum number of samples per period/4
01605   if(value > L6208_USTEPS_PER_QUARTER_PERIOD)
01606   {
01607     value = L6208_USTEPS_PER_QUARTER_PERIOD;  
01608   }
01609   // copy the stepper acceleration rate
01610   devicePrm.uStepsample2update = value;    
01611 }
01612 
01613 /******************************************************//**
01614  * @brief Set the stepper state machine index
01615  * @param[in] newMotionState
01616  * @retval None
01617  **********************************************************/
01618 void L6208::L6208_SetMotionState(motorState_t newMotionState)
01619 {
01620   // sets the new stepper state machine index
01621   devicePrm.motionState = newMotionState;    
01622 }
01623 
01624 /******************************************************//**
01625  * @brief Set the user selected speed in step/tick
01626  * @param[in] newSpeed speed value (step/s)
01627  * @param[in] pSpeed pointer to the selected speed field
01628  * @retval return FALSE if the speed is too low or too high
01629  * or if the device is running in position mode, else TRUE
01630  **********************************************************/
01631 bool L6208::L6208_SetSpeed(uint16_t newSpeed, uint32_t volatile *pSpeed)
01632 {
01633   uint64_t tmp64;
01634   uint32_t tmp32;
01635 
01636   if (((L6208_IsSysFlag(running))&&(L6208_IsSysFlag(positionmode)))||\
01637       (newSpeed < L6208_MIN_SPEED))
01638   {
01639     return FALSE;
01640   }
01641   tmp32 = (uint32_t)L6208_Board_TickGetFreq();
01642   if (tmp32 < newSpeed)
01643   {
01644     return FALSE;
01645   }
01646   /* Compute the decimal number of microstep or step per tick */
01647   /* Decimal part is on 32 bits */
01648   tmp64 = (uint64_t)newSpeed << 32;
01649   tmp64 /= ((uint64_t)tmp32);
01650   /* set the running constant speed value (step/tick) */
01651   *pSpeed = (uint32_t)((tmp64 & 0x00000000FFFFFFFF)>>8);
01652   
01653   return TRUE;
01654 }
01655 
01656 /******************************************************//**
01657  * @brief Set the bit/s of flags according to the specified mask
01658  * @param[in] mask flag bit mask
01659  * @retval None
01660  **********************************************************/
01661 inline void L6208::L6208_SetSysFlag(uint32_t mask)
01662 {
01663   devicePrm.flags |= mask;    
01664 }
01665 
01666 /******************************************************//**
01667  * @brief Stepper motor start command
01668  * @retval true on correct command execution
01669  **********************************************************/
01670 bool L6208::L6208_StartMovement(void)
01671 {
01672   uint32_t tmp;
01673   if (L6208_IsSysFlag(running))
01674   {
01675     /* Motor is already running ==> quit */
01676     return FALSE;    
01677   }
01678   if (!L6208_IsSysFlag(positionmode))
01679   {
01680     /* Set the VREFA and VREFB to the selected acc. torque */
01681     L6208_VectorCalc(devicePrm.accelTorque);
01682     
01683     /* If the speed control mode is selected */
01684     /* setup the motor acceleration for velocity mode driving */
01685     L6208_SetMotionState(ACCELERATING);  
01686   }
01687   else
01688   {  
01689     /* if position control mode is selected, reset the current step counter  */
01690     devicePrm.step = 0;    
01691     if(devicePrm.uStepSample > 31)
01692     {
01693       /* check the micro stepping waveform sample index */
01694       devicePrm.uStepSample = 0;
01695     }
01696     /* Set the position dwelling wait time */
01697     /* compute number of ticks per millisecond */
01698     tmp = (uint32_t)L6208_Board_TickGetFreq() / 1000;
01699     /* Compute the dwelling time in ticks => dwellCounter (ticks) */
01700     devicePrm.dwellCounter = tmp * (uint32_t)devicePrm.moveDwellTime;
01701     if (devicePrm.positionTarget == 0)
01702     {
01703       /* if the position to go is 0 (no move) */
01704       /* Set the deceleration torque */
01705       L6208_VectorCalc(devicePrm.decelTorque); 
01706       /* Set the dwelling delay state index */
01707       L6208_SetMotionState(INDEX_DWELL);       
01708     }
01709     else
01710     {
01711       /* Set the VREFA and VREFB to the selected acc. torque */
01712       L6208_VectorCalc(devicePrm.accelTorque);
01713       /* go to the selected position */
01714       L6208_Indexmodeinit();
01715       L6208_SetMotionState(INDEX_ACCEL);
01716     }
01717   }
01718   /* Sets the motor running flag */
01719   L6208_SetSysFlag(running);
01720   /* Start the VREFA and VREFB PWMs */
01721   L6208_Board_VrefPwmStart(BRIDGE_A, devicePrm.vrefPwmPeriod);
01722   L6208_Board_VrefPwmStart(BRIDGE_B, devicePrm.vrefPwmPeriod);
01723   if (!(L6208_IsSysFlag(EN_A_set)))
01724   {
01725     /* Enable power bridges */
01726     L6208_Enable();
01727   }
01728   /* Start the tick */
01729   L6208_Board_TickStart(L6208::tickFreq);
01730   
01731   return TRUE;
01732 }
01733 
01734 /******************************************************//**
01735  * @brief Update the micro stepping waveform samples table with the
01736  * values previously scaled with current selected torque and tick period
01737  * @retval None
01738  **********************************************************/
01739 void L6208::L6208_UpdateScanWaveformTable(void)
01740 {
01741   uint8_t index;
01742 
01743   for(index=0; index<=L6208_USTEPS_PER_QUARTER_PERIOD; index++)
01744   {
01745     microTable1[index] = updatedMicroTable[index];
01746     microTable1[L6208_USTEPS_PER_QUARTER_PERIOD*2 - index] = microTable1[index];
01747     microTable1[index + L6208_USTEPS_PER_QUARTER_PERIOD*2] = updatedMicroTable[index];
01748   }
01749   /* clear the number of samples to update */
01750   L6208_SetMicrostepSample2Update(0); 
01751 }
01752 
01753 /******************************************************//**
01754  * @brief Check if there are waveform samples to rescale and if so, perform the rescaling
01755  * @retval None
01756  **********************************************************/
01757 void L6208::L6208_UstepWaveformHandling(void)
01758 {
01759   /* micro stepper waveform samples rescaling ... and updating */
01760   uint8_t nbSamplesToRescale = L6208_GetMicrostepSample2Scale();
01761   if(nbSamplesToRescale > 0)
01762   { 
01763     /* Current torque value has been changed, so recalculate the waveform table */
01764     L6208_ScaleWaveformTable();
01765     
01766     /* Set the number of samples to update */
01767     L6208_SetMicrostepSample2Update(L6208_USTEPS_PER_QUARTER_PERIOD);
01768 
01769     /* Reset the number of samples to rescaled afer rescaling */
01770     L6208_SetMicrostepSample2Scale(0);
01771   }
01772 }
01773 
01774 /******************************************************//**
01775  * @brief Set the current torque value (Vref)
01776  * @param[in] newTorque Selected torque value
01777  * @retval always TRUE
01778  **********************************************************/
01779 bool L6208::L6208_VectorCalc(uint8_t newTorque)
01780 {
01781   /* save current selected torque value */
01782   devicePrm.curTorqueScaler = (uint16_t)newTorque;
01783 
01784   if(!L6208_IsSysFlag(microstep))
01785   {
01786     /* full/half step mode or the motor is not running */
01787     /* set the PWM duty cycle according to the current torque value (%). */
01788     /* The TON value will be calculated inside the TIMx_PWM_duty_setup f(). */
01789     L6208_VrefPwmComputePulseWidth(BRIDGE_A, devicePrm.curTorqueScaler, TRUE);
01790     L6208_VrefPwmComputePulseWidth(BRIDGE_B, devicePrm.curTorqueScaler, TRUE);
01791     devicePrm.vRefAVal = devicePrm.curTorqueScaler; // save current VREFA value
01792     devicePrm.vRefBVal = devicePrm.curTorqueScaler; // save current VREFB value
01793   }
01794   else
01795   { 
01796     /* microstep mode */
01797     if(L6208_IsSysFlag(running))
01798     {
01799       /* set the number of waveform sample to rescale according current selected */
01800       /* torque value */
01801       L6208_SetMicrostepSample2Scale(L6208_USTEPS_PER_QUARTER_PERIOD);
01802     }
01803     else
01804     { 
01805       /* micro stepping mode motor stopped */
01806       L6208_ScaleWaveformTable();
01807       L6208_UpdateScanWaveformTable();
01808       /* Set the VREF timer PWM TON to update VREFA and VREFB */
01809       L6208_VrefPwmComputePulseWidth(BRIDGE_A, pMicroTable2[devicePrm.uStepSample], FALSE);      
01810       L6208_VrefPwmComputePulseWidth(BRIDGE_B, microTable1[devicePrm.uStepSample], FALSE);
01811     }
01812   }
01813   return TRUE;
01814 }
01815 
01816 /******************************************************//**
01817  * @brief Compute the pulse width of VREFA or VREFB PWM
01818  * @param[in] bridgeId
01819  *            0 for BRIDGE_A
01820  *            1 for BRIDGE_B
01821  * @param[in] value pulse length in 1/256th of microsecond
01822  * or PWM duty cycle: 0 - 100 %
01823  * @param[in] valueIsPwmDutyCycle must be TRUE if value is a PWM duty cycle
01824  * @retval FALSE if wrong timer handle is used, else TRUE
01825  **********************************************************/
01826 bool L6208::L6208_VrefPwmComputePulseWidth(uint8_t bridgeId, uint16_t value, bool valueIsPwmDutyCycle)
01827 {
01828   if(valueIsPwmDutyCycle)
01829   {
01830     if (value > 100)
01831     {
01832       value = 100;
01833     }
01834     value = (uint16_t)(((uint32_t)devicePrm.vrefPwmPeriod * (uint32_t)value) / 100); 
01835   }
01836   if (bridgeId == 0)
01837   {
01838     devicePrm.vrefPwmPulseWidthTargetA = value;
01839     devicePrm.vrefPwmPulseWidthToBeGeneratedA = 0;
01840   } 
01841   else if (bridgeId == 1)
01842   {
01843     devicePrm.vrefPwmPulseWidthTargetB = value;
01844     devicePrm.vrefPwmPulseWidthToBeGeneratedB = 0;
01845   }
01846   else
01847   {
01848     return FALSE;
01849   }
01850   return TRUE;
01851 }
01852 
01853 /******************************************************//**
01854  * @brief Update the pulse width of VREFA or VREFB PWM
01855  * @param None
01856  * @retval None
01857  **********************************************************/
01858 void L6208::L6208_VrefPwmUpdatePulseWidth(void)
01859 {
01860   uint16_t pulseWidthUs;
01861   
01862   devicePrm.vrefPwmPulseWidthToBeGeneratedA += devicePrm.vrefPwmPulseWidthTargetA;
01863   pulseWidthUs = devicePrm.vrefPwmPulseWidthToBeGeneratedA>>8;
01864   if (pulseWidthUs!=0)
01865   {
01866     L6208_Board_VrefPwmSetPulseWidthA(pulseWidthUs);
01867     devicePrm.vrefPwmPulseWidthToBeGeneratedA -= (pulseWidthUs<<8);
01868   }
01869   else
01870   {
01871     L6208_Board_VrefPwmSetPulseWidthA(0);
01872   }
01873   
01874   devicePrm.vrefPwmPulseWidthToBeGeneratedB += devicePrm.vrefPwmPulseWidthTargetB;
01875   pulseWidthUs = devicePrm.vrefPwmPulseWidthToBeGeneratedB>>8;
01876   if (pulseWidthUs!=0)
01877   {
01878     L6208_Board_VrefPwmSetPulseWidthB(pulseWidthUs);
01879     devicePrm.vrefPwmPulseWidthToBeGeneratedB -= (pulseWidthUs<<8);
01880   }
01881   else
01882   {
01883     L6208_Board_VrefPwmSetPulseWidthB(0);
01884   }
01885 }
01886 
01887 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/