ChibiOS 21.11.4
lsm303agr.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2016..2023 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 lsm303agr.c
23 * @brief LSM303AGR MEMS interface module code.
24 *
25 * @addtogroup LSM303AGR
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "lsm303agr.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 * @brief Accelerometer and Compass Slave Address.
47 */
48typedef enum {
49 LSM303AGR_SAD_ACC = 0x19, /**< SAD for accelerometer. */
50 LSM303AGR_SAD_COMP = 0x1E /**< SAD for compass. */
52
53/*===========================================================================*/
54/* Driver local functions. */
55/*===========================================================================*/
56
57/**
58 * @brief Reads registers value using I2C.
59 * @pre The I2C interface must be initialized and the driver started.
60 * @note IF_ADD_INC bit must be 1 in CTRL_REG8.
61 *
62 * @param[in] i2cp pointer to the I2C interface.
63 * @param[in] sad slave address without R bit.
64 * @param[in] reg first sub-register address.
65 * @param[in] rxbuf receiving buffer.
66 * @param[in] n size of rxbuf.
67 * @return the operation status.
68 */
70 uint8_t reg, uint8_t *rxbuf, size_t n) {
71
72 uint8_t txbuf = reg | LSM303AGR_MS;
73 return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
75}
76
77/**
78 * @brief Writes a value into a register using I2C.
79 * @pre The I2C interface must be initialized and the driver started.
80 *
81 * @param[in] i2cp pointer to the I2C interface.
82 * @param[in] sad slave address without R bit.
83 * @param[in] txbuf buffer containing sub-address value in first position
84 * and values to write.
85 * @param[in] n size of txbuf less one (not considering the first
86 * element).
87 * @return the operation status.
88 */
90 uint8_t *txbuf, size_t n) {
91 if (n != 1)
92 *txbuf |= LSM303AGR_MS;
93 return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
95}
96
97/**
98 * @brief Return the number of axes of the BaseAccelerometer.
99 *
100 * @param[in] ip pointer to @p BaseAccelerometer interface.
101 *
102 * @return the number of axes.
103 */
104static size_t acc_get_axes_number(void *ip) {
105 (void)ip;
106
108}
109
110/**
111 * @brief Retrieves raw data from the BaseAccelerometer.
112 * @note This data is retrieved from MEMS register without any algebraical
113 * manipulation.
114 * @note The axes array must be at least the same size of the
115 * BaseAccelerometer axes number.
116 *
117 * @param[in] ip pointer to @p BaseAccelerometer interface.
118 * @param[out] axes a buffer which would be filled with raw data.
119 *
120 * @return The operation status.
121 * @retval MSG_OK if the function succeeded.
122 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
123 * be retrieved using @p i2cGetErrors().
124 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
125 */
126static msg_t acc_read_raw(void *ip, int32_t axes[]) {
127 LSM303AGRDriver* devp;
128 uint8_t buff [LSM303AGR_ACC_NUMBER_OF_AXES * 2], i;
129 int16_t tmp;
130 msg_t msg;
131
132 osalDbgCheck((ip != NULL) && (axes != NULL));
133
134 /* Getting parent instance pointer.*/
136
137 osalDbgAssert((devp->state == LSM303AGR_READY),
138 "acc_read_raw(), invalid state");
139 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
140 "acc_read_raw(), channel not ready");
141
142#if LSM303AGR_SHARED_I2C
143 i2cAcquireBus(devp->config->i2cp);
144 i2cStart(devp->config->i2cp,
145 devp->config->i2ccfg);
146#endif /* LSM303AGR_SHARED_I2C */
147
148 msg = lsm303agrI2CReadRegister(devp->config->i2cp, LSM303AGR_SAD_ACC,
151
152#if LSM303AGR_SHARED_I2C
153 i2cReleaseBus(devp->config->i2cp);
154#endif /* LSM303AGR_SHARED_I2C */
155
156 if(msg == MSG_OK)
157 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
158 tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
159 axes[i] = (int32_t)tmp;
160 }
161 return msg;
162}
163
164/**
165 * @brief Retrieves cooked data from the BaseAccelerometer.
166 * @note This data is manipulated according to the formula
167 * cooked = (raw * sensitivity) - bias.
168 * @note Final data is expressed as milli-G.
169 * @note The axes array must be at least the same size of the
170 * BaseAccelerometer axes number.
171 *
172 * @param[in] ip pointer to @p BaseAccelerometer interface.
173 * @param[out] axes a buffer which would be filled with cooked data.
174 *
175 * @return The operation status.
176 * @retval MSG_OK if the function succeeded.
177 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
178 * be retrieved using @p i2cGetErrors().
179 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
180 */
181static msg_t acc_read_cooked(void *ip, float axes[]) {
182 LSM303AGRDriver* devp;
183 uint32_t i;
184 int32_t raw[LSM303AGR_ACC_NUMBER_OF_AXES];
185 msg_t msg;
186
187 osalDbgCheck((ip != NULL) && (axes != NULL));
188
189 /* Getting parent instance pointer.*/
191
192 osalDbgAssert((devp->state == LSM303AGR_READY),
193 "acc_read_cooked(), invalid state");
194
195 msg = acc_read_raw(ip, raw);
196 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
197 axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
198 }
199 return msg;
200}
201
202/**
203 * @brief Set bias values for the BaseAccelerometer.
204 * @note Bias must be expressed as milli-G.
205 * @note The bias buffer must be at least the same size of the
206 * BaseAccelerometer axes number.
207 *
208 * @param[in] ip pointer to @p BaseAccelerometer interface.
209 * @param[in] bp a buffer which contains biases.
210 *
211 * @return The operation status.
212 * @retval MSG_OK if the function succeeded.
213 */
214static msg_t acc_set_bias(void *ip, float *bp) {
215 LSM303AGRDriver* devp;
216 uint32_t i;
217 msg_t msg = MSG_OK;
218
219 osalDbgCheck((ip != NULL) && (bp != NULL));
220
221 /* Getting parent instance pointer.*/
223
224 osalDbgAssert((devp->state == LSM303AGR_READY),
225 "acc_set_bias(), invalid state");
226
227 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
228 devp->accbias[i] = bp[i];
229 }
230 return msg;
231}
232
233/**
234 * @brief Reset bias values for the BaseAccelerometer.
235 * @note Default biases value are obtained from device datasheet when
236 * available otherwise they are considered zero.
237 *
238 * @param[in] ip pointer to @p BaseAccelerometer interface.
239 *
240 * @return The operation status.
241 * @retval MSG_OK if the function succeeded.
242 */
243static msg_t acc_reset_bias(void *ip) {
244 LSM303AGRDriver* devp;
245 uint32_t i;
246 msg_t msg = MSG_OK;
247
248 osalDbgCheck(ip != NULL);
249
250 /* Getting parent instance pointer.*/
252
253 osalDbgAssert((devp->state == LSM303AGR_READY),
254 "acc_reset_bias(), invalid state");
255
256 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
257 devp->accbias[i] = LSM303AGR_ACC_BIAS;
258 return msg;
259}
260
261/**
262 * @brief Set sensitivity values for the BaseAccelerometer.
263 * @note Sensitivity must be expressed as milli-G/LSB.
264 * @note The sensitivity buffer must be at least the same size of the
265 * BaseAccelerometer axes number.
266 *
267 * @param[in] ip pointer to @p BaseAccelerometer interface.
268 * @param[in] sp a buffer which contains sensitivities.
269 *
270 * @return The operation status.
271 * @retval MSG_OK if the function succeeded.
272 */
273static msg_t acc_set_sensivity(void *ip, float *sp) {
274 LSM303AGRDriver* devp;
275 uint32_t i;
276 msg_t msg = MSG_OK;
277
278 /* Getting parent instance pointer.*/
280
281 osalDbgCheck((ip != NULL) && (sp != NULL));
282
283 osalDbgAssert((devp->state == LSM303AGR_READY),
284 "acc_set_sensivity(), invalid state");
285
286 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
287 devp->accsensitivity[i] = sp[i];
288 }
289 return msg;
290}
291
292/**
293 * @brief Reset sensitivity values for the BaseAccelerometer.
294 * @note Default sensitivities value are obtained from device datasheet.
295 *
296 * @param[in] ip pointer to @p BaseAccelerometer interface.
297 *
298 * @return The operation status.
299 * @retval MSG_OK if the function succeeded.
300 * @retval MSG_RESET otherwise.
301 */
302static msg_t acc_reset_sensivity(void *ip) {
303 LSM303AGRDriver* devp;
304 uint32_t i;
305 msg_t msg = MSG_OK;
306
307 osalDbgCheck(ip != NULL);
308
309 /* Getting parent instance pointer.*/
311
312 osalDbgAssert((devp->state == LSM303AGR_READY),
313 "acc_reset_sensivity(), invalid state");
314
315 if(devp->config->accfullscale == LSM303AGR_ACC_FS_2G) {
316 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
317 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_2G;
318 }
319 }
320 else if(devp->config->accfullscale == LSM303AGR_ACC_FS_4G) {
321 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
322 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_4G;
323 }
324 }
325 else if(devp->config->accfullscale == LSM303AGR_ACC_FS_8G) {
326 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
327 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_8G;
328 }
329 }
330 else if(devp->config->accfullscale == LSM303AGR_ACC_FS_16G) {
331 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
332 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_16G;
333 }
334 }
335 else {
336 osalDbgAssert(FALSE, "reset_sensivity(), accelerometer full scale issue");
337 msg = MSG_RESET;
338 }
339 return msg;
340}
341
342/**
343 * @brief Changes the LSM303AGRDriver accelerometer fullscale value.
344 * @note This function also rescale sensitivities and biases based on
345 * previous and next fullscale value.
346 * @note A recalibration is highly suggested after calling this function.
347 *
348 * @param[in] devp pointer to @p LSM303AGRDriver interface.
349 * @param[in] fs new fullscale value.
350 *
351 * @return The operation status.
352 * @retval MSG_OK if the function succeeded.
353 * @retval MSG_RESET otherwise.
354 */
357 float newfs, scale;
358 uint8_t i, buff[2];
359 msg_t msg;
360
361 osalDbgCheck(devp != NULL);
362
363 osalDbgAssert((devp->state == LSM303AGR_READY),
364 "acc_set_full_scale(), invalid state");
365 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
366 "acc_set_full_scale(), channel not ready");
367
368 /* Computing new fullscale value.*/
369 if(fs == LSM303AGR_ACC_FS_2G) {
370 newfs = LSM303AGR_ACC_2G;
371 msg = MSG_OK;
372 }
373 else if(fs == LSM303AGR_ACC_FS_4G) {
374 newfs = LSM303AGR_ACC_4G;
375 msg = MSG_OK;
376 }
377 else if(fs == LSM303AGR_ACC_FS_8G) {
378 newfs = LSM303AGR_ACC_8G;
379 msg = MSG_OK;
380 }
381 else if(fs == LSM303AGR_ACC_FS_16G) {
382 newfs = LSM303AGR_ACC_16G;
383 msg = MSG_OK;
384 }
385 else {
386 msg = MSG_RESET;
387 }
388
389 if((msg == MSG_OK) &&
390 (newfs != devp->compfullscale)) {
391 /* Computing scale value.*/
392 scale = newfs / devp->accfullscale;
393 devp->accfullscale = newfs;
394
395#if LSM303AGR_SHARED_I2C
396 i2cAcquireBus(devp->config->i2cp);
397 i2cStart(devp->config->i2cp,
398 devp->config->i2ccfg);
399#endif /* LSM303AGR_SHARED_I2C */
400
401 /* Updating register.*/
402 msg = lsm303agrI2CReadRegister(devp->config->i2cp,
405 &buff[1], 1);
406
407#if LSM303AGR_SHARED_I2C
408 i2cReleaseBus(devp->config->i2cp);
409#endif /* LSM303AGR_SHARED_I2C */
410
411 if(msg == MSG_OK) {
412
413 buff[1] &= ~(LSM303AGR_CTRL_REG4_A_FS_MASK);
414 buff[1] |= fs;
415 buff[0] = LSM303AGR_AD_CTRL_REG4_A;
416
417#if LSM303AGR_SHARED_I2C
418 i2cAcquireBus(devp->config->i2cp);
419 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
420#endif /* LSM303AGR_SHARED_I2C */
421
422 msg = lsm303agrI2CWriteRegister(devp->config->i2cp,
423 LSM303AGR_SAD_ACC, buff, 1);
424
425#if LSM303AGR_SHARED_I2C
426 i2cReleaseBus(devp->config->i2cp);
427#endif /* LSM303AGR_SHARED_I2C */
428 }
429 if(msg == MSG_OK) {
430
431 /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
432 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
433 devp->accsensitivity[i] *= scale;
434 devp->accbias[i] *= scale;
435 }
436 }
437 }
438 return msg;
439}
440
441/**
442 * @brief Return the number of axes of the BaseCompass.
443 *
444 * @param[in] ip pointer to @p BaseCompass interface
445 *
446 * @return the number of axes.
447 */
448static size_t comp_get_axes_number(void *ip) {
449
450 osalDbgCheck(ip != NULL);
452}
453
454/**
455 * @brief Retrieves raw data from the BaseCompass.
456 * @note This data is retrieved from MEMS register without any algebraical
457 * manipulation.
458 * @note The axes array must be at least the same size of the
459 * BaseCompass axes number.
460 *
461 * @param[in] ip pointer to @p BaseCompass interface.
462 * @param[out] axes a buffer which would be filled with raw data.
463 *
464 * @return The operation status.
465 * @retval MSG_OK if the function succeeded.
466 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
467 * be retrieved using @p i2cGetErrors().
468 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
469 */
470static msg_t comp_read_raw(void *ip, int32_t axes[]) {
471 LSM303AGRDriver* devp;
472 uint8_t buff [LSM303AGR_COMP_NUMBER_OF_AXES * 2], i;
473 int16_t tmp;
474 msg_t msg;
475
476 osalDbgCheck((ip != NULL) && (axes != NULL));
477
478 /* Getting parent instance pointer.*/
480
481 osalDbgAssert((devp->state == LSM303AGR_READY),
482 "comp_read_raw(), invalid state");
483 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
484 "comp_read_raw(), channel not ready");
485
486#if LSM303AGR_SHARED_I2C
487 i2cAcquireBus(devp->config->i2cp);
488 i2cStart(devp->config->i2cp,
489 devp->config->i2ccfg);
490#endif /* LSM303AGR_SHARED_I2C */
491 msg = lsm303agrI2CReadRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
494
495#if LSM303AGR_SHARED_I2C
496 i2cReleaseBus(devp->config->i2cp);
497#endif /* LSM303AGR_SHARED_I2C */
498
499 if(msg == MSG_OK)
500 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
501 tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
502 axes[i] = (int32_t)tmp;
503 }
504 return msg;
505}
506
507/**
508 * @brief Retrieves cooked data from the BaseCompass.
509 * @note This data is manipulated according to the formula
510 * cooked = (raw * sensitivity) - bias.
511 * @note Final data is expressed as G.
512 * @note The axes array must be at least the same size of the
513 * BaseCompass axes number.
514 *
515 * @param[in] ip pointer to @p BaseCompass interface.
516 * @param[out] axes a buffer which would be filled with cooked data.
517 *
518 * @return The operation status.
519 * @retval MSG_OK if the function succeeded.
520 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
521 * be retrieved using @p i2cGetErrors().
522 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
523 */
524static msg_t comp_read_cooked(void *ip, float axes[]) {
525 LSM303AGRDriver* devp;
526 uint32_t i;
528 msg_t msg;
529
530 osalDbgCheck((ip != NULL) && (axes != NULL));
531
532
533 /* Getting parent instance pointer.*/
535
536 osalDbgAssert((devp->state == LSM303AGR_READY),
537 "comp_read_cooked(), invalid state");
538
539 msg = comp_read_raw(ip, raw);
540 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES ; i++) {
541 axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i];
542 }
543 return msg;
544}
545
546/**
547 * @brief Set bias values for the BaseCompass.
548 * @note Bias must be expressed as G.
549 * @note The bias buffer must be at least the same size of the
550 * BaseCompass axes number.
551 *
552 * @param[in] ip pointer to @p BaseCompass interface.
553 * @param[in] bp a buffer which contains biases.
554 *
555 * @return The operation status.
556 * @retval MSG_OK if the function succeeded.
557 */
558static msg_t comp_set_bias(void *ip, float *bp) {
559 LSM303AGRDriver* devp;
560 uint32_t i;
561 msg_t msg = MSG_OK;
562
563 osalDbgCheck((ip != NULL) && (bp != NULL));
564
565 /* Getting parent instance pointer.*/
567
568 osalDbgAssert((devp->state == LSM303AGR_READY),
569 "comp_set_bias(), invalid state");
570
571 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
572 devp->compbias[i] = bp[i];
573 }
574 return msg;
575}
576
577/**
578 * @brief Reset bias values for the BaseCompass.
579 * @note Default biases value are obtained from device datasheet when
580 * available otherwise they are considered zero.
581 *
582 * @param[in] ip pointer to @p BaseCompass interface.
583 *
584 * @return The operation status.
585 * @retval MSG_OK if the function succeeded.
586 */
587static msg_t comp_reset_bias(void *ip) {
588 LSM303AGRDriver* devp;
589 uint32_t i;
590 msg_t msg = MSG_OK;
591
592 osalDbgCheck(ip != NULL);
593
594 /* Getting parent instance pointer.*/
596
597 osalDbgAssert((devp->state == LSM303AGR_READY),
598 "comp_reset_bias(), invalid state");
599
600 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++)
601 devp->compbias[i] = LSM303AGR_COMP_BIAS;
602 return msg;
603}
604
605/**
606 * @brief Set sensitivity values for the BaseCompass.
607 * @note Sensitivity must be expressed as G/LSB.
608 * @note The sensitivity buffer must be at least the same size of the
609 * BaseCompass axes number.
610 *
611 * @param[in] ip pointer to @p BaseCompass interface.
612 * @param[in] sp a buffer which contains sensitivities.
613 *
614 * @return The operation status.
615 * @retval MSG_OK if the function succeeded.
616 */
617static msg_t comp_set_sensivity(void *ip, float *sp) {
618 LSM303AGRDriver* devp;
619 uint32_t i;
620 msg_t msg = MSG_OK;
621
622 /* Getting parent instance pointer.*/
624
625 osalDbgCheck((ip != NULL) && (sp != NULL));
626
627 osalDbgAssert((devp->state == LSM303AGR_READY),
628 "comp_set_sensivity(), invalid state");
629
630 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
631 devp->compsensitivity[i] = sp[i];
632 }
633 return msg;
634}
635
636/**
637 * @brief Reset sensitivity values for the BaseCompass.
638 * @note Default sensitivities value are obtained from device datasheet.
639 *
640 * @param[in] ip pointer to @p BaseCompass interface.
641 *
642 * @return The operation status.
643 * @retval MSG_OK if the function succeeded.
644 * @retval MSG_RESET otherwise.
645 */
646static msg_t comp_reset_sensivity(void *ip) {
647 LSM303AGRDriver* devp;
648 uint32_t i;
649 msg_t msg = MSG_OK;
650
651 osalDbgCheck(ip != NULL);
652
653 /* Getting parent instance pointer.*/
655
656 osalDbgAssert((devp->state == LSM303AGR_READY),
657 "comp_reset_sensivity(), invalid state");
658
659 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++)
660 devp->compsensitivity[i] = LSM303AGR_COMP_SENS_50GA;
661
662 return msg;
663}
664
665static const struct LSM303AGRVMT vmt_device = {
666 (size_t)0,
668};
669
675
681
682/*===========================================================================*/
683/* Driver exported functions. */
684/*===========================================================================*/
685
686/**
687 * @brief Initializes an instance.
688 *
689 * @param[out] devp pointer to the @p LSM303AGRDriver object
690 *
691 * @init
692 */
694 devp->vmt = &vmt_device;
696 devp->comp_if.vmt = &vmt_compass;
697
698 devp->config = NULL;
699
700 devp->accaxes = LSM303AGR_ACC_NUMBER_OF_AXES;
701 devp->compaxes = LSM303AGR_COMP_NUMBER_OF_AXES;
702
703 devp->state = LSM303AGR_STOP;
704}
705
706/**
707 * @brief Configures and activates LSM303AGR Complex Driver peripheral.
708 *
709 * @param[in] devp pointer to the @p LSM303AGRDriver object
710 * @param[in] config pointer to the @p LSM303AGRConfig object
711 *
712 * @api
713 */
715 uint32_t i;
716 uint8_t cr[6];
717 osalDbgCheck((devp != NULL) && (config != NULL));
718
719 osalDbgAssert((devp->state == LSM303AGR_STOP) ||
720 (devp->state == LSM303AGR_READY),
721 "lsm303agrStart(), invalid state");
722
723 devp->config = config;
724
725 /* Configuring Accelerometer subsystem.*/
726
727 /* Multiple write starting address.*/
729
730 /* Control register 1 configuration block.*/
731 {
732 cr[1] = LSM303AGR_ACC_AE_XYZ | devp->config->accodr;
733#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
734 if(devp->config->accmode == LSM303AGR_ACC_MODE_LPOW)
736#endif
737 }
738
739 /* Control register 2 configuration block.*/
740 {
741 cr[2] = 0;
742 }
743
744 /* Control register 3 configuration block.*/
745 {
746 cr[3] = 0;
747 }
748
749 /* Control register 4 configuration block.*/
750 {
751 cr[4] = devp->config->accfullscale;
752#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
753 cr[4] |= devp->config->accendianess |
754 devp->config->accbdu;
755 if(devp->config->accmode == LSM303AGR_ACC_MODE_HRES)
757#endif
758 }
759
760 /* Storing sensitivity according to user settings */
761 if(devp->config->accfullscale == LSM303AGR_ACC_FS_2G) {
762 devp->accfullscale = LSM303AGR_ACC_2G;
763 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
764 if(devp->config->accsensitivity == NULL)
765 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_2G;
766 else
767 devp->accsensitivity[i] = devp->config->accsensitivity[i];
768 }
769 }
770 else if(devp->config->accfullscale == LSM303AGR_ACC_FS_4G) {
771 devp->accfullscale = LSM303AGR_ACC_4G;
772 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
773 if(devp->config->accsensitivity == NULL)
774 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_4G;
775 else
776 devp->accsensitivity[i] = devp->config->accsensitivity[i];
777 }
778 }
779 else if(devp->config->accfullscale == LSM303AGR_ACC_FS_8G) {
780 devp->accfullscale = LSM303AGR_ACC_8G;
781 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
782 if(devp->config->accsensitivity == NULL)
783 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_8G;
784 else
785 devp->accsensitivity[i] = devp->config->accsensitivity[i];
786 }
787 }
788 else if(devp->config->accfullscale == LSM303AGR_ACC_FS_16G) {
789 devp->accfullscale = LSM303AGR_ACC_16G;
790 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
791 if(devp->config->accsensitivity == NULL)
792 devp->accsensitivity[i] = LSM303AGR_ACC_SENS_16G;
793 else
794 devp->accsensitivity[i] = devp->config->accsensitivity[i];
795 }
796 }
797 else
798 osalDbgAssert(FALSE, "lsm303dlhcStart(), accelerometer full scale issue");
799
800 /* Storing bias information */
801 if(devp->config->accbias != NULL)
802 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
803 devp->accbias[i] = devp->config->accbias[i];
804 else
805 for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
806 devp->accbias[i] = LSM303AGR_ACC_BIAS;
807
808#if LSM303AGR_SHARED_I2C
809 i2cAcquireBus((devp)->config->i2cp);
810#endif /* LSM303AGR_SHARED_I2C */
811 i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
812
813 lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_ACC, cr, 4);
814
815#if LSM303AGR_SHARED_I2C
816 i2cReleaseBus((devp)->config->i2cp);
817#endif /* LSM303AGR_SHARED_I2C */
818
819 /* Configuring Compass subsystem */
820 /* Multiple write starting address.*/
822
823 /* Control register A configuration block.*/
824 {
825 cr[1] = devp->config->compodr;
826#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
827 cr[1] |= devp->config->compmode | devp->config->complp;
828#endif
829 }
830
831 /* Control register B configuration block.*/
832 {
833 cr[2] = 0;
834 }
835
836 /* Control register C configuration block.*/
837 {
838 cr[3] = 0;
839 }
840
841#if LSM303AGR_SHARED_I2C
842 i2cAcquireBus((devp)->config->i2cp);
843 i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
844#endif /* LSM303AGR_SHARED_I2C */
845
847 cr, 3);
848
849#if LSM303AGR_SHARED_I2C
850 i2cReleaseBus((devp)->config->i2cp);
851#endif /* LSM303AGR_SHARED_I2C */
852
853 devp->compfullscale = LSM303AGR_COMP_50GA;
854 for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
855 if(devp->config->compsensitivity == NULL) {
856 devp->compsensitivity[i] = LSM303AGR_COMP_SENS_50GA;
857 }
858 else {
859 devp->compsensitivity[i] = devp->config->compsensitivity[i];
860 }
861 }
862
863 /* This is the MEMS transient recovery time */
865
866 devp->state = LSM303AGR_READY;
867}
868
869/**
870 * @brief Deactivates the LSM303AGR Complex Driver peripheral.
871 *
872 * @param[in] devp pointer to the @p LSM303AGRDriver object
873 *
874 * @api
875 */
877 uint8_t cr[2];
878 osalDbgCheck(devp != NULL);
879
880 osalDbgAssert((devp->state == LSM303AGR_STOP) ||
881 (devp->state == LSM303AGR_READY),
882 "lsm303agrStop(), invalid state");
883
884 if (devp->state == LSM303AGR_READY) {
885#if LSM303AGR_SHARED_I2C
886 i2cAcquireBus((devp)->config->i2cp);
887 i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
888#endif /* LSM303AGR_SHARED_I2C */
889
890 /* Disabling accelerometer. */
894 cr, 1);
895
896 /* Disabling compass. */
900 cr, 1);
901
902 i2cStop((devp)->config->i2cp);
903#if LSM303AGR_SHARED_I2C
904 i2cReleaseBus((devp)->config->i2cp);
905#endif /* LSM303AGR_SHARED_I2C */
906 }
907 devp->state = LSM303AGR_STOP;
908}
909/** @} */
static size_t acc_get_axes_number(void *ip)
Return the number of axes of the BaseAccelerometer.
Definition adxl317.c:115
static msg_t acc_reset_sensivity(void *ip)
Reset sensitivity values for the BaseAccelerometer.
Definition adxl317.c:310
static msg_t acc_set_bias(void *ip, float *bp)
Set bias values for the BaseAccelerometer.
Definition adxl317.c:222
static msg_t acc_reset_bias(void *ip)
Reset bias values for the BaseAccelerometer.
Definition adxl317.c:251
static msg_t acc_set_sensivity(void *ip, float *sp)
Set sensitivity values for the BaseAccelerometer.
Definition adxl317.c:281
static msg_t acc_read_cooked(void *ip, float axes[])
Retrieves cooked data from the BaseAccelerometer.
Definition adxl317.c:185
static msg_t acc_read_raw(void *ip, int32_t axes[])
Retrieves raw data from the BaseAccelerometer.
Definition adxl317.c:137
static const struct BaseAccelerometerVMT vmt_accelerometer
Definition adxl317.c:332
static const struct ADXL317VMT vmt_device
Definition adxl317.c:328
static msg_t acc_set_full_scale(ADXL355Driver *devp, adxl355_acc_fs_t fs)
Changes the ADXL355Driver accelerometer fullscale value.
Definition adxl355.c:301
#define objGetInstance(type, ip)
Returns the instance pointer starting from an interface pointer.
Definition hal_objects.h:78
msg_t i2cStart(I2CDriver *i2cp, const I2CConfig *config)
Configures and activates the I2C peripheral.
Definition hal_i2c.c:94
msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout)
Sends data via the I2C bus.
Definition hal_i2c.c:187
void i2cReleaseBus(I2CDriver *i2cp)
Releases exclusive access to the I2C bus.
Definition hal_i2c.c:293
void i2cStop(I2CDriver *i2cp)
Deactivates the I2C peripheral.
Definition hal_i2c.c:131
void i2cAcquireBus(I2CDriver *i2cp)
Gains exclusive access to the I2C bus.
Definition hal_i2c.c:277
struct hal_i2c_driver I2CDriver
Type of a structure representing an I2C driver.
Definition hal_i2c_lld.h:88
@ I2C_READY
Ready.
Definition hal_i2c.h:87
static size_t comp_get_axes_number(void *ip)
Return the number of axes of the BaseCompass.
Definition lis3mdl.c:102
static msg_t comp_set_sensivity(void *ip, float *sp)
Set sensitivity values for the BaseCompass.
Definition lis3mdl.c:271
static msg_t comp_reset_bias(void *ip)
Reset bias values for the BaseCompass.
Definition lis3mdl.c:241
static msg_t comp_set_bias(void *ip, float *bp)
Set bias values for the BaseCompass.
Definition lis3mdl.c:212
static msg_t comp_reset_sensivity(void *ip)
Reset sensitivity values for the BaseCompass.
Definition lis3mdl.c:300
static msg_t comp_read_cooked(void *ip, float axes[])
Retrieves cooked data from the BaseCompass.
Definition lis3mdl.c:178
static const struct BaseCompassVMT vmt_compass
Definition lis3mdl.c:433
static msg_t comp_read_raw(void *ip, int32_t axes[])
Retrieves raw data from the BaseCompass.
Definition lis3mdl.c:124
static msg_t acc_set_full_scale(LSM303AGRDriver *devp, lsm303agr_acc_fs_t fs)
Changes the LSM303AGRDriver accelerometer fullscale value.
Definition lsm303agr.c:355
#define LSM303AGR_ACC_4G
Definition lsm303agr.h:75
#define LSM303AGR_COMP_50GA
Definition lsm303agr.h:96
static size_t comp_get_axes_number(void *ip)
Return the number of axes of the BaseCompass.
Definition lsm303agr.c:448
void lsm303agrObjectInit(LSM303AGRDriver *devp)
Initializes an instance.
Definition lsm303agr.c:693
static msg_t comp_set_sensivity(void *ip, float *sp)
Set sensitivity values for the BaseCompass.
Definition lsm303agr.c:617
#define LSM303AGR_CTRL_REG4_A_HR
Definition lsm303agr.h:235
static msg_t comp_reset_bias(void *ip)
Reset bias values for the BaseCompass.
Definition lsm303agr.c:587
#define LSM303AGR_COMP_BIAS
Definition lsm303agr.h:100
static size_t acc_get_axes_number(void *ip)
Return the number of axes of the BaseAccelerometer.
Definition lsm303agr.c:104
#define LSM303AGR_AD_OUTX_L_REG_M
Definition lsm303agr.h:171
void lsm303agrStart(LSM303AGRDriver *devp, const LSM303AGRConfig *config)
Configures and activates LSM303AGR Complex Driver peripheral.
Definition lsm303agr.c:714
void lsm303agrStop(LSM303AGRDriver *devp)
Deactivates the LSM303AGR Complex Driver peripheral.
Definition lsm303agr.c:876
#define LSM303AGR_ACC_SENS_8G
Definition lsm303agr.h:81
static msg_t acc_reset_sensivity(void *ip)
Reset sensitivity values for the BaseAccelerometer.
Definition lsm303agr.c:302
static msg_t comp_set_bias(void *ip, float *bp)
Set bias values for the BaseCompass.
Definition lsm303agr.c:558
static msg_t acc_set_bias(void *ip, float *bp)
Set bias values for the BaseAccelerometer.
Definition lsm303agr.c:214
static msg_t comp_reset_sensivity(void *ip)
Reset sensitivity values for the BaseCompass.
Definition lsm303agr.c:646
static msg_t lsm303agrI2CReadRegister(I2CDriver *i2cp, lsm303agr_sad_t sad, uint8_t reg, uint8_t *rxbuf, size_t n)
Reads registers value using I2C.
Definition lsm303agr.c:69
static msg_t lsm303agrI2CWriteRegister(I2CDriver *i2cp, lsm303agr_sad_t sad, uint8_t *txbuf, size_t n)
Writes a value into a register using I2C.
Definition lsm303agr.c:89
#define LSM303AGR_CTRL_REG4_A_FS_MASK
Definition lsm303agr.h:236
static msg_t comp_read_cooked(void *ip, float axes[])
Retrieves cooked data from the BaseCompass.
Definition lsm303agr.c:524
#define LSM303AGR_ACC_BIAS
Definition lsm303agr.h:84
#define LSM303AGR_COMP_SENS_50GA
Definition lsm303agr.h:98
#define LSM303AGR_ACC_SENS_2G
Definition lsm303agr.h:79
#define LSM303AGR_ACC_SENS_4G
Definition lsm303agr.h:80
static msg_t acc_reset_bias(void *ip)
Reset bias values for the BaseAccelerometer.
Definition lsm303agr.c:243
lsm303agr_acc_fs_t
LSM303AGR accelerometer subsystem full scale.
Definition lsm303agr.h:407
#define LSM303AGR_CTRL_REG1_A_LPEN
Definition lsm303agr.h:194
#define LSM303AGR_ACC_NUMBER_OF_AXES
LSM303AGR accelerometer subsystem characteristics.
Definition lsm303agr.h:72
#define LSM303AGR_ACC_2G
Definition lsm303agr.h:74
static msg_t acc_set_sensivity(void *ip, float *sp)
Set sensitivity values for the BaseAccelerometer.
Definition lsm303agr.c:273
static msg_t acc_read_cooked(void *ip, float axes[])
Retrieves cooked data from the BaseAccelerometer.
Definition lsm303agr.c:181
#define LSM303AGR_AD_CTRL_REG4_A
Definition lsm303agr.h:127
static msg_t acc_read_raw(void *ip, int32_t axes[])
Retrieves raw data from the BaseAccelerometer.
Definition lsm303agr.c:126
#define LSM303AGR_ACC_SENS_16G
Definition lsm303agr.h:82
#define LSM303AGR_MS
Definition lsm303agr.h:111
#define LSM303AGR_COMP_NUMBER_OF_AXES
LSM303AGR compass subsystem characteristics.
Definition lsm303agr.h:94
lsm303agr_sad_t
Accelerometer and Compass Slave Address.
Definition lsm303agr.c:48
#define LSM303AGR_AD_OUT_X_L_A
Definition lsm303agr.h:132
#define LSM303AGR_ACC_16G
Definition lsm303agr.h:77
#define LSM303AGR_ACC_8G
Definition lsm303agr.h:76
static msg_t comp_read_raw(void *ip, int32_t axes[])
Retrieves raw data from the BaseCompass.
Definition lsm303agr.c:470
#define LSM303AGR_AD_CTRL_REG1_A
Definition lsm303agr.h:124
#define LSM303AGR_AD_CFG_REG_A_M
Definition lsm303agr.h:163
@ LSM303AGR_ACC_AE_XYZ
Definition lsm303agr.h:441
@ LSM303AGR_ACC_AE_DISABLED
Definition lsm303agr.h:434
@ LSM303AGR_READY
Definition lsm303agr.h:512
@ LSM303AGR_STOP
Definition lsm303agr.h:511
@ LSM303AGR_ACC_FS_16G
Definition lsm303agr.h:411
@ LSM303AGR_ACC_FS_4G
Definition lsm303agr.h:409
@ LSM303AGR_ACC_FS_2G
Definition lsm303agr.h:408
@ LSM303AGR_ACC_FS_8G
Definition lsm303agr.h:410
@ LSM303AGR_ACC_MODE_HRES
Definition lsm303agr.h:450
@ LSM303AGR_ACC_MODE_LPOW
Definition lsm303agr.h:449
@ LSM303AGR_SAD_ACC
Definition lsm303agr.c:49
@ LSM303AGR_SAD_COMP
Definition lsm303agr.c:50
@ LSM303AGR_ACC_ODR_PD
Definition lsm303agr.h:418
@ LSM303AGR_COMP_MODE_IDLE
Definition lsm303agr.h:490
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
#define osalThreadSleepMilliseconds(msecs)
Delays the invoking thread for the specified number of milliseconds.
Definition osal.h:522
#define FALSE
Generic 'false' preprocessor boolean constant.
int32_t msg_t
Definition chearly.h:88
#define MSG_OK
Normal wakeup message.
Definition chschd.h:39
#define MSG_RESET
Wakeup caused by a reset condition.
Definition chschd.h:42
#define TIME_INFINITE
Infinite interval specification for all functions with a timeout specification.
Definition chtime.h:55
HAL subsystem header.
LSM303AGR MEMS interface module header.
Base accelerometer class.
const struct BaseAccelerometerVMT * vmt
Virtual Methods Table.
BaseAccelerometer virtual methods table.
Base compass class.
Definition ex_compass.h:86
const struct BaseCompassVMT * vmt
Virtual Methods Table.
Definition ex_compass.h:88
BaseCompass virtual methods table.
Definition ex_compass.h:70
LSM303AGR configuration structure.
Definition lsm303agr.h:518
I2CDriver * i2cp
I2C driver associated to this LSM303AGR.
Definition lsm303agr.h:522
LSM303AGR 6-axis accelerometer/compass class.
Definition lsm303agr.h:634
BaseAccelerometer acc_if
Base accelerometer interface.
Definition lsm303agr.h:638
BaseCompass comp_if
Base compass interface.
Definition lsm303agr.h:640
const struct LSM303AGRVMT * vmt
Virtual Methods Table.
Definition lsm303agr.h:636
LSM303AGR virtual methods table.
Definition lsm303agr.h:601
const I2CConfig * config
Current configuration data.