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