Added ST_INTERFACES library.

Dependencies:   ST_INTERFACES

Fork of X-NUCLEO-IHM05A1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers l6208_class.cpp Source File

l6208_class.cpp

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