lsm6dsl.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. /*
  2. ChibiOS - Copyright (C) 2016..2018 Rocco Marco Guglielmi
  3. This file is part of ChibiOS.
  4. ChibiOS is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. ChibiOS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /**
  16. * @file lsm6dsl.c
  17. * @brief LSM6DSL MEMS interface module code.
  18. *
  19. * @addtogroup LSM6DSL
  20. * @ingroup EX_ST
  21. * @{
  22. */
  23. #include "hal.h"
  24. #include "lsm6dsl.h"
  25. /*===========================================================================*/
  26. /* Driver local definitions. */
  27. /*===========================================================================*/
  28. /*===========================================================================*/
  29. /* Driver exported variables. */
  30. /*===========================================================================*/
  31. /*===========================================================================*/
  32. /* Driver local variables and types. */
  33. /*===========================================================================*/
  34. /*===========================================================================*/
  35. /* Driver local functions. */
  36. /*===========================================================================*/
  37. #if (LSM6DSL_USE_I2C) || defined(__DOXYGEN__)
  38. /**
  39. * @brief Reads registers value using I2C.
  40. * @pre The I2C interface must be initialized and the driver started.
  41. * @note IF_ADD_INC bit must be 1 in CTRL_REG8
  42. *
  43. * @param[in] i2cp pointer to the I2C interface
  44. * @param[in] sad slave address without R bit
  45. * @param[in] reg first sub-register address
  46. * @param[out] rxbuf pointer to an output buffer
  47. * @param[in] n number of consecutive register to read
  48. * @return the operation status.
  49. * @notapi
  50. */
  51. msg_t lsm6dslI2CReadRegister(I2CDriver *i2cp, lsm6dsl_sad_t sad, uint8_t reg,
  52. uint8_t* rxbuf, size_t n) {
  53. return i2cMasterTransmitTimeout(i2cp, sad, &reg, 1, rxbuf, n,
  54. TIME_INFINITE);
  55. }
  56. /**
  57. * @brief Writes a value into a register using I2C.
  58. * @pre The I2C interface must be initialized and the driver started.
  59. *
  60. * @param[in] i2cp pointer to the I2C interface
  61. * @param[in] sad slave address without R bit
  62. * @param[in] txbuf buffer containing sub-address value in first position
  63. * and values to write
  64. * @param[in] n size of txbuf less one (not considering the first
  65. * element)
  66. * @return the operation status.
  67. * @notapi
  68. */
  69. #define lsm6dslI2CWriteRegister(i2cp, sad, txbuf, n) \
  70. i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0, \
  71. TIME_INFINITE)
  72. #endif /* LSM6DSL_USE_I2C */
  73. /**
  74. * @brief Return the number of axes of the BaseAccelerometer.
  75. *
  76. * @param[in] ip pointer to @p BaseAccelerometer interface.
  77. *
  78. * @return the number of axes.
  79. */
  80. static size_t acc_get_axes_number(void *ip) {
  81. (void)ip;
  82. return LSM6DSL_ACC_NUMBER_OF_AXES;
  83. }
  84. /**
  85. * @brief Retrieves raw data from the BaseAccelerometer.
  86. * @note This data is retrieved from MEMS register without any algebraical
  87. * manipulation.
  88. * @note The axes array must be at least the same size of the
  89. * BaseAccelerometer axes number.
  90. *
  91. * @param[in] ip pointer to @p BaseAccelerometer interface.
  92. * @param[out] axes a buffer which would be filled with raw data.
  93. *
  94. * @return The operation status.
  95. * @retval MSG_OK if the function succeeded.
  96. * @retval MSG_RESET if one or more I2C errors occurred, the errors can
  97. * be retrieved using @p i2cGetErrors().
  98. * @retval MSG_TIMEOUT if a timeout occurred before operation end.
  99. */
  100. static msg_t acc_read_raw(void *ip, int32_t axes[]) {
  101. LSM6DSLDriver* devp;
  102. uint8_t buff [LSM6DSL_ACC_NUMBER_OF_AXES * 2], i;
  103. int16_t tmp;
  104. msg_t msg;
  105. osalDbgCheck((ip != NULL) && (axes != NULL));
  106. /* Getting parent instance pointer.*/
  107. devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
  108. osalDbgAssert((devp->state == LSM6DSL_READY),
  109. "acc_read_raw(), invalid state");
  110. #if LSM6DSL_USE_I2C
  111. osalDbgAssert((devp->config->i2cp->state == I2C_READY),
  112. "acc_read_raw(), channel not ready");
  113. #if LSM6DSL_SHARED_I2C
  114. i2cAcquireBus(devp->config->i2cp);
  115. i2cStart(devp->config->i2cp,
  116. devp->config->i2ccfg);
  117. #endif /* LSM6DSL_SHARED_I2C */
  118. msg = lsm6dslI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
  119. LSM6DSL_AD_OUTX_L_XL, buff,
  120. LSM6DSL_ACC_NUMBER_OF_AXES * 2);
  121. #if LSM6DSL_SHARED_I2C
  122. i2cReleaseBus(devp->config->i2cp);
  123. #endif /* LSM6DSL_SHARED_I2C */
  124. #endif /* LSM6DSL_USE_I2C */
  125. if(msg == MSG_OK)
  126. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  127. tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
  128. axes[i] = (int32_t)tmp;
  129. }
  130. return msg;
  131. }
  132. /**
  133. * @brief Retrieves cooked data from the BaseAccelerometer.
  134. * @note This data is manipulated according to the formula
  135. * cooked = (raw * sensitivity) - bias.
  136. * @note Final data is expressed as milli-G.
  137. * @note The axes array must be at least the same size of the
  138. * BaseAccelerometer axes number.
  139. *
  140. * @param[in] ip pointer to @p BaseAccelerometer interface.
  141. * @param[out] axes a buffer which would be filled with cooked data.
  142. *
  143. * @return The operation status.
  144. * @retval MSG_OK if the function succeeded.
  145. * @retval MSG_RESET if one or more I2C errors occurred, the errors can
  146. * be retrieved using @p i2cGetErrors().
  147. * @retval MSG_TIMEOUT if a timeout occurred before operation end.
  148. */
  149. static msg_t acc_read_cooked(void *ip, float axes[]) {
  150. LSM6DSLDriver* devp;
  151. uint32_t i;
  152. int32_t raw[LSM6DSL_ACC_NUMBER_OF_AXES];
  153. msg_t msg;
  154. osalDbgCheck((ip != NULL) && (axes != NULL));
  155. /* Getting parent instance pointer.*/
  156. devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
  157. osalDbgAssert((devp->state == LSM6DSL_READY),
  158. "acc_read_cooked(), invalid state");
  159. msg = acc_read_raw(ip, raw);
  160. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  161. axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
  162. }
  163. return msg;
  164. }
  165. /**
  166. * @brief Set bias values for the BaseAccelerometer.
  167. * @note Bias must be expressed as milli-G.
  168. * @note The bias buffer must be at least the same size of the
  169. * BaseAccelerometer axes number.
  170. *
  171. * @param[in] ip pointer to @p BaseAccelerometer interface.
  172. * @param[in] bp a buffer which contains biases.
  173. *
  174. * @return The operation status.
  175. * @retval MSG_OK if the function succeeded.
  176. */
  177. static msg_t acc_set_bias(void *ip, float *bp) {
  178. LSM6DSLDriver* devp;
  179. uint32_t i;
  180. msg_t msg = MSG_OK;
  181. osalDbgCheck((ip != NULL) && (bp != NULL));
  182. /* Getting parent instance pointer.*/
  183. devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
  184. osalDbgAssert((devp->state == LSM6DSL_READY),
  185. "acc_set_bias(), invalid state");
  186. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  187. devp->accbias[i] = bp[i];
  188. }
  189. return msg;
  190. }
  191. /**
  192. * @brief Reset bias values for the BaseAccelerometer.
  193. * @note Default biases value are obtained from device datasheet when
  194. * available otherwise they are considered zero.
  195. *
  196. * @param[in] ip pointer to @p BaseAccelerometer interface.
  197. *
  198. * @return The operation status.
  199. * @retval MSG_OK if the function succeeded.
  200. */
  201. static msg_t acc_reset_bias(void *ip) {
  202. LSM6DSLDriver* devp;
  203. uint32_t i;
  204. msg_t msg = MSG_OK;
  205. osalDbgCheck(ip != NULL);
  206. /* Getting parent instance pointer.*/
  207. devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
  208. osalDbgAssert((devp->state == LSM6DSL_READY),
  209. "acc_reset_bias(), invalid state");
  210. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  211. devp->accbias[i] = LSM6DSL_ACC_BIAS;
  212. return msg;
  213. }
  214. /**
  215. * @brief Set sensitivity values for the BaseAccelerometer.
  216. * @note Sensitivity must be expressed as milli-G/LSB.
  217. * @note The sensitivity buffer must be at least the same size of the
  218. * BaseAccelerometer axes number.
  219. *
  220. * @param[in] ip pointer to @p BaseAccelerometer interface.
  221. * @param[in] sp a buffer which contains sensitivities.
  222. *
  223. * @return The operation status.
  224. * @retval MSG_OK if the function succeeded.
  225. */
  226. static msg_t acc_set_sensivity(void *ip, float *sp) {
  227. LSM6DSLDriver* devp;
  228. uint32_t i;
  229. msg_t msg = MSG_OK;
  230. /* Getting parent instance pointer.*/
  231. devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
  232. osalDbgCheck((ip != NULL) && (sp != NULL));
  233. osalDbgAssert((devp->state == LSM6DSL_READY),
  234. "acc_set_sensivity(), invalid state");
  235. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  236. devp->accsensitivity[i] = sp[i];
  237. }
  238. return msg;
  239. }
  240. /**
  241. * @brief Reset sensitivity values for the BaseAccelerometer.
  242. * @note Default sensitivities value are obtained from device datasheet.
  243. *
  244. * @param[in] ip pointer to @p BaseAccelerometer interface.
  245. *
  246. * @return The operation status.
  247. * @retval MSG_OK if the function succeeded.
  248. * @retval MSG_RESET otherwise.
  249. */
  250. static msg_t acc_reset_sensivity(void *ip) {
  251. LSM6DSLDriver* devp;
  252. uint32_t i;
  253. msg_t msg = MSG_OK;
  254. osalDbgCheck(ip != NULL);
  255. /* Getting parent instance pointer.*/
  256. devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
  257. osalDbgAssert((devp->state == LSM6DSL_READY),
  258. "acc_reset_sensivity(), invalid state");
  259. if(devp->config->accfullscale == LSM6DSL_ACC_FS_2G)
  260. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  261. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_2G;
  262. else if(devp->config->accfullscale == LSM6DSL_ACC_FS_4G)
  263. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  264. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_4G;
  265. else if(devp->config->accfullscale == LSM6DSL_ACC_FS_8G)
  266. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  267. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_8G;
  268. else if(devp->config->accfullscale == LSM6DSL_ACC_FS_16G)
  269. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  270. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_16G;
  271. else {
  272. osalDbgAssert(FALSE, "reset_sensivity(), accelerometer full scale issue");
  273. msg = MSG_RESET;
  274. }
  275. return msg;
  276. }
  277. /**
  278. * @brief Changes the LSM6DSLDriver accelerometer fullscale value.
  279. * @note This function also rescale sensitivities and biases based on
  280. * previous and next fullscale value.
  281. * @note A recalibration is highly suggested after calling this function.
  282. *
  283. * @param[in] devp pointer to @p LSM6DSLDriver interface.
  284. * @param[in] fs new fullscale value.
  285. *
  286. * @return The operation status.
  287. * @retval MSG_OK if the function succeeded.
  288. * @retval MSG_RESET otherwise.
  289. */
  290. static msg_t acc_set_full_scale(LSM6DSLDriver *devp, lsm6dsl_acc_fs_t fs) {
  291. float newfs, scale;
  292. uint8_t i, buff[2];
  293. msg_t msg;
  294. osalDbgCheck(devp != NULL);
  295. osalDbgAssert((devp->state == LSM6DSL_READY),
  296. "acc_set_full_scale(), invalid state");
  297. osalDbgAssert((devp->config->i2cp->state == I2C_READY),
  298. "acc_set_full_scale(), channel not ready");
  299. /* Computing new fullscale value.*/
  300. if(fs == LSM6DSL_ACC_FS_2G) {
  301. newfs = LSM6DSL_ACC_2G;
  302. }
  303. else if(fs == LSM6DSL_ACC_FS_4G) {
  304. newfs = LSM6DSL_ACC_4G;
  305. }
  306. else if(fs == LSM6DSL_ACC_FS_8G) {
  307. newfs = LSM6DSL_ACC_8G;
  308. }
  309. else if(fs == LSM6DSL_ACC_FS_16G) {
  310. newfs = LSM6DSL_ACC_16G;
  311. }
  312. else {
  313. msg = MSG_RESET;
  314. return msg;
  315. }
  316. if(newfs != devp->accfullscale) {
  317. /* Computing scale value.*/
  318. scale = newfs / devp->accfullscale;
  319. devp->accfullscale = newfs;
  320. #if LSM6DSL_SHARED_I2C
  321. i2cAcquireBus(devp->config->i2cp);
  322. i2cStart(devp->config->i2cp,
  323. devp->config->i2ccfg);
  324. #endif /* LSM6DSL_SHARED_I2C */
  325. /* Updating register.*/
  326. msg = lsm6dslI2CReadRegister(devp->config->i2cp,
  327. devp->config->slaveaddress,
  328. LSM6DSL_AD_CTRL1_XL, &buff[1], 1);
  329. #if LSM6DSL_SHARED_I2C
  330. i2cReleaseBus(devp->config->i2cp);
  331. #endif /* LSM6DSL_SHARED_I2C */
  332. if(msg != MSG_OK)
  333. return msg;
  334. buff[1] &= ~(LSMDSL_CTRL1_XL_FS_MASK);
  335. buff[1] |= fs;
  336. buff[0] = LSM6DSL_AD_CTRL1_XL;
  337. #if LSM6DSL_SHARED_I2C
  338. i2cAcquireBus(devp->config->i2cp);
  339. i2cStart(devp->config->i2cp, devp->config->i2ccfg);
  340. #endif /* LSM6DSL_SHARED_I2C */
  341. msg = lsm6dslI2CWriteRegister(devp->config->i2cp,
  342. devp->config->slaveaddress, buff, 1);
  343. #if LSM6DSL_SHARED_I2C
  344. i2cReleaseBus(devp->config->i2cp);
  345. #endif /* LSM6DSL_SHARED_I2C */
  346. if(msg != MSG_OK)
  347. return msg;
  348. /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
  349. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  350. devp->accsensitivity[i] *= scale;
  351. devp->accbias[i] *= scale;
  352. }
  353. }
  354. return msg;
  355. }
  356. /**
  357. * @brief Return the number of axes of the BaseGyroscope.
  358. *
  359. * @param[in] ip pointer to @p BaseGyroscope interface.
  360. *
  361. * @return the number of axes.
  362. */
  363. static size_t gyro_get_axes_number(void *ip) {
  364. (void)ip;
  365. return LSM6DSL_GYRO_NUMBER_OF_AXES;
  366. }
  367. /**
  368. * @brief Retrieves raw data from the BaseGyroscope.
  369. * @note This data is retrieved from MEMS register without any algebraical
  370. * manipulation.
  371. * @note The axes array must be at least the same size of the
  372. * BaseGyroscope axes number.
  373. *
  374. * @param[in] ip pointer to @p BaseGyroscope interface.
  375. * @param[out] axes a buffer which would be filled with raw data.
  376. *
  377. * @return The operation status.
  378. * @retval MSG_OK if the function succeeded.
  379. * @retval MSG_RESET if one or more I2C errors occurred, the errors can
  380. * be retrieved using @p i2cGetErrors().
  381. * @retval MSG_TIMEOUT if a timeout occurred before operation end.
  382. */
  383. static msg_t gyro_read_raw(void *ip, int32_t axes[LSM6DSL_GYRO_NUMBER_OF_AXES]) {
  384. LSM6DSLDriver* devp;
  385. int16_t tmp;
  386. uint8_t i, buff [2 * LSM6DSL_GYRO_NUMBER_OF_AXES];
  387. msg_t msg = MSG_OK;
  388. osalDbgCheck((ip != NULL) && (axes != NULL));
  389. /* Getting parent instance pointer.*/
  390. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  391. osalDbgAssert((devp->state == LSM6DSL_READY),
  392. "gyro_read_raw(), invalid state");
  393. #if LSM6DSL_USE_I2C
  394. osalDbgAssert((devp->config->i2cp->state == I2C_READY),
  395. "gyro_read_raw(), channel not ready");
  396. #if LSM6DSL_SHARED_I2C
  397. i2cAcquireBus(devp->config->i2cp);
  398. i2cStart(devp->config->i2cp,
  399. devp->config->i2ccfg);
  400. #endif /* LSM6DSL_SHARED_I2C */
  401. msg = lsm6dslI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
  402. LSM6DSL_AD_OUTX_L_G, buff,
  403. LSM6DSL_GYRO_NUMBER_OF_AXES * 2);
  404. #if LSM6DSL_SHARED_I2C
  405. i2cReleaseBus(devp->config->i2cp);
  406. #endif /* LSM6DSL_SHARED_I2C */
  407. #endif /* LSM6DSL_USE_I2C */
  408. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  409. tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
  410. axes[i] = (int32_t)tmp;
  411. }
  412. return msg;
  413. }
  414. /**
  415. * @brief Retrieves cooked data from the BaseGyroscope.
  416. * @note This data is manipulated according to the formula
  417. * cooked = (raw * sensitivity) - bias.
  418. * @note Final data is expressed as DPS.
  419. * @note The axes array must be at least the same size of the
  420. * BaseGyroscope axes number.
  421. *
  422. * @param[in] ip pointer to @p BaseGyroscope interface.
  423. * @param[out] axes a buffer which would be filled with cooked data.
  424. *
  425. * @return The operation status.
  426. * @retval MSG_OK if the function succeeded.
  427. * @retval MSG_RESET if one or more I2C errors occurred, the errors can
  428. * be retrieved using @p i2cGetErrors().
  429. * @retval MSG_TIMEOUT if a timeout occurred before operation end.
  430. */
  431. static msg_t gyro_read_cooked(void *ip, float axes[]) {
  432. LSM6DSLDriver* devp;
  433. uint32_t i;
  434. int32_t raw[LSM6DSL_GYRO_NUMBER_OF_AXES];
  435. msg_t msg;
  436. osalDbgCheck((ip != NULL) && (axes != NULL));
  437. /* Getting parent instance pointer.*/
  438. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  439. osalDbgAssert((devp->state == LSM6DSL_READY),
  440. "gyro_read_cooked(), invalid state");
  441. msg = gyro_read_raw(ip, raw);
  442. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++){
  443. axes[i] = (raw[i] * devp->gyrosensitivity[i]) - devp->gyrobias[i];
  444. }
  445. return msg;
  446. }
  447. /**
  448. * @brief Samples bias values for the BaseGyroscope.
  449. * @note The LSM6DSL shall not be moved during the whole procedure.
  450. * @note After this function internal bias is automatically updated.
  451. * @note The behavior of this function depends on @p LSM6DSL_BIAS_ACQ_TIMES
  452. * and @p LSM6DSL_BIAS_SETTLING_US.
  453. *
  454. * @param[in] ip pointer to @p BaseGyroscope interface.
  455. *
  456. * @return The operation status.
  457. * @retval MSG_OK if the function succeeded.
  458. */
  459. static msg_t gyro_sample_bias(void *ip) {
  460. LSM6DSLDriver* devp;
  461. uint32_t i, j;
  462. int32_t raw[LSM6DSL_GYRO_NUMBER_OF_AXES];
  463. int32_t buff[LSM6DSL_GYRO_NUMBER_OF_AXES] = {0, 0, 0};
  464. msg_t msg;
  465. osalDbgCheck(ip != NULL);
  466. /* Getting parent instance pointer.*/
  467. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  468. osalDbgAssert((devp->state == LSM6DSL_READY),
  469. "gyro_sample_bias(), invalid state");
  470. #if LSM6DSL_USE_I2C
  471. osalDbgAssert((devp->config->i2cp->state == I2C_READY),
  472. "gyro_sample_bias(), channel not ready");
  473. #endif
  474. for(i = 0; i < LSM6DSL_GYRO_BIAS_ACQ_TIMES; i++){
  475. msg = gyro_read_raw(ip, raw);
  476. if(msg != MSG_OK)
  477. return msg;
  478. for(j = 0; j < LSM6DSL_GYRO_NUMBER_OF_AXES; j++){
  479. buff[j] += raw[j];
  480. }
  481. osalThreadSleepMicroseconds(LSM6DSL_GYRO_BIAS_SETTLING_US);
  482. }
  483. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++){
  484. devp->gyrobias[i] = (buff[i] / LSM6DSL_GYRO_BIAS_ACQ_TIMES);
  485. devp->gyrobias[i] *= devp->gyrosensitivity[i];
  486. }
  487. return msg;
  488. }
  489. /**
  490. * @brief Set bias values for the BaseGyroscope.
  491. * @note Bias must be expressed as DPS.
  492. * @note The bias buffer must be at least the same size of the BaseGyroscope
  493. * axes number.
  494. *
  495. * @param[in] ip pointer to @p BaseGyroscope interface.
  496. * @param[in] bp a buffer which contains biases.
  497. *
  498. * @return The operation status.
  499. * @retval MSG_OK if the function succeeded.
  500. */
  501. static msg_t gyro_set_bias(void *ip, float *bp) {
  502. LSM6DSLDriver* devp;
  503. uint32_t i;
  504. msg_t msg = MSG_OK;
  505. osalDbgCheck((ip != NULL) && (bp != NULL));
  506. /* Getting parent instance pointer.*/
  507. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  508. osalDbgAssert((devp->state == LSM6DSL_READY),
  509. "gyro_set_bias(), invalid state");
  510. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  511. devp->gyrobias[i] = bp[i];
  512. }
  513. return msg;
  514. }
  515. /**
  516. * @brief Reset bias values for the BaseGyroscope.
  517. * @note Default biases value are obtained from device datasheet when
  518. * available otherwise they are considered zero.
  519. *
  520. * @param[in] ip pointer to @p BaseGyroscope interface.
  521. *
  522. * @return The operation status.
  523. * @retval MSG_OK if the function succeeded.
  524. */
  525. static msg_t gyro_reset_bias(void *ip) {
  526. LSM6DSLDriver* devp;
  527. uint32_t i;
  528. msg_t msg = MSG_OK;
  529. osalDbgCheck(ip != NULL);
  530. /* Getting parent instance pointer.*/
  531. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  532. osalDbgAssert((devp->state == LSM6DSL_READY),
  533. "gyro_reset_bias(), invalid state");
  534. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  535. devp->gyrobias[i] = LSM6DSL_GYRO_BIAS;
  536. return msg;
  537. }
  538. /**
  539. * @brief Set sensitivity values for the BaseGyroscope.
  540. * @note Sensitivity must be expressed as DPS/LSB.
  541. * @note The sensitivity buffer must be at least the same size of the
  542. * BaseGyroscope axes number.
  543. *
  544. * @param[in] ip pointer to @p BaseGyroscope interface.
  545. * @param[in] sp a buffer which contains sensitivities.
  546. *
  547. * @return The operation status.
  548. * @retval MSG_OK if the function succeeded.
  549. */
  550. static msg_t gyro_set_sensivity(void *ip, float *sp) {
  551. LSM6DSLDriver* devp;
  552. uint32_t i;
  553. msg_t msg = MSG_OK;
  554. osalDbgCheck((ip != NULL) && (sp !=NULL));
  555. /* Getting parent instance pointer.*/
  556. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  557. osalDbgAssert((devp->state == LSM6DSL_READY),
  558. "gyro_set_sensivity(), invalid state");
  559. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  560. devp->gyrosensitivity[i] = sp[i];
  561. }
  562. return msg;
  563. }
  564. /**
  565. * @brief Reset sensitivity values for the BaseGyroscope.
  566. * @note Default sensitivities value are obtained from device datasheet.
  567. *
  568. * @param[in] ip pointer to @p BaseGyroscope interface.
  569. *
  570. * @return The operation status.
  571. * @retval MSG_OK if the function succeeded.
  572. * @retval MSG_RESET otherwise.
  573. */
  574. static msg_t gyro_reset_sensivity(void *ip) {
  575. LSM6DSLDriver* devp;
  576. uint32_t i;
  577. msg_t msg = MSG_OK;
  578. osalDbgCheck(ip != NULL);
  579. /* Getting parent instance pointer.*/
  580. devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
  581. osalDbgAssert((devp->state == LSM6DSL_READY),
  582. "gyro_reset_sensivity(), invalid state");
  583. if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_125DPS)
  584. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  585. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_125DPS;
  586. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_250DPS)
  587. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  588. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_250DPS;
  589. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_500DPS)
  590. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  591. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_500DPS;
  592. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_1000DPS)
  593. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  594. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_1000DPS;
  595. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_2000DPS)
  596. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  597. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_2000DPS;
  598. else {
  599. osalDbgAssert(FALSE, "gyro_reset_sensivity(), full scale issue");
  600. return MSG_RESET;
  601. }
  602. return msg;
  603. }
  604. /**
  605. * @brief Changes the LSM6DSLDriver gyroscope fullscale value.
  606. * @note This function also rescale sensitivities and biases based on
  607. * previous and next fullscale value.
  608. * @note A recalibration is highly suggested after calling this function.
  609. *
  610. * @param[in] devp pointer to @p BaseGyroscope interface.
  611. * @param[in] fs new fullscale value.
  612. *
  613. * @return The operation status.
  614. * @retval MSG_OK if the function succeeded.
  615. * @retval MSG_RESET otherwise.
  616. */
  617. static msg_t gyro_set_full_scale(LSM6DSLDriver *devp, lsm6dsl_gyro_fs_t fs) {
  618. float newfs, scale;
  619. uint8_t i, buff[2];
  620. msg_t msg = MSG_OK;
  621. osalDbgCheck(devp != NULL);
  622. osalDbgAssert((devp->state == LSM6DSL_READY),
  623. "gyro_set_full_scale(), invalid state");
  624. #if LSM6DSL_USE_I2C
  625. osalDbgAssert((devp->config->i2cp->state == I2C_READY),
  626. "gyro_set_full_scale(), channel not ready");
  627. #endif
  628. if(fs == LSM6DSL_GYRO_FS_125DPS) {
  629. newfs = LSM6DSL_GYRO_125DPS;
  630. }
  631. else if(fs == LSM6DSL_GYRO_FS_250DPS) {
  632. newfs = LSM6DSL_GYRO_250DPS;
  633. }
  634. else if(fs == LSM6DSL_GYRO_FS_500DPS) {
  635. newfs = LSM6DSL_GYRO_500DPS;
  636. }
  637. else if(fs == LSM6DSL_GYRO_FS_1000DPS) {
  638. newfs = LSM6DSL_GYRO_1000DPS;
  639. }
  640. else if(fs == LSM6DSL_GYRO_FS_2000DPS) {
  641. newfs = LSM6DSL_GYRO_2000DPS;
  642. }
  643. else {
  644. return MSG_RESET;
  645. }
  646. if(newfs != devp->gyrofullscale) {
  647. scale = newfs / devp->gyrofullscale;
  648. devp->gyrofullscale = newfs;
  649. #if LSM6DSL_USE_I2C
  650. #if LSM6DSL_SHARED_I2C
  651. i2cAcquireBus(devp->config->i2cp);
  652. i2cStart(devp->config->i2cp,
  653. devp->config->i2ccfg);
  654. #endif /* LSM6DSL_SHARED_I2C */
  655. /* Updating register.*/
  656. msg = lsm6dslI2CReadRegister(devp->config->i2cp,
  657. devp->config->slaveaddress,
  658. LSM6DSL_AD_CTRL2_G, &buff[1], 1);
  659. #if LSM6DSL_SHARED_I2C
  660. i2cReleaseBus(devp->config->i2cp);
  661. #endif /* LSM6DSL_SHARED_I2C */
  662. #endif /* LSM6DSL_USE_I2C */
  663. buff[1] &= ~(LSMDSL_CTRL2_G_FS_MASK);
  664. buff[1] |= fs;
  665. buff[0] = LSM6DSL_AD_CTRL2_G;
  666. #if LSM6DSL_USE_I2C
  667. #if LSM6DSL_SHARED_I2C
  668. i2cAcquireBus(devp->config->i2cp);
  669. i2cStart(devp->config->i2cp,
  670. devp->config->i2ccfg);
  671. #endif /* LSM6DSL_SHARED_I2C */
  672. lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
  673. buff, 1);
  674. #if LSM6DSL_SHARED_I2C
  675. i2cReleaseBus(devp->config->i2cp);
  676. #endif /* LSM6DSL_SHARED_I2C */
  677. #endif /* LSM6DSL_USE_I2C */
  678. /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
  679. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  680. devp->gyrosensitivity[i] *= scale;
  681. devp->gyrobias[i] *= scale;
  682. }
  683. }
  684. return msg;
  685. }
  686. static const struct LSM6DSLVMT vmt_device = {
  687. (size_t)0,
  688. acc_set_full_scale, gyro_set_full_scale
  689. };
  690. static const struct BaseAccelerometerVMT vmt_accelerometer = {
  691. sizeof(struct LSM6DSLVMT*),
  692. acc_get_axes_number, acc_read_raw, acc_read_cooked,
  693. acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
  694. };
  695. static const struct BaseGyroscopeVMT vmt_gyroscope = {
  696. sizeof(struct LSM6DSLVMT*) + sizeof(BaseAccelerometer),
  697. gyro_get_axes_number, gyro_read_raw, gyro_read_cooked,
  698. gyro_sample_bias, gyro_set_bias, gyro_reset_bias,
  699. gyro_set_sensivity, gyro_reset_sensivity
  700. };
  701. /*===========================================================================*/
  702. /* Driver exported functions. */
  703. /*===========================================================================*/
  704. /**
  705. * @brief Initializes an instance.
  706. *
  707. * @param[out] devp pointer to the @p LSM6DSLDriver object
  708. *
  709. * @init
  710. */
  711. void lsm6dslObjectInit(LSM6DSLDriver *devp) {
  712. devp->vmt = &vmt_device;
  713. devp->acc_if.vmt = &vmt_accelerometer;
  714. devp->gyro_if.vmt = &vmt_gyroscope;
  715. devp->config = NULL;
  716. devp->accaxes = LSM6DSL_ACC_NUMBER_OF_AXES;
  717. devp->gyroaxes = LSM6DSL_GYRO_NUMBER_OF_AXES;
  718. devp->state = LSM6DSL_STOP;
  719. }
  720. /**
  721. * @brief Configures and activates LSM6DSL Complex Driver peripheral.
  722. *
  723. * @param[in] devp pointer to the @p LSM6DSLDriver object
  724. * @param[in] config pointer to the @p LSM6DSLConfig object
  725. *
  726. * @api
  727. */
  728. void lsm6dslStart(LSM6DSLDriver *devp, const LSM6DSLConfig *config) {
  729. uint32_t i;
  730. uint8_t cr[11];
  731. osalDbgCheck((devp != NULL) && (config != NULL));
  732. osalDbgAssert((devp->state == LSM6DSL_STOP) ||
  733. (devp->state == LSM6DSL_READY),
  734. "lsm6dslStart(), invalid state");
  735. devp->config = config;
  736. /* Enforcing multiple write configuration.*/
  737. {
  738. cr[0] = LSM6DSL_AD_CTRL3_C;
  739. cr[1] = LSMDSL_CTRL3_C_IF_INC;
  740. }
  741. #if LSM6DSL_USE_I2C
  742. #if LSM6DSL_SHARED_I2C
  743. i2cAcquireBus(devp->config->i2cp);
  744. #endif /* LSM6DSL_SHARED_I2C */
  745. i2cStart(devp->config->i2cp, devp->config->i2ccfg);
  746. lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
  747. cr, 1);
  748. #if LSM6DSL_SHARED_I2C
  749. i2cReleaseBus(devp->config->i2cp);
  750. #endif /* LSM6DSL_SHARED_I2C */
  751. #endif /* LSM6DSL_USE_I2C */
  752. /* Configuring all the control registers.*/
  753. /* Multiple write starting address.*/
  754. cr[0] = LSM6DSL_AD_CTRL1_XL;
  755. /* Control register 1 configuration block.*/
  756. {
  757. cr[1] = devp->config->accoutdatarate |
  758. devp->config->accfullscale;
  759. }
  760. /* Control register 2 configuration block.*/
  761. {
  762. cr[2] = devp->config->gyrooutdatarate |
  763. devp->config->gyrofullscale;
  764. }
  765. /* Control register 3 configuration block.*/
  766. {
  767. cr[3] = LSMDSL_CTRL3_C_IF_INC;
  768. #if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
  769. cr[3] |= devp->config->endianness | devp->config->blockdataupdate;
  770. #endif
  771. }
  772. /* Control register 4 configuration block.*/
  773. {
  774. cr[4] = 0;
  775. #if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
  776. if(devp->config->gyrolowpassfilter != LSM6DSL_GYRO_LPF_DISABLED) {
  777. cr[4] |= LSMDSL_CTRL4_C_LPF1_SEL_G;
  778. }
  779. else {
  780. /* Nothing to do. */
  781. }
  782. #endif
  783. }
  784. /* Control register 5 configuration block.*/
  785. {
  786. cr[5] = 0;
  787. }
  788. /* Control register 6 configuration block.*/
  789. {
  790. cr[6] = 0;
  791. #if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
  792. cr[6] |= devp->config->acclpmode;
  793. #endif
  794. #if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
  795. if(devp->config->gyrolowpassfilter != LSM6DSL_GYRO_LPF_DISABLED) {
  796. cr[6] |= devp->config->gyrolowpassfilter;
  797. }
  798. else {
  799. /* Nothing to do. */
  800. }
  801. #endif
  802. }
  803. /* Control register 7 configuration block.*/
  804. {
  805. cr[7] = 0;
  806. #if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
  807. cr[7] |= devp->config->gyrolpmode;
  808. #endif
  809. }
  810. /* Control register 8 configuration block.*/
  811. {
  812. cr[8] = 0;
  813. }
  814. /* Control register 9 configuration block.*/
  815. {
  816. cr[9] = 0;
  817. }
  818. /* Control register 10 configuration block.*/
  819. {
  820. cr[10] = 0;
  821. }
  822. #if LSM6DSL_USE_I2C
  823. #if LSM6DSL_SHARED_I2C
  824. i2cAcquireBus(devp->config->i2cp);
  825. i2cStart(devp->config->i2cp, devp->config->i2ccfg);
  826. #endif /* LSM6DSL_SHARED_I2C */
  827. lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
  828. cr, 10);
  829. #if LSM6DSL_SHARED_I2C
  830. i2cReleaseBus(devp->config->i2cp);
  831. #endif /* LSM6DSL_SHARED_I2C */
  832. #endif /* LSM6DSL_USE_I2C */
  833. /* Storing sensitivity according to user settings */
  834. if(devp->config->accfullscale == LSM6DSL_ACC_FS_2G) {
  835. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  836. if(devp->config->accsensitivity == NULL)
  837. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_2G;
  838. else
  839. devp->accsensitivity[i] = devp->config->accsensitivity[i];
  840. }
  841. devp->accfullscale = LSM6DSL_ACC_2G;
  842. }
  843. else if(devp->config->accfullscale == LSM6DSL_ACC_FS_4G) {
  844. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  845. if(devp->config->accsensitivity == NULL)
  846. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_4G;
  847. else
  848. devp->accsensitivity[i] = devp->config->accsensitivity[i];
  849. }
  850. devp->accfullscale = LSM6DSL_ACC_4G;
  851. }
  852. else if(devp->config->accfullscale == LSM6DSL_ACC_FS_8G) {
  853. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  854. if(devp->config->accsensitivity == NULL)
  855. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_8G;
  856. else
  857. devp->accsensitivity[i] = devp->config->accsensitivity[i];
  858. }
  859. devp->accfullscale = LSM6DSL_ACC_8G;
  860. }
  861. else if(devp->config->accfullscale == LSM6DSL_ACC_FS_16G) {
  862. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
  863. if(devp->config->accsensitivity == NULL)
  864. devp->accsensitivity[i] = LSM6DSL_ACC_SENS_16G;
  865. else
  866. devp->accsensitivity[i] = devp->config->accsensitivity[i];
  867. }
  868. devp->accfullscale = LSM6DSL_ACC_16G;
  869. }
  870. else
  871. osalDbgAssert(FALSE, "lsm6dslStart(), accelerometer full scale issue");
  872. /* Storing bias information */
  873. if(devp->config->accbias != NULL)
  874. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  875. devp->accbias[i] = devp->config->accbias[i];
  876. else
  877. for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
  878. devp->accbias[i] = LSM6DSL_ACC_BIAS;
  879. if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_125DPS) {
  880. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  881. if(devp->config->gyrosensitivity == NULL)
  882. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_125DPS;
  883. else
  884. devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
  885. }
  886. devp->gyrofullscale = LSM6DSL_GYRO_125DPS;
  887. }
  888. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_250DPS) {
  889. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  890. if(devp->config->gyrosensitivity == NULL)
  891. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_250DPS;
  892. else
  893. devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
  894. }
  895. devp->gyrofullscale = LSM6DSL_GYRO_250DPS;
  896. }
  897. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_500DPS) {
  898. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  899. if(devp->config->gyrosensitivity == NULL)
  900. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_500DPS;
  901. else
  902. devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
  903. }
  904. devp->gyrofullscale = LSM6DSL_GYRO_500DPS;
  905. }
  906. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_1000DPS) {
  907. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  908. if(devp->config->gyrosensitivity == NULL)
  909. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_1000DPS;
  910. else
  911. devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
  912. }
  913. devp->gyrofullscale = LSM6DSL_GYRO_1000DPS;
  914. }
  915. else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_2000DPS) {
  916. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
  917. if(devp->config->gyrosensitivity == NULL)
  918. devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_2000DPS;
  919. else
  920. devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
  921. }
  922. devp->gyrofullscale = LSM6DSL_GYRO_2000DPS;
  923. }
  924. else
  925. osalDbgAssert(FALSE, "lsm6dslStart(), gyroscope full scale issue");
  926. /* Storing bias information */
  927. if(devp->config->gyrobias != NULL)
  928. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  929. devp->gyrobias[i] = devp->config->gyrobias[i];
  930. else
  931. for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
  932. devp->gyrobias[i] = LSM6DSL_GYRO_BIAS;
  933. /* This is the MEMS transient recovery time */
  934. osalThreadSleepMilliseconds(5);
  935. devp->state = LSM6DSL_READY;
  936. }
  937. /**
  938. * @brief Deactivates the LSM6DSL Complex Driver peripheral.
  939. *
  940. * @param[in] devp pointer to the @p LSM6DSLDriver object
  941. *
  942. * @api
  943. */
  944. void lsm6dslStop(LSM6DSLDriver *devp) {
  945. uint8_t cr[2];
  946. osalDbgCheck(devp != NULL);
  947. osalDbgAssert((devp->state == LSM6DSL_STOP) || (devp->state == LSM6DSL_READY),
  948. "lsm6dslStop(), invalid state");
  949. if (devp->state == LSM6DSL_READY) {
  950. #if LSM6DSL_USE_I2C
  951. #if LSM6DSL_SHARED_I2C
  952. i2cAcquireBus(devp->config->i2cp);
  953. i2cStart(devp->config->i2cp, devp->config->i2ccfg);
  954. #endif /* LSM6DSL_SHARED_I2C */
  955. cr[0] = LSM6DSL_AD_CTRL1_XL;
  956. /* Disabling accelerometer.*/
  957. cr[1] = LSM6DSL_ACC_ODR_PD;
  958. /* Disabling gyroscope.*/
  959. cr[2] = LSM6DSL_GYRO_ODR_PD;
  960. lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
  961. cr, 2);
  962. i2cStop(devp->config->i2cp);
  963. #if LSM6DSL_SHARED_I2C
  964. i2cReleaseBus(devp->config->i2cp);
  965. #endif /* LSM6DSL_SHARED_I2C */
  966. #endif /* LSM6DSL_USE_I2C */
  967. }
  968. devp->state = LSM6DSL_STOP;
  969. }
  970. /** @} */