Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of X_NUCLEO_IHM02A1 by
l6470_class.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_class.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 ResetDevice(); 01401 01402 /* Reset Status Register flags. */ 01403 GetStatus(); 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 (!SetStepMode((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 Thu Jul 14 2022 03:27:23 by
1.7.2
