Library to handle the X_NUCLEO_IHM02A1 Motor Control Expansion Board based on the L6470 component.
Dependencies: X_NUCLEO_COMMON ST_INTERFACES
Dependents: HelloWorld_IHM02A1 ConcorsoFinal HelloWorld_IHM02A1_mbedOS HelloWorld_IHM02A1-Serialinterpreter ... more
Fork of X_NUCLEO_IHM02A1 by
L6470.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file l6470_class.cpp 00004 * @date 01/10/2014 12:00:00 00005 * @brief This file provides set of firmware functions to manage the 00006 * L6470. 00007 ****************************************************************************** 00008 * 00009 * COPYRIGHT(c) 2014 STMicroelectronics 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00025 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00028 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00030 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 * 00033 ****************************************************************************** 00034 */ 00035 00036 00037 /* Generated with STM32CubeTOO -----------------------------------------------*/ 00038 00039 00040 /* Revision ------------------------------------------------------------------*/ 00041 /* 00042 Repository: http://svn.x-nucleodev.codex.cro.st.com/svnroot/X-NucleoDev 00043 Branch/Trunk/Tag: trunk 00044 Based on: X-CUBE-SPN2/trunk/Drivers/BSP/Components/L6470/L6470.c 00045 Revision: 0 00046 */ 00047 00048 00049 /* Includes ------------------------------------------------------------------*/ 00050 00051 #include "L6470.h" 00052 00053 00054 /* Variables -----------------------------------------------------------------*/ 00055 00056 /* Number of instantiated devices on an expansion board. */ 00057 uint8_t L6470::number_of_devices = 0; 00058 00059 /* SPI Transmission for Daisy-Chain Configuration. */ 00060 eFlagStatus_t L6470::L6470_DaisyChain_HalfPrepared; 00061 sL6470_AppCmdPkg_t L6470::L6470_AppCmdPkg[L6470DAISYCHAINSIZE]; 00062 uint8_t L6470::L6470_DaisyChainSpiTxStruct[L6470MAXSPICMDBYTESIZE][L6470DAISYCHAINSIZE]; 00063 uint8_t L6470::L6470_DaisyChainSpiRxStruct[L6470MAXSPICMDBYTESIZE][L6470DAISYCHAINSIZE]; 00064 00065 /** 00066 * @brief Array whose elements are a structure in which store information about 00067 * the L6470 Registers (the address, the names, the length in bits, the 00068 * reset value) 00069 */ 00070 const sL6470_Register_t L6470::_L6470_Register[L6470REGIDSIZE] = { 00071 {0x01 , "ABS_POS", 22, 3, 0x000000}, //!< Current position 00072 {0x02 , "EL_POS", 9, 2, 0x000}, //!< Electrical position 00073 {0x03 , "MARK", 22, 3, 0x000000}, //!< Mark position 00074 {0x04 , "SPEED", 20, 3, 0x0000}, //!< Current speed 00075 {0x05 , "ACC", 12, 2, 0x08A}, //!< Acceleration 00076 {0x06 , "DEC", 12, 2, 0x08A}, //!< Deceleration 00077 {0x07 , "MAX_SPEED", 10, 2, 0x041}, //!< Maximum speed 00078 {0x08 , "MIN_SPEED", 13, 2, 0x000}, //!< Minimum speed 00079 {0x15 , "FS_SPD", 10, 2, 0x027}, //!< Full-step speed 00080 {0x09 , "KVAL_HOLD", 8, 1, 0x29}, //!< Holding KVAL 00081 {0x0A , "KVAL_RUN", 8, 1, 0x29}, //!< Constant speed KVAL 00082 {0x0B , "KVAL_ACC", 8, 1, 0x29}, //!< Acceleration starting KVAL 00083 {0x0C , "KVAL_DEC", 8, 1, 0x29}, //!< Deceleration starting KVAL 00084 {0x0D , "INT_SPEED", 14, 2, 0x0408}, //!< Intersect speed 00085 {0x0E , "ST_SLP", 8, 1, 0x19}, //!< Start slope 00086 {0x0F , "FN_SLP_ACC", 8, 1, 0x29}, //!< Acceleration final slope 00087 {0x10 , "FN_SLP_DEC", 8, 1, 0x29}, //!< Deceleration final slope 00088 {0x11 , "K_THERM", 4, 1, 0x0}, //!< Thermal compensation factor 00089 {0x12 , "ADC_OUT", 5, 1, 0x00}, //!< ADC output, (the reset value is according to startup conditions) 00090 {0x13 , "OCD_TH", 4, 1, 0x8}, //!< OCD threshold 00091 {0x14 , "STALL_TH", 7, 1, 0x40}, //!< STALL threshold 00092 {0x16 , "STEP_MODE", 8, 1, 0x7}, //!< Step mode 00093 {0x17 , "ALARM_EN", 8, 1, 0xFF}, //!< Alarm enable 00094 {0x18 , "CONFIG", 16, 2, 0x2E88}, //!< IC configuration 00095 {0x19 , "STATUS", 16, 2, 0x0000} //!< Status, (the reset value is according to startup conditions) 00096 }; 00097 00098 /** 00099 * @brief Array whose elements are a structure in which store information about 00100 * the L6470 Application Commands (the mnemonic name, the number of 00101 * needed parameters, the related funtion to call) 00102 */ 00103 const sL6470_ApplicationCommand_t L6470::_L6470_ApplicationCommand[L6470APPCMDIDSIZE] = { 00104 {"NOP", 0x00, 0}, 00105 {"SETPARAM", 0x00, 2}, 00106 {"GETPARAM", 0x20, 1}, 00107 {"RUN", 0x50, 2}, 00108 {"STEPCLOCK", 0x58, 1}, 00109 {"MOVE", 0x40, 2}, 00110 {"GOTO", 0x60, 1}, 00111 {"GOTO_DIR", 0x68, 2}, 00112 {"GOUNTIL", 0x82, 3}, 00113 {"RELEASESW", 0x92, 2}, 00114 {"GOHOME", 0x70, 0}, 00115 {"GOMARK", 0x78, 0}, 00116 {"RESETPOS", 0xD8, 0}, 00117 {"RESETDEVICE", 0xC0, 0}, 00118 {"SOFTSTOP", 0xB0, 0}, 00119 {"HARDSTOP", 0xB8, 0}, 00120 {"SOFTHIZ", 0xA0, 0}, 00121 {"HARDHIZ", 0xA8, 0}, 00122 {"GETSTATUS", 0xD0, 0} 00123 }; 00124 00125 /** 00126 * @brief The mnemonic names for the L6470 direction 00127 */ 00128 const sL6470_Direction_t L6470::_L6470_Direction[L6470DIRIDSIZE] = { 00129 {"REV", 0x00}, //!< Reverse direction 00130 {"FWD", 0x01} //!< Forward direction 00131 }; 00132 00133 /** 00134 * @brief Action taken about ABS_POS register 00135 */ 00136 const sL6470_ACT_t L6470::_L6470_ACT[L6470ACTIDSIZE] = { 00137 {"RST", 0x00}, //!< ABS_POS register is reset 00138 {"CPY", 0x01} //!< ABS_POS register value is copied into the MARK register 00139 }; 00140 00141 /* End of L6470_Private_Constants */ 00142 00143 /** 00144 * @defgroup L6470_Private_Variables 00145 * @brief L6470 Private Variables. 00146 * @{ 00147 */ 00148 00149 /* End of L6470_Private_Variables */ 00150 00151 00152 /** 00153 * @addtogroup L6470_Private_Functions 00154 * @{ 00155 */ 00156 00157 00158 /* Methods -------------------------------------------------------------------*/ 00159 00160 /** 00161 * @brief Reset the structure used to store the identifier of the L6470 00162 * application command and its the needed parameters. 00163 * @param pL6470_AppCmdPkg The structure to be reset. 00164 */ 00165 void L6470::L6470_ResetAppCmdPkg(sL6470_AppCmdPkg_t* pL6470_AppCmdPkg) 00166 { 00167 uint8_t id; 00168 00169 for(id=0; id<L6470DAISYCHAINSIZE; id++) 00170 { 00171 (pL6470_AppCmdPkg+id)->L6470_AppCmdId=(eL6470_AppCmdId_t)0; 00172 (pL6470_AppCmdPkg+id)->p1=0; 00173 (pL6470_AppCmdPkg+id)->p2=0; 00174 (pL6470_AppCmdPkg+id)->p3=0; 00175 } 00176 } 00177 00178 /** 00179 * @brief Fill the structure used to store the identifier of the L6470 00180 * application command and its the needed parameters. 00181 * @param L6470_Id The identifier of the L6470 target inside the daisy chain. 00182 * @param pL6470_AppCmdPkg The structure to be filled. 00183 * @param L6470_AppCmdId The identifier of the L6470 application command to be sent. 00184 * @param p1 The 1st parameter (if it is not needed it will be not considered). 00185 * @param p2 The 2nd parameter (if it is not needed it will be not considered). 00186 * @param p3 The 3rd parameter (if it is not needed it will be not considered). 00187 */ 00188 void L6470::L6470_FillAppCmdPkg(sL6470_AppCmdPkg_t* pL6470_AppCmdPkg, eL6470_AppCmdId_t L6470_AppCmdId, uint32_t p1, uint32_t p2, uint32_t p3) 00189 { 00190 (pL6470_AppCmdPkg+L6470_Id)->L6470_AppCmdId = L6470_AppCmdId; 00191 (pL6470_AppCmdPkg+L6470_Id)->p1 = p1; 00192 (pL6470_AppCmdPkg+L6470_Id)->p2 = p2; 00193 (pL6470_AppCmdPkg+L6470_Id)->p3 = p3; 00194 } 00195 00196 /** 00197 * @brief This function will fill the column of the L6470_AppCmdPkg related 00198 * the L6470 to be addressed inside the daisy chain. 00199 * 00200 * @param L6470_Id The identifier of the L6470 target inside the daisy chain. 00201 * @param pL6470_AppCmdPkg Pointer to the sL6470_AppCmdPkg_t to be filled. 00202 * @param L6470_AppCmdId The identifier of the L6470 application command to be sent. 00203 * @param p1 The 1st parameter (if it is not needed it will be not considered). 00204 * @param p2 The 2nd parameter (if it is not needed it will be not considered). 00205 * @param p3 The 3rd parameter (if it is not needed it will be not considered). 00206 */ 00207 void L6470::L6470_PrepareAppCmdPkg(sL6470_AppCmdPkg_t* pL6470_AppCmdPkg, eL6470_AppCmdId_t L6470_AppCmdId, uint32_t p1, uint32_t p2, uint32_t p3) 00208 { 00209 if(!L6470_DaisyChain_HalfPrepared) 00210 { 00211 L6470_DaisyChain_HalfPrepared = ONE_F; /* To avoid to delete the previous entered command */ 00212 L6470_ResetAppCmdPkg(pL6470_AppCmdPkg); 00213 } 00214 00215 L6470_FillAppCmdPkg(pL6470_AppCmdPkg, L6470_AppCmdId, p1, p2, p3); 00216 } 00217 00218 /** 00219 * @brief This function will translate the data inside the L6470_AppCmdPkg into 00220 * the right data to be sent via SPI to the L6470 daisy chain. 00221 * 00222 * @param pL6470_AppCmdPkg Pointer to the sL6470_AppCmdPkg_t to be filled. 00223 * @param pL6470_DaisyChainSpiTxStruct Pointer to the structure used by SPI to send the commands. 00224 */ 00225 void L6470::L6470_PrepareDaisyChainCommand(sL6470_AppCmdPkg_t* pL6470_AppCmdPkg, uint8_t* pL6470_DaisyChainSpiTxStruct) 00226 { 00227 uint8_t PkgId; 00228 uint8_t PARAMLengthBytes; /* The number of bytes related to the numeric value for the addressed register */ 00229 uint8_t spibyte; 00230 00231 /* Reset the structure used to send the command to the L6470 Daisy Chain through the SPI */ 00232 uint8_t i = 0; 00233 for(spibyte=0;spibyte<L6470MAXSPICMDBYTESIZE;spibyte++) 00234 for(PkgId=0; PkgId<L6470DAISYCHAINSIZE; PkgId++) 00235 *(pL6470_DaisyChainSpiTxStruct+(i++)) = 0x00; 00236 00237 for(PkgId=0; PkgId<L6470DAISYCHAINSIZE; PkgId++) 00238 { 00239 /* Build the 1st bytes to transmit with the binary code of the command */ 00240 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) = (L6470_ApplicationCommand[(pL6470_AppCmdPkg+PkgId)->L6470_AppCmdId].BinaryCode); 00241 00242 /* Perform the related L6470_AppCmdId */ 00243 switch((pL6470_AppCmdPkg+PkgId)->L6470_AppCmdId) 00244 { 00245 case L6470_NOP_ID: 00246 break; 00247 case L6470_SETPARAM_ID: 00248 /* Build the 1st bytes to transmit (PARAM) */ 00249 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Register[((pL6470_AppCmdPkg+PkgId)->p1)].Address); 00250 00251 /* The length, in byte, of this register (PARAM) is... */ 00252 PARAMLengthBytes = L6470_Register[((pL6470_AppCmdPkg+PkgId)->p1)].LengthByte; 00253 00254 /* Build the others bytes to transmit (VALUE) */ 00255 for (spibyte=1; spibyte<(PARAMLengthBytes+1); spibyte++) 00256 { 00257 *(pL6470_DaisyChainSpiTxStruct+((spibyte*L6470DAISYCHAINSIZE)+PkgId)) = (uint8_t)(((pL6470_AppCmdPkg+PkgId)->p2) >> (8*(PARAMLengthBytes-spibyte))); 00258 } 00259 break; 00260 case L6470_GETPARAM_ID: 00261 /* Build the 1st bytes to transmit (PARAM) */ 00262 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Register[((pL6470_AppCmdPkg+PkgId)->p1)].Address); 00263 break; 00264 case L6470_RUN_ID: 00265 /* Build the 1st bytes to transmit (DIR) */ 00266 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Direction[((pL6470_AppCmdPkg+PkgId)->p1)].BinaryCode); 00267 00268 /* Build the others bytes to transmit (SPD) */ 00269 for (spibyte=1; spibyte<(3+1); spibyte++) 00270 { 00271 *(pL6470_DaisyChainSpiTxStruct+((spibyte*L6470DAISYCHAINSIZE)+PkgId)) = (uint8_t)(((pL6470_AppCmdPkg+PkgId)->p2) >> (8*(3-spibyte))); 00272 } 00273 break; 00274 case L6470_STEPCLOCK_ID: 00275 /* Build the 1st bytes to transmit (DIR) */ 00276 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Direction[((pL6470_AppCmdPkg+PkgId)->p1)].BinaryCode); 00277 break; 00278 case L6470_MOVE_ID: 00279 /* Build the 1st bytes to transmit (DIR) */ 00280 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Direction[((pL6470_AppCmdPkg+PkgId)->p1)].BinaryCode); 00281 00282 /* Build the others bytes to transmit (N_STEP) */ 00283 for (spibyte=1; spibyte<(3+1); spibyte++) 00284 { 00285 *(pL6470_DaisyChainSpiTxStruct+((spibyte*L6470DAISYCHAINSIZE)+PkgId)) = (uint8_t)(((pL6470_AppCmdPkg+PkgId)->p2) >> (8*(3-spibyte))); 00286 } 00287 break; 00288 case L6470_GOTO_ID: 00289 /* Build the others bytes to transmit (ABS_POS) */ 00290 for (spibyte=1; spibyte<(3+1); spibyte++) 00291 { 00292 *(pL6470_DaisyChainSpiTxStruct+((spibyte*L6470DAISYCHAINSIZE)+PkgId)) = (uint8_t)(((pL6470_AppCmdPkg+PkgId)->p1) >> (8*(3-spibyte))); 00293 } 00294 break; 00295 case L6470_GOTODIR_ID: 00296 /* Build the 1st bytes to transmit (DIR) */ 00297 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Direction[((pL6470_AppCmdPkg+PkgId)->p1)].BinaryCode); 00298 00299 /* Build the others bytes to transmit (ABS_POS) */ 00300 for (spibyte=1; spibyte<(3+1); spibyte++) 00301 { 00302 *(pL6470_DaisyChainSpiTxStruct+((spibyte*L6470DAISYCHAINSIZE)+PkgId)) = (uint8_t)(((pL6470_AppCmdPkg+PkgId)->p2) >> (8*(3-spibyte))); 00303 } 00304 break; 00305 case L6470_GOUNTIL_ID: 00306 /* Build the 1st bytes to transmit (ACT) */ 00307 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= ((L6470_ACT[((pL6470_AppCmdPkg+PkgId)->p1)].BinaryCode)<<3); 00308 /* Build the 1st bytes to transmit (DIR) */ 00309 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Direction[((pL6470_AppCmdPkg+PkgId)->p2)].BinaryCode); 00310 00311 /* Build the others bytes to transmit (SPD) */ 00312 for (spibyte=1; spibyte<(3+1); spibyte++) 00313 { 00314 *(pL6470_DaisyChainSpiTxStruct+((spibyte*L6470DAISYCHAINSIZE)+PkgId)) = (uint8_t)(((pL6470_AppCmdPkg+PkgId)->p3) >> (8*(3-spibyte))); 00315 } 00316 break; 00317 case L6470_RELEASESW_ID: 00318 /* Build the 1st bytes to transmit (ACT) */ 00319 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= ((L6470_ACT[((pL6470_AppCmdPkg+PkgId)->p1)].BinaryCode)<<3); 00320 /* Build the 1st bytes to transmit (DIR) */ 00321 *(pL6470_DaisyChainSpiTxStruct+((0*L6470DAISYCHAINSIZE)+PkgId)) |= (L6470_Direction[((pL6470_AppCmdPkg+PkgId)->p2)].BinaryCode); 00322 break; 00323 case L6470_GOHOME_ID: 00324 break; 00325 case L6470_GOMARK_ID: 00326 break; 00327 case L6470_RESETPOS_ID: 00328 break; 00329 case L6470_RESETDEVICE_ID: 00330 break; 00331 case L6470_SOFTSTOP_ID: 00332 break; 00333 case L6470_HARDSTOP_ID: 00334 break; 00335 case L6470_SOFTHIZ_ID: 00336 break; 00337 case L6470_HARDHIZ_ID: 00338 break; 00339 case L6470_GETSTATUS_ID: 00340 break; 00341 } 00342 } 00343 } 00344 00345 /* End of L6470_Private_Functions */ 00346 00347 /** 00348 * @addtogroup L6470_Exported_Functions 00349 * @{ 00350 */ 00351 00352 /** 00353 * @addtogroup L6470_Conversion_Functions 00354 * @brief The following functions act just on one driver inside the L6470 00355 * daisy chain. The command is immediately sent. 00356 * @{ 00357 */ 00358 00359 /** 00360 * @brief Convert the absolute position as 2's complement format into the signed number. 00361 * 00362 * @param AbsPos The absolute position in the range from [-(2^21)] to [+(2^21)-1]. 00363 * @retval Position The position as signed number. 00364 */ 00365 int32_t L6470::L6470_AbsPos_2_Position(uint32_t AbsPos) 00366 { 00367 if (AbsPos > L6470_MAX_POSITION) 00368 return (AbsPos - (L6470_POSITION_RANGE + 1)); 00369 else 00370 return AbsPos; 00371 } 00372 00373 /** 00374 * @brief Convert the position as signed number into absolute position as 2's complement format. 00375 * 00376 * @param Position The position as signed number. 00377 * @retval AbsPos The absolute position in the range from [-(2^21)] to [+(2^21)-1]. 00378 */ 00379 uint32_t L6470::L6470_Position_2_AbsPos(int32_t Position) 00380 { 00381 if ((Position >= 0) && (Position <= L6470_MAX_POSITION)) 00382 return Position; 00383 else 00384 { 00385 if ((Position >= L6470_MIN_POSITION) && (Position < 0)) 00386 return (Position + (L6470_POSITION_RANGE + 1)); 00387 else 00388 return (L6470_POSITION_RANGE + 1); // OVF 00389 } 00390 } 00391 00392 /** 00393 * @brief Convert the SPEED register value into step/s. 00394 * 00395 * @param Speed The SPEED register value. 00396 * @retval step/s The speed as step/s. 00397 */ 00398 float L6470::L6470_Speed_2_Step_s(uint32_t Speed) 00399 { 00400 return (Speed * ((float)14.9012e-3)); 00401 } 00402 00403 /** 00404 * @brief Convert the speed as step/s into a right value for SPEED register. 00405 * 00406 * @param step/s The speed as step/s. 00407 * @retval Speed The SPEED register value. 00408 */ 00409 uint32_t L6470::L6470_Step_s_2_Speed(float Step_s) 00410 { 00411 if (Step_s <= (L6470_MAX_SPEED * ((float)14.9012e-3))) 00412 return (uint32_t)(Step_s / ((float)14.9012e-3)); 00413 else 00414 return 0; // Warning 00415 } 00416 00417 /** 00418 * @brief Convert the ACC register value into step/(s^2). 00419 * 00420 * @param Acc The ACC register value. 00421 * @retval step/(s^2) The acceleration as step/(s^2). 00422 */ 00423 float L6470::L6470_Acc_2_Step_s2(uint16_t Acc) 00424 { 00425 if (Acc <= L6470_MAX_ACC) 00426 return (Acc * ((float)1.4552e1)); 00427 else 00428 return 0; // Warning 00429 } 00430 00431 /** 00432 * @brief Convert the acceleartion as step/(s^2) into a right value for ACC register. 00433 * 00434 * @param step/(s^2) The acceleration as step/(s^2). 00435 * @retval Acc The ACC register value. 00436 */ 00437 uint16_t L6470::L6470_Step_s2_2_Acc(float Step_s2) 00438 { 00439 if (Step_s2 <= (L6470_MAX_ACC * ((float)1.4552e1))) 00440 return (uint16_t)(Step_s2 / ((float)1.4552e1)); 00441 else 00442 return 0; // Warning 00443 } 00444 00445 /** 00446 * @brief Convert the DEC register value into step/(s^2). 00447 * 00448 * @param Dec The DEC register value. 00449 * @retval step/(s^2) The deceleration as step/(s^2). 00450 */ 00451 float L6470::L6470_Dec_2_Step_s2(uint16_t Dec) 00452 { 00453 if (Dec <= L6470_MAX_DEC) 00454 return (Dec * ((float)1.4552e1)); 00455 else 00456 return 0; // Warning 00457 } 00458 00459 /** 00460 * @brief Convert the deceleration as step/(s^2) into a right value for DEC register. 00461 * 00462 * @param step/(s^2) The deceleration as step/(s^2). 00463 * @retval Dec The DEC register value. 00464 */ 00465 uint16_t L6470::L6470_Step_s2_2_Dec(float Step_s2) 00466 { 00467 if (Step_s2 <= (L6470_MAX_DEC * ((float)1.4552e1))) 00468 return (uint16_t)(Step_s2 / ((float)1.4552e1)); 00469 else 00470 return 0; // Warning 00471 } 00472 00473 /** 00474 * @brief Convert the MAX_SPEED register value into step/s. 00475 * 00476 * @param MaxSpeed The MAX_SPEED register value. 00477 * @retval step/s The max speed as step/s. 00478 */ 00479 float L6470::L6470_MaxSpeed_2_Step_s(uint16_t MaxSpeed) 00480 { 00481 if (MaxSpeed <= L6470_MAX_MAX_SPEED) 00482 return (MaxSpeed * ((float)15.2588)); 00483 else 00484 return 0; // Warning 00485 } 00486 00487 /** 00488 * @brief Convert the max speed as step/s into a right value for MAX_SPEED register. 00489 * 00490 * @param step/s The max speed as step/s. 00491 * @retval MaxSpeed The MAX_SPEED register value. 00492 */ 00493 uint16_t L6470::L6470_Step_s_2_MaxSpeed(float Step_s) 00494 { 00495 if (Step_s <= (L6470_MAX_MAX_SPEED * ((float)15.2588))) 00496 return (uint16_t)(Step_s / ((float)15.2588)); 00497 else 00498 return 0; // Warning 00499 } 00500 00501 /** 00502 * @brief Convert the MIN_SPEED register value into step/s. 00503 * 00504 * @param MinSpeed The MIN_SPEED register value. 00505 * @retval step/s The min speed as step/s. 00506 */ 00507 float L6470::L6470_MinSpeed_2_Step_s(uint16_t MinSpeed) 00508 { 00509 if (MinSpeed <= L6470_MAX_MIN_SPEED) 00510 return (MinSpeed * ((float)238.4186e-3)); 00511 else 00512 return 0; // Warning 00513 } 00514 00515 /** 00516 * @brief Convert the min speed as step/s into a right value for MIN_SPEED register. 00517 * 00518 * @param step/s The min speed as step/s. 00519 * @retval MinSpeed The MIN_SPEED register value. 00520 */ 00521 uint16_t L6470::L6470_Step_s_2_MinSpeed(float Step_s) 00522 { 00523 if (Step_s <= (L6470_MAX_MIN_SPEED * ((float)238.4186e-3))) 00524 return (uint16_t)(Step_s / ((float)238.4186e-3)); 00525 else 00526 return 0; // Warning 00527 } 00528 00529 /** 00530 * @brief Convert the FS_SPD register value into step/s. 00531 * 00532 * @param FsSpd The FS_SPD register value. 00533 * @retval step/s The full-step speed as step/s. 00534 */ 00535 float L6470::L6470_FsSpd_2_Step_s(uint16_t FsSpd) 00536 { 00537 if (FsSpd <= L6470_MAX_FS_SPD) 00538 return ((FsSpd+0.5) * ((float)15.25)); 00539 else 00540 return 0; // Warning 00541 } 00542 00543 /** 00544 * @brief Convert the full-step speed as step/s into a right value for FS_SPD register. 00545 * 00546 * @param step/s The full-step speed as step/s. 00547 * @retval FsSpd The FS_SPD register value. 00548 */ 00549 uint16_t L6470::L6470_Step_s_2_FsSpd(float Step_s) 00550 { 00551 if (Step_s <= ((L6470_MAX_FS_SPD+0.5) * ((float)15.25))) 00552 return (uint16_t)((float)(Step_s / ((float)15.25)) - (float)0.5); 00553 else 00554 return 0; // Warning 00555 } 00556 00557 /** 00558 * @brief Convert the INT_SPEED register value into step/s. 00559 * 00560 * @param IntSpeed The INT_SPEED register value. 00561 * @retval step/s The intersect speed as step/s. 00562 */ 00563 float L6470::L6470_IntSpeed_2_Step_s(uint16_t IntSpeed) 00564 { 00565 if (IntSpeed <= L6470_MAX_INT_SPEED) 00566 return (IntSpeed * ((float)59.6046e-3)); 00567 else 00568 return 0; // Warning 00569 } 00570 00571 /** 00572 * @brief Convert the intersect speed as step/s into a right value for INT_SPEED register. 00573 * 00574 * @param step/s The full-step speed as step/s. 00575 * @retval FsSpd The FS_SPD register value. 00576 */ 00577 uint16_t L6470::L6470_Step_s_2_IntSpeed(float Step_s) 00578 { 00579 if (Step_s <= (L6470_MAX_INT_SPEED * ((float)59.6046e-3))) 00580 return (uint16_t)(Step_s / ((float)59.6046e-3)); 00581 else 00582 return 0; // Warning 00583 } 00584 00585 /** 00586 * @brief Convert the ST_SLP register value into s/step. 00587 * 00588 * @param StartSlope The ST_SLP register value. 00589 * @retval s/step The start slope as s/step. 00590 */ 00591 float L6470::L6470_StSlp_2_s_Step(uint8_t StSlp) 00592 { 00593 // if (StSlp <= L6470_MAX_ST_SLP) 00594 return (StSlp * ((float)1.5686e-5)); 00595 // else 00596 // return 0; // Warning 00597 } 00598 00599 /** 00600 * @brief Convert the intersect speed as step/s into a right value for INT_SPEED register. 00601 * 00602 * @param step/s The full-step speed as step/s. 00603 * @retval FsSpd The FS_SPD register value. 00604 */ 00605 uint8_t L6470::L6470_s_Step_2_StSlp(float s_Step) 00606 { 00607 if (s_Step <= (L6470_MAX_ST_SLP * ((float)1.5686e-5))) 00608 return (uint8_t)(s_Step / ((float)1.5686e-5)); 00609 else 00610 return 0; // Warning 00611 } 00612 00613 /** 00614 * @brief Convert the INT_SPEED register value into step/s. 00615 * 00616 * @param IntSpeed The INT_SPEED register value. 00617 * @retval step/s The intersect speed as step/s. 00618 */ 00619 float L6470::L6470_FnSlpAcc_2_s_Step(uint8_t FnSlpAcc) 00620 { 00621 // if (FnSlpAcc <= L6470_MAX_FN_SLP_ACC) 00622 return (FnSlpAcc * ((float)1.5686e-5)); 00623 // else 00624 // return 0; // Warning 00625 } 00626 00627 /** 00628 * @brief Convert the intersect speed as step/s into a right value for INT_SPEED register. 00629 * 00630 * @param step/s The full-step speed as step/s. 00631 * @retval FsSpd The FS_SPD register value. 00632 */ 00633 uint8_t L6470::L6470_s_Step_2_FnSlpAcc(float s_Step) 00634 { 00635 if (s_Step <= (L6470_MAX_FN_SLP_ACC * ((float)1.5686e-5))) 00636 return (uint8_t)(s_Step / ((float)1.5686e-5)); 00637 else 00638 return 0; // Warning 00639 } 00640 00641 /** 00642 * @brief Convert the INT_SPEED register value into step/s. 00643 * 00644 * @param IntSpeed The INT_SPEED register value. 00645 * @retval step/s The intersect speed as step/s. 00646 */ 00647 float L6470::L6470_FnSlpDec_2_s_Step(uint8_t FnSlpDec) 00648 { 00649 // if (FnSlpDec <= L6470_MAX_FN_SLP_DEC) 00650 return (FnSlpDec * ((float)1.5686e-5)); 00651 // else 00652 // return 0; // Warning 00653 } 00654 00655 /** 00656 * @brief Convert the intersect speed as step/s into a right value for INT_SPEED register. 00657 * 00658 * @param step/s The full-step speed as step/s. 00659 * @retval FsSpd The FS_SPD register value. 00660 */ 00661 uint8_t L6470::L6470_s_Step_2_FnSlpDec(float s_Step) 00662 { 00663 if (s_Step <= (L6470_MAX_FN_SLP_DEC * ((float)1.5686e-5))) 00664 return (uint8_t)(s_Step / ((float)1.5686e-5)); 00665 else 00666 return 0; // Warning 00667 } 00668 00669 /** 00670 * @brief Convert the OCD_TH register value into mA. 00671 * 00672 * @param OcdTh The OCD_TH register value. 00673 * @retval mA The overcurrent threshold as mA. 00674 */ 00675 float L6470::L6470_OcdTh_2_mA(uint8_t OcdTh) 00676 { 00677 if (OcdTh <= L6470_MAX_OCD_TH) 00678 return ((OcdTh+1) * ((float)375)); 00679 else 00680 return 0; // Warning 00681 } 00682 00683 /** 00684 * @brief Convert the overcurrent threshold as mA into a right value for OCD_TH register. 00685 * 00686 * @param mA The overcurrent threshold as mA. 00687 * @retval OcdTh The OCD_TH register value. 00688 */ 00689 uint8_t L6470::L6470_mA_2_OcdTh(float mA) 00690 { 00691 float result, decimal; 00692 00693 if (mA <= ((L6470_MAX_OCD_TH+1) * ((float)375))) 00694 { 00695 result = (mA / ((float)375)); 00696 decimal = result - (uint8_t)result; 00697 00698 if (decimal < (float)0.5) 00699 return ((uint8_t)result - 1); 00700 else 00701 return ((uint8_t)result); 00702 } 00703 else 00704 return 0; // Warning 00705 } 00706 00707 /** 00708 * @brief Convert the STALL_TH register value into mA. 00709 * 00710 * @param StallTh The STALL_TH register value. 00711 * @retval mA The stall detection threshold as mA. 00712 */ 00713 float L6470::L6470_StallTh_2_mA(uint8_t StallTh) 00714 { 00715 if (StallTh <= L6470_MAX_STALL_TH) 00716 return ((StallTh+1) * ((float)31.25)); 00717 else 00718 return 0; // Warning 00719 } 00720 00721 /** 00722 * @brief Convert the stall detection threshold as mA into a right value for STALL_TH register. 00723 * 00724 * @param mA The stall detection threshold as mA. 00725 * @retval StallTh The STALL_TH register value. 00726 */ 00727 uint8_t L6470::L6470_mA_2_StallTh(float mA) 00728 { 00729 float result, decimal; 00730 00731 if (mA <= ((L6470_MAX_STALL_TH+1) * ((float)31.25))) 00732 { 00733 result = (mA / ((float)31.25)); 00734 decimal = result - (uint8_t)result; 00735 00736 if (decimal < (float)0.5) 00737 return ((uint8_t)result - 1); 00738 else 00739 return ((uint8_t)result); 00740 } 00741 else 00742 return 0; // Warning 00743 } 00744 00745 /* End of L6470_Conversion_Functions */ 00746 00747 /** 00748 * @addtogroup L6470_AppCMDs 00749 * @{ 00750 */ 00751 00752 /** 00753 * @brief SetParam command sets the register value equal to a new value. 00754 * 00755 * @param L6470_RegId The identifier of the L6470 register to be addressed. 00756 * @param Value The new value. 00757 */ 00758 void L6470::L6470_SetParam(eL6470_RegId_t L6470_RegId, uint32_t Value) 00759 { 00760 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_SETPARAM_ID, L6470_RegId, Value, 0); 00761 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00762 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00763 } 00764 00765 /** 00766 * @brief GetParam command reads the register value. 00767 * 00768 * @param L6470_RegId The identifier of the L6470 register to be addressed. 00769 * 00770 * @retval ReceivedValue The register value. 00771 */ 00772 uint32_t L6470::L6470_GetParam(eL6470_RegId_t L6470_RegId) 00773 { 00774 uint8_t ValueLengthByte; 00775 uint32_t ReceivedValue; 00776 00777 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GETPARAM_ID, L6470_RegId, 0, 0); 00778 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00779 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00780 00781 ValueLengthByte = L6470_Register[L6470_RegId].LengthByte; 00782 00783 ReceivedValue = L6470_ExtractReturnedData((uint8_t*)L6470_DaisyChainSpiRxStruct, ValueLengthByte); 00784 00785 return ReceivedValue; 00786 } 00787 00788 /** 00789 * @brief Run command produces a motion at fixed speed. 00790 * 00791 * @param L6470_DirId The identifier of the L6470 motion direction. 00792 * @param Speed The speed value as (([step/s] * 250e-9) / 2^-28) 00793 */ 00794 void L6470::L6470_Run(eL6470_DirId_t L6470_DirId, uint32_t Speed) 00795 { 00796 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RUN_ID, L6470_DirId, Speed, 0); 00797 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00798 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00799 } 00800 00801 /** 00802 * @brief StepClock command switches the device in Step-clock mode. 00803 * 00804 * @param L6470_DirId The identifier of the L6470 motion direction. 00805 */ 00806 void L6470::L6470_StepClock(eL6470_DirId_t L6470_DirId) 00807 { 00808 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_STEPCLOCK_ID, L6470_DirId, 0, 0); 00809 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00810 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00811 } 00812 00813 /** 00814 * @brief Move command produces a motion of N_STEP microsteps. 00815 * 00816 * @param L6470_DirId The identifier of the L6470 motion direction. 00817 * @param N_Step The number of microsteps. 00818 */ 00819 void L6470::L6470_Move(eL6470_DirId_t L6470_DirId, uint32_t N_Step) 00820 { 00821 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_MOVE_ID, L6470_DirId, N_Step, 0); 00822 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00823 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00824 } 00825 00826 /** 00827 * @brief GoTo command produces a motion to ABS_POS absolute position through the shortest path. 00828 * 00829 * @param AbsPos The target absolute position. 00830 */ 00831 void L6470::L6470_GoTo(uint32_t AbsPos) 00832 { 00833 if (AbsPos <= L6470_POSITION_RANGE) 00834 { 00835 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOTO_ID, AbsPos, 0, 0); 00836 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00837 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00838 } 00839 } 00840 00841 /** 00842 * @brief GoTo_DIR command produces a motion to ABS_POS absolute position imposing a direction. 00843 * 00844 * @param L6470_DirId The identifier of the L6470 motion direction. 00845 * @param AbsPos The target absolute position. 00846 */ 00847 void L6470::L6470_GoToDir(eL6470_DirId_t L6470_DirId, uint32_t AbsPos) 00848 { 00849 if (AbsPos <= L6470_POSITION_RANGE) 00850 { 00851 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOTODIR_ID, L6470_DirId, AbsPos, 0); 00852 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00853 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00854 } 00855 } 00856 00857 /** 00858 * @brief GoUntil command produces a motion at fixed speed imposing a direction 00859 * until an external switch turn-on event occurs. 00860 * 00861 * @param L6470_ActId The identifier of the L6470 action about the absolute position. 00862 * @param L6470_DirId The identifier of the L6470 motion direction. 00863 * @param Speed The speed value as (([step/s] * 250e-9) / 2^-28) 00864 */ 00865 void L6470::L6470_GoUntil(eL6470_ActId_t L6470_ActId, eL6470_DirId_t L6470_DirId, uint32_t Speed) 00866 { 00867 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOUNTIL_ID, L6470_ActId, L6470_DirId, Speed); 00868 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00869 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00870 } 00871 00872 /** 00873 * @brief ReleaseSW command produces a motion at minimum speed imposing a direction 00874 * until SW is released. 00875 * 00876 * @param L6470_ActId The identifier of the L6470 action about the absolute position. 00877 * @param L6470_DirId The identifier of the L6470 motion direction. 00878 */ 00879 void L6470::L6470_ReleaseSW(eL6470_ActId_t L6470_ActId, eL6470_DirId_t L6470_DirId) 00880 { 00881 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RELEASESW_ID, L6470_ActId, L6470_DirId, 0); 00882 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00883 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00884 } 00885 00886 /** 00887 * @brief GoHome command produces a motion to the HOME position (zero position) 00888 * via the shortest path. 00889 * 00890 */ 00891 void L6470::L6470_GoHome(void) 00892 { 00893 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOHOME_ID, 0, 0, 0); 00894 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00895 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00896 } 00897 00898 /** 00899 * @brief GoMark command produces a motion to the MARK position performing the 00900 * minimum path. 00901 * 00902 */ 00903 void L6470::L6470_GoMark(void) 00904 { 00905 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOMARK_ID, 0, 0, 0); 00906 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00907 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00908 } 00909 00910 /** 00911 * @brief ResetPos command resets the ABS_POS register to zero. 00912 * 00913 */ 00914 void L6470::L6470_ResetPos(void) 00915 { 00916 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RESETPOS_ID, 0, 0, 0); 00917 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00918 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00919 } 00920 00921 /** 00922 * @brief ResetDevice command resets the device to power-up conditions. 00923 * 00924 */ 00925 void L6470::L6470_ResetDevice(void) 00926 { 00927 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RESETDEVICE_ID, 0, 0, 0); 00928 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00929 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00930 } 00931 00932 /** 00933 * @brief SoftStop command causes an immediate deceleration to zero speed and 00934 * a consequent motor stop; the deceleration value used is the one stored 00935 * in the DEC register. 00936 * 00937 */ 00938 void L6470::L6470_SoftStop(void) 00939 { 00940 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_SOFTSTOP_ID, 0, 0, 0); 00941 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00942 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00943 } 00944 00945 /** 00946 * @brief HardStop command causes an immediate motor stop with infinite deceleration. 00947 * 00948 */ 00949 void L6470::L6470_HardStop(void) 00950 { 00951 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_HARDSTOP_ID, 0, 0, 0); 00952 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00953 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00954 } 00955 00956 /** 00957 * @brief SoftHiZ command disables the power bridges (high impedance state) 00958 * after a deceleration to zero; the deceleration value used is the one 00959 * stored in the DEC register. 00960 * 00961 */ 00962 void L6470::L6470_SoftHiZ(void) 00963 { 00964 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_SOFTHIZ_ID, 0, 0, 0); 00965 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00966 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00967 } 00968 00969 /** 00970 * @brief HardHiZ command immediately disables the power bridges (high impedance state). 00971 * 00972 */ 00973 void L6470::L6470_HardHiZ(void) 00974 { 00975 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_HARDHIZ_ID, 0, 0, 0); 00976 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00977 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00978 } 00979 00980 /** 00981 * @brief GetStatus command returns the STATUS register value. 00982 * 00983 * 00984 * @retval ReceivedValue The register value. 00985 */ 00986 uint16_t L6470::L6470_GetStatus(void) 00987 { 00988 uint16_t ReceivedValue; 00989 00990 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GETSTATUS_ID, 0, 0, 0); 00991 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 00992 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 00993 00994 ReceivedValue = (uint16_t)L6470_ExtractReturnedData((uint8_t*)L6470_DaisyChainSpiRxStruct, 2); 00995 00996 return ReceivedValue; 00997 } 00998 00999 /* End of L6470_AppCMDs */ 01000 01001 /** 01002 * @addtogroup L6470_AppCMDs_ToBePrepared 01003 * @{ 01004 */ 01005 01006 /** 01007 * @brief Prepare to send @ref L6470_SetParam command. 01008 * 01009 * @param L6470_RegId The identifier of the L6470 register to be addressed. 01010 * @param Value The new value. 01011 * 01012 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01013 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01014 */ 01015 void L6470::L6470_PrepareSetParam(eL6470_RegId_t L6470_RegId, uint32_t Value) 01016 { 01017 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_SETPARAM_ID, L6470_RegId, Value, 0); 01018 } 01019 01020 /** 01021 * @brief Prepare to send @ref L6470_GetParam command. 01022 * 01023 * @param L6470_Id The L6470 identifier inside the daisy chain. 01024 * @param L6470_RegId The identifier of the L6470 register to be addressed. 01025 * 01026 * @retval ReceivedValue The register value. 01027 * 01028 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01029 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01030 */ 01031 void L6470::L6470_PrepareGetParam(eL6470_RegId_t L6470_RegId) 01032 { 01033 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GETPARAM_ID, L6470_RegId, 0, 0); 01034 } 01035 01036 /** 01037 * @brief Prepare to send @ref L6470_Run command. 01038 * 01039 * @param L6470_DirId The identifier of the L6470 motion direction. 01040 * @param Speed The speed value as (([step/s] * 250e-9) / 2^-28) 01041 * 01042 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01043 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01044 */ 01045 void L6470::L6470_PrepareRun(eL6470_DirId_t L6470_DirId, uint32_t Speed) 01046 { 01047 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RUN_ID, L6470_DirId, Speed, 0); 01048 } 01049 01050 /** 01051 * @brief Prepare to send @ref L6470_StepClock command. 01052 * 01053 * @param L6470_DirId The identifier of the L6470 motion direction. 01054 * 01055 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01056 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01057 */ 01058 void L6470::L6470_PrepareStepClock(eL6470_DirId_t L6470_DirId) 01059 { 01060 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_STEPCLOCK_ID, L6470_DirId, 0, 0); 01061 } 01062 01063 /** 01064 * @brief Prepare to send @ref L6470_Move command. 01065 * 01066 * @param L6470_DirId The identifier of the L6470 motion direction. 01067 * @param N_Step The number of microsteps. 01068 * 01069 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01070 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01071 */ 01072 void L6470::L6470_PrepareMove(eL6470_DirId_t L6470_DirId, uint32_t N_Step) 01073 { 01074 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_MOVE_ID, L6470_DirId, N_Step, 0); 01075 } 01076 01077 /** 01078 * @brief Prepare to send @ref L6470_GoTo command. 01079 * 01080 * @param AbsPos The target absolute position. 01081 * 01082 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01083 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01084 */ 01085 void L6470::L6470_PrepareGoTo(uint32_t AbsPos) 01086 { 01087 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOTO_ID, AbsPos, 0, 0); 01088 } 01089 01090 /** 01091 * @brief Prepare to send @ref L6470_GoToDIR command. 01092 * 01093 * @param L6470_DirId The identifier of the L6470 motion direction. 01094 * @param AbsPos The target absolute position. 01095 * 01096 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01097 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01098 */ 01099 void L6470::L6470_PrepareGoToDir(eL6470_DirId_t L6470_DirId, uint32_t AbsPos) 01100 { 01101 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOTODIR_ID, L6470_DirId, AbsPos, 0); 01102 } 01103 01104 /** 01105 * @brief Prepare to send @ref L6470_GoUntil command. 01106 * 01107 * @param L6470_ActId The identifier of the L6470 action about the absolute position. 01108 * @param L6470_DirId The identifier of the L6470 motion direction. 01109 * @param Speed The speed value as (([step/s] * 250e-9) / 2^-28) 01110 * 01111 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01112 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01113 */ 01114 void L6470::L6470_PrepareGoUntil(eL6470_ActId_t L6470_ActId, eL6470_DirId_t L6470_DirId, uint32_t Speed) 01115 { 01116 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOUNTIL_ID, L6470_ActId, L6470_DirId, Speed); 01117 } 01118 01119 /** 01120 * @brief Prepare to send @ref L6470_ReleaseSW. 01121 * 01122 * @param L6470_ActId The identifier of the L6470 action about the absolute position. 01123 * @param L6470_DirId The identifier of the L6470 motion direction. 01124 * 01125 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01126 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01127 */ 01128 void L6470::L6470_PrepareReleaseSW(eL6470_ActId_t L6470_ActId, eL6470_DirId_t L6470_DirId) 01129 { 01130 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RELEASESW_ID, L6470_ActId, L6470_DirId, 0); 01131 } 01132 01133 /** 01134 * @brief Prepare to send @ref L6470_GoHome command. 01135 * 01136 * 01137 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01138 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01139 */ 01140 void L6470::L6470_PrepareGoHome(void) 01141 { 01142 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOHOME_ID, 0, 0, 0); 01143 } 01144 01145 /** 01146 * @brief Prepare to send @ref L6470_GoMark command. 01147 * 01148 * 01149 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01150 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01151 */ 01152 void L6470::L6470_PrepareGoMark(void) 01153 { 01154 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GOMARK_ID, 0, 0, 0); 01155 } 01156 01157 /** 01158 * @brief Prepare to send @ref L6470_ResetPos command. 01159 * 01160 * 01161 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01162 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01163 */ 01164 void L6470::L6470_PrepareResetPos(void) 01165 { 01166 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RESETPOS_ID, 0, 0, 0); 01167 } 01168 01169 /** 01170 * @brief Prepare to send @ref L6470_ResetDevice command. 01171 * 01172 * 01173 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01174 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01175 */ 01176 void L6470::L6470_PrepareResetDevice(void) 01177 { 01178 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_RESETDEVICE_ID, 0, 0, 0); 01179 } 01180 01181 /** 01182 * @brief Prepare to send @ref L6470_SoftStop command. 01183 * 01184 * 01185 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01186 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01187 */ 01188 void L6470::L6470_PrepareSoftStop(void) 01189 { 01190 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_SOFTSTOP_ID, 0, 0, 0); 01191 } 01192 01193 /** 01194 * @brief Prepare to send @ref L6470_HardStop command. 01195 * 01196 * 01197 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01198 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01199 */ 01200 void L6470::L6470_PrepareHardStop(void) 01201 { 01202 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_HARDSTOP_ID, 0, 0, 0); 01203 } 01204 01205 /** 01206 * @brief Prepare to send @ref L6470_SoftHiZ command. 01207 * 01208 * 01209 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01210 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01211 */ 01212 void L6470::L6470_PrepareSoftHiZ(void) 01213 { 01214 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_SOFTHIZ_ID, 0, 0, 0); 01215 } 01216 01217 /** 01218 * @brief Prepare to send @ref L6470_HardHiZ command. 01219 * 01220 * 01221 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01222 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01223 */ 01224 void L6470::L6470_PrepareHardHiZ(void) 01225 { 01226 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_HARDHIZ_ID, 0, 0, 0); 01227 } 01228 01229 /** 01230 * @brief Prepare to send @ref L6470_GetStatus command. 01231 * 01232 * 01233 * @note This function will properly fill the right column of the L6470_AppCmdPkg. 01234 * @note The commad will be sent by @ref L6470_PerformPreparedApplicationCommand. 01235 */ 01236 void L6470::L6470_PrepareGetStatus(void) 01237 { 01238 L6470_PrepareAppCmdPkg(L6470_AppCmdPkg, L6470_GETSTATUS_ID, 0, 0, 0); 01239 } 01240 01241 /* End of L6470_AppCMDs_ToBePrepared */ 01242 01243 /** 01244 * @brief Send via SPI the command stored inside the L6470_AppCmdPkg to the 01245 * L6470 daisy chain. 01246 * 01247 * @retval (uint8_t*)data->L6470_DaisyChainSpiRxStruct The pointer to the structure 01248 * containing returned values from each L6470 of the daisy chain for each 01249 * sent SPI data. 01250 */ 01251 uint8_t* L6470::L6470_PerformPreparedApplicationCommand(void) 01252 { 01253 L6470_PrepareDaisyChainCommand(L6470_AppCmdPkg, (uint8_t*)L6470_DaisyChainSpiTxStruct); 01254 L6470_DaisyChainCommand((uint8_t*)L6470_DaisyChainSpiTxStruct, (uint8_t*)L6470_DaisyChainSpiRxStruct); 01255 01256 return (uint8_t*)(L6470_DaisyChainSpiRxStruct); 01257 } 01258 01259 /** 01260 * @brief Send command to the L6470 daisy chain via SPI 01261 * @param pL6470_DaisyChainSpiTxStruct Pointer to the matrix array of bytes to be sent to the daisy chain L6470 01262 * @param pL6470_DaisyChainSpiRxStruct Pointer to the matrix array of bytes to be received from the daisy chain L6470 01263 */ 01264 void L6470::L6470_DaisyChainCommand(uint8_t* pL6470_DaisyChainSpiTxStruct, uint8_t* pL6470_DaisyChainSpiRxStruct) 01265 { 01266 uint8_t spibyte; 01267 01268 L6470_DaisyChain_HalfPrepared = ZERO_F; 01269 01270 /* Send all command bytes via SPI */ 01271 for(spibyte=0; spibyte < L6470MAXSPICMDBYTESIZE; spibyte++) 01272 { 01273 /* Send the command via SPI */ 01274 L6470_SPI_Communication((pL6470_DaisyChainSpiTxStruct+(spibyte * L6470DAISYCHAINSIZE)), (pL6470_DaisyChainSpiRxStruct+(spibyte * L6470DAISYCHAINSIZE)), L6470DAISYCHAINSIZE, 10); 01275 01276 //_DELAY(TDISCS); 01277 uint8_t delay_cnt; 01278 for (delay_cnt=0; delay_cnt<20; delay_cnt++) __NOP(); //!<Simply deselect time delay for SPI nCS 01279 } 01280 } 01281 01282 /** 01283 * @brief Extracts the data returned by the L6470 from the matrix that 01284 * contains the received SPI data. 01285 * @param L6470_Id The identifier of the L6470 target inside the daisy chain. 01286 * @param pL6470_DaisyChainSpiRxStruct uint8_t-pointer to the matrix that 01287 * contains the received data by SPI from the L6470 daisy chain. 01288 * @param LengthByte The number of bytes about the received value. 01289 */ 01290 uint32_t L6470::L6470_ExtractReturnedData(uint8_t* pL6470_DaisyChainSpiRxStruct, uint8_t LengthByte) 01291 { 01292 uint32_t value; 01293 uint8_t i; 01294 01295 value = 0x000000; 01296 for (i=1; i<=(L6470MAXSPICMDBYTESIZE-1); i++) 01297 { 01298 value |= (*(pL6470_DaisyChainSpiRxStruct+(i*L6470DAISYCHAINSIZE)+L6470_Id))<<((LengthByte-i)*8); 01299 } 01300 01301 return value; 01302 } 01303 01304 /** 01305 * @brief Check the state of a flag inside the L6470 STATUS register. 01306 * 01307 * @param L6470_Id The identifier of the L6470 target inside the daisy chain. 01308 * @param L6470_StatusRegisterFlagId The identifier of the L6470 STATUS flag to be checked. 01309 * 01310 * @retval state The flag state. 01311 */ 01312 01313 uint8_t L6470::L6470_CheckStatusRegisterFlag(uint8_t L6470_StatusRegisterFlagId) 01314 { 01315 uint8_t state = 0; 01316 01317 *((uint16_t*)pL6470_StatusRegister) = L6470_GetParam(L6470_STATUS_ID); 01318 01319 switch(L6470_StatusRegisterFlagId) 01320 { 01321 case HiZ_ID: 01322 state = pL6470_StatusRegister->HiZ; 01323 break; 01324 case BUSY_ID: 01325 state = pL6470_StatusRegister->BUSY; 01326 break; 01327 case SW_F_ID: 01328 state = pL6470_StatusRegister->SW_F; 01329 break; 01330 case SW_EVN_ID: 01331 state = pL6470_StatusRegister->SW_EVN; 01332 break; 01333 case DIR_ID: 01334 state = pL6470_StatusRegister->DIR; 01335 break; 01336 case MOT_STATUS_ID: 01337 state = pL6470_StatusRegister->MOT_STATUS; 01338 break; 01339 case NOTPERF_CMD_ID: 01340 state = pL6470_StatusRegister->NOTPERF_CMD; 01341 break; 01342 case WRONG_CMD_ID: 01343 state = pL6470_StatusRegister->WRONG_CMD; 01344 break; 01345 case UVLO_ID: 01346 state = pL6470_StatusRegister->UVLO; 01347 break; 01348 case TH_WRN_ID: 01349 state = pL6470_StatusRegister->TH_WRN; 01350 break; 01351 case TH_SD_ID: 01352 state = pL6470_StatusRegister->TH_SD; 01353 break; 01354 case OCD_ID: 01355 state = pL6470_StatusRegister->OCD; 01356 break; 01357 case STEP_LOSS_A_ID: 01358 state = pL6470_StatusRegister->STEP_LOSS_A; 01359 break; 01360 case STEP_LOSS_B_ID: 01361 state = pL6470_StatusRegister->STEP_LOSS_B; 01362 break; 01363 case SCK_MOD_ID: 01364 state = pL6470_StatusRegister->SCK_MOD; 01365 break; 01366 } 01367 01368 return state; 01369 } 01370 01371 /** 01372 * @brief Return the mnemonic name for the L6470 register. 01373 * @param id The identifier of the L6470 register. 01374 */ 01375 uint8_t *L6470::L6470_GetRegisterName(uint8_t id) 01376 { 01377 if (id < L6470REGIDSIZE) 01378 { 01379 return (uint8_t*)L6470_Register[id].Name; 01380 } 01381 else 01382 { 01383 return NULL; 01384 } 01385 } 01386 01387 /** 01388 * @brief Configures the L6470 registers. 01389 * @param init The pointer to the initialization structure. 01390 */ 01391 status_t L6470::L6470_Config(void *init) 01392 { 01393 /* Disable the L6470. */ 01394 L6470_DISABLE(); 01395 01396 /* Enable the L6470. */ 01397 L6470_ENABLE(); 01398 01399 /* Reset devices. */ 01400 reset_device(); 01401 01402 /* Reset Status Register flags. */ 01403 get_status(); 01404 01405 /* Prepare the 'Register' field of StepperMotorDriverHandle */ 01406 L6470_init_t *MotorParameterData = (L6470_init_t *) init; 01407 StepperMotorRegister.ACC = L6470_Step_s2_2_Acc(MotorParameterData->acc); 01408 StepperMotorRegister.DEC = L6470_Step_s2_2_Dec(MotorParameterData->dec); 01409 StepperMotorRegister.MAX_SPEED = L6470_Step_s_2_MaxSpeed(MotorParameterData->maxspeed); 01410 StepperMotorRegister.MIN_SPEED = L6470_Step_s_2_MinSpeed(MotorParameterData->minspeed); 01411 StepperMotorRegister.FS_SPD = L6470_Step_s_2_FsSpd(MotorParameterData->fsspd); 01412 StepperMotorRegister.KVAL_HOLD = (uint8_t)((float)((float)(MotorParameterData->kvalhold * 256) / (MotorParameterData->motorvoltage))); 01413 StepperMotorRegister.KVAL_RUN = (uint8_t)((float)((float)(MotorParameterData->kvalrun * 256) / (MotorParameterData->motorvoltage))); 01414 StepperMotorRegister.KVAL_ACC = (uint8_t)((float)((float)(MotorParameterData->kvalacc * 256) / (MotorParameterData->motorvoltage))); 01415 StepperMotorRegister.KVAL_DEC = (uint8_t)((float)((float)(MotorParameterData->kvaldec * 256) / (MotorParameterData->motorvoltage))); 01416 StepperMotorRegister.INT_SPEED = L6470_Step_s_2_IntSpeed(MotorParameterData->intspeed); 01417 StepperMotorRegister.ST_SLP = L6470_s_Step_2_StSlp(MotorParameterData->stslp); 01418 StepperMotorRegister.FN_SLP_ACC = L6470_s_Step_2_FnSlpAcc(MotorParameterData->fnslpacc); 01419 StepperMotorRegister.FN_SLP_DEC = L6470_s_Step_2_FnSlpDec(MotorParameterData->fnslpdec); 01420 StepperMotorRegister.K_THERM = MotorParameterData->kterm; 01421 StepperMotorRegister.OCD_TH = L6470_mA_2_OcdTh(MotorParameterData->ocdth); 01422 StepperMotorRegister.STALL_TH = L6470_mA_2_StallTh(MotorParameterData->stallth); 01423 StepperMotorRegister.ALARM_EN = MotorParameterData->alarmen; 01424 StepperMotorRegister.CONFIG = MotorParameterData->config; 01425 StepperMotorRegister.STEP_MODE = MotorParameterData->step_sel; 01426 01427 /* Write the L6470 registers with the prepared data */ 01428 L6470_SetParam(L6470_ACC_ID, StepperMotorRegister.ACC); 01429 L6470_SetParam(L6470_DEC_ID, StepperMotorRegister.DEC); 01430 L6470_SetParam(L6470_MAX_SPEED_ID, StepperMotorRegister.MAX_SPEED); 01431 L6470_SetParam(L6470_MIN_SPEED_ID, StepperMotorRegister.MIN_SPEED); 01432 L6470_SetParam(L6470_FS_SPD_ID, StepperMotorRegister.FS_SPD); 01433 L6470_SetParam(L6470_KVAL_HOLD_ID, StepperMotorRegister.KVAL_HOLD); 01434 L6470_SetParam(L6470_KVAL_RUN_ID, StepperMotorRegister.KVAL_RUN); 01435 L6470_SetParam(L6470_KVAL_ACC_ID, StepperMotorRegister.KVAL_ACC); 01436 L6470_SetParam(L6470_KVAL_DEC_ID, StepperMotorRegister.KVAL_DEC); 01437 L6470_SetParam(L6470_INT_SPEED_ID, StepperMotorRegister.INT_SPEED); 01438 L6470_SetParam(L6470_ST_SLP_ID, StepperMotorRegister.ST_SLP); 01439 L6470_SetParam(L6470_FN_SLP_ACC_ID, StepperMotorRegister.FN_SLP_ACC); 01440 L6470_SetParam(L6470_FN_SLP_DEC_ID, StepperMotorRegister.FN_SLP_DEC); 01441 L6470_SetParam(L6470_K_THERM_ID, StepperMotorRegister.K_THERM); 01442 L6470_SetParam(L6470_OCD_TH_ID, StepperMotorRegister.OCD_TH); 01443 L6470_SetParam(L6470_STALL_TH_ID, StepperMotorRegister.STALL_TH); 01444 L6470_SetParam(L6470_ALARM_EN_ID, StepperMotorRegister.ALARM_EN); 01445 L6470_SetParam(L6470_CONFIG_ID, StepperMotorRegister.CONFIG); 01446 if (!set_step_mode((StepperMotor::step_mode_t) StepperMotorRegister.STEP_MODE)) 01447 return COMPONENT_ERROR; 01448 01449 return COMPONENT_OK; 01450 } 01451 01452 /* End of L6470_Exported_Functions */ 01453 01454 /* End of L6470 */ 01455 01456 /* End of Components */ 01457 01458 /* End of BSP */ 01459 01460 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 22:48:07 by 1.7.2