ChibiOS  0.0.0
lsm303agr.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2016..2018 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  */
48 typedef 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  */
104 static 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  */
126 static 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,
149  LSM303AGR_AD_OUT_X_L_A, buff,
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  */
181 static 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  */
214 static 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  */
243 static 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  */
273 static 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  */
302 static 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  */
356  lsm303agr_acc_fs_t fs) {
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  }
372  else if(fs == LSM303AGR_ACC_FS_4G) {
373  newfs = LSM303AGR_ACC_4G;
374  }
375  else if(fs == LSM303AGR_ACC_FS_8G) {
376  newfs = LSM303AGR_ACC_8G;
377  }
378  else if(fs == LSM303AGR_ACC_FS_16G) {
379  newfs = LSM303AGR_ACC_16G;
380  }
381  else {
382  msg = MSG_RESET;
383  return msg;
384  }
385 
386  if(newfs != devp->accfullscale) {
387  /* Computing scale value.*/
388  scale = newfs / devp->accfullscale;
389  devp->accfullscale = newfs;
390 
391 #if LSM303AGR_SHARED_I2C
392  i2cAcquireBus(devp->config->i2cp);
393  i2cStart(devp->config->i2cp,
394  devp->config->i2ccfg);
395 #endif /* LSM303AGR_SHARED_I2C */
396 
397  /* Updating register.*/
398  msg = lsm303agrI2CReadRegister(devp->config->i2cp,
400  LSM303AGR_AD_CTRL_REG4_A,
401  &buff[1], 1);
402 
403 #if LSM303AGR_SHARED_I2C
404  i2cReleaseBus(devp->config->i2cp);
405 #endif /* LSM303AGR_SHARED_I2C */
406 
407  if(msg != MSG_OK)
408  return msg;
409 
410  buff[1] &= ~(LSM303AGR_CTRL_REG4_A_FS_MASK);
411  buff[1] |= fs;
412  buff[0] = LSM303AGR_AD_CTRL_REG4_A;
413 
414 #if LSM303AGR_SHARED_I2C
415  i2cAcquireBus(devp->config->i2cp);
416  i2cStart(devp->config->i2cp, devp->config->i2ccfg);
417 #endif /* LSM303AGR_SHARED_I2C */
418 
419  msg = lsm303agrI2CWriteRegister(devp->config->i2cp,
420  LSM303AGR_SAD_ACC, buff, 1);
421 
422 #if LSM303AGR_SHARED_I2C
423  i2cReleaseBus(devp->config->i2cp);
424 #endif /* LSM303AGR_SHARED_I2C */
425 
426  if(msg != MSG_OK)
427  return msg;
428 
429  /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
430  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
431  devp->accsensitivity[i] *= scale;
432  devp->accbias[i] *= scale;
433  }
434  }
435  return msg;
436 }
437 
438 /**
439  * @brief Return the number of axes of the BaseCompass.
440  *
441  * @param[in] ip pointer to @p BaseCompass interface
442  *
443  * @return the number of axes.
444  */
445 static size_t comp_get_axes_number(void *ip) {
446 
447  osalDbgCheck(ip != NULL);
449 }
450 
451 /**
452  * @brief Retrieves raw data from the BaseCompass.
453  * @note This data is retrieved from MEMS register without any algebraical
454  * manipulation.
455  * @note The axes array must be at least the same size of the
456  * BaseCompass axes number.
457  *
458  * @param[in] ip pointer to @p BaseCompass interface.
459  * @param[out] axes a buffer which would be filled with raw data.
460  *
461  * @return The operation status.
462  * @retval MSG_OK if the function succeeded.
463  * @retval MSG_RESET if one or more I2C errors occurred, the errors can
464  * be retrieved using @p i2cGetErrors().
465  * @retval MSG_TIMEOUT if a timeout occurred before operation end.
466  */
467 static msg_t comp_read_raw(void *ip, int32_t axes[]) {
468  LSM303AGRDriver* devp;
469  uint8_t buff [LSM303AGR_COMP_NUMBER_OF_AXES * 2], i;
470  int16_t tmp;
471  msg_t msg;
472 
473  osalDbgCheck((ip != NULL) && (axes != NULL));
474 
475  /* Getting parent instance pointer.*/
477 
478  osalDbgAssert((devp->state == LSM303AGR_READY),
479  "comp_read_raw(), invalid state");
480  osalDbgAssert((devp->config->i2cp->state == I2C_READY),
481  "comp_read_raw(), channel not ready");
482 
483 #if LSM303AGR_SHARED_I2C
484  i2cAcquireBus(devp->config->i2cp);
485  i2cStart(devp->config->i2cp,
486  devp->config->i2ccfg);
487 #endif /* LSM303AGR_SHARED_I2C */
488  msg = lsm303agrI2CReadRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
489  LSM303AGR_AD_OUTX_L_REG_M, buff,
491 
492 #if LSM303AGR_SHARED_I2C
493  i2cReleaseBus(devp->config->i2cp);
494 #endif /* LSM303AGR_SHARED_I2C */
495 
496  if(msg == MSG_OK)
497  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
498  tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
499  axes[i] = (int32_t)tmp;
500  }
501  return msg;
502 }
503 
504 /**
505  * @brief Retrieves cooked data from the BaseCompass.
506  * @note This data is manipulated according to the formula
507  * cooked = (raw * sensitivity) - bias.
508  * @note Final data is expressed as G.
509  * @note The axes array must be at least the same size of the
510  * BaseCompass axes number.
511  *
512  * @param[in] ip pointer to @p BaseCompass interface.
513  * @param[out] axes a buffer which would be filled with cooked data.
514  *
515  * @return The operation status.
516  * @retval MSG_OK if the function succeeded.
517  * @retval MSG_RESET if one or more I2C errors occurred, the errors can
518  * be retrieved using @p i2cGetErrors().
519  * @retval MSG_TIMEOUT if a timeout occurred before operation end.
520  */
521 static msg_t comp_read_cooked(void *ip, float axes[]) {
522  LSM303AGRDriver* devp;
523  uint32_t i;
524  int32_t raw[LSM303AGR_COMP_NUMBER_OF_AXES];
525  msg_t msg;
526 
527  osalDbgCheck((ip != NULL) && (axes != NULL));
528 
529 
530  /* Getting parent instance pointer.*/
532 
533  osalDbgAssert((devp->state == LSM303AGR_READY),
534  "comp_read_cooked(), invalid state");
535 
536  msg = comp_read_raw(ip, raw);
537  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES ; i++) {
538  axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i];
539  }
540  return msg;
541 }
542 
543 /**
544  * @brief Set bias values for the BaseCompass.
545  * @note Bias must be expressed as G.
546  * @note The bias buffer must be at least the same size of the
547  * BaseCompass axes number.
548  *
549  * @param[in] ip pointer to @p BaseCompass interface.
550  * @param[in] bp a buffer which contains biases.
551  *
552  * @return The operation status.
553  * @retval MSG_OK if the function succeeded.
554  */
555 static msg_t comp_set_bias(void *ip, float *bp) {
556  LSM303AGRDriver* devp;
557  uint32_t i;
558  msg_t msg = MSG_OK;
559 
560  osalDbgCheck((ip != NULL) && (bp != NULL));
561 
562  /* Getting parent instance pointer.*/
564 
565  osalDbgAssert((devp->state == LSM303AGR_READY),
566  "comp_set_bias(), invalid state");
567 
568  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
569  devp->compbias[i] = bp[i];
570  }
571  return msg;
572 }
573 
574 /**
575  * @brief Reset bias values for the BaseCompass.
576  * @note Default biases value are obtained from device datasheet when
577  * available otherwise they are considered zero.
578  *
579  * @param[in] ip pointer to @p BaseCompass interface.
580  *
581  * @return The operation status.
582  * @retval MSG_OK if the function succeeded.
583  */
584 static msg_t comp_reset_bias(void *ip) {
585  LSM303AGRDriver* devp;
586  uint32_t i;
587  msg_t msg = MSG_OK;
588 
589  osalDbgCheck(ip != NULL);
590 
591  /* Getting parent instance pointer.*/
593 
594  osalDbgAssert((devp->state == LSM303AGR_READY),
595  "comp_reset_bias(), invalid state");
596 
597  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++)
598  devp->compbias[i] = LSM303AGR_COMP_BIAS;
599  return msg;
600 }
601 
602 /**
603  * @brief Set sensitivity values for the BaseCompass.
604  * @note Sensitivity must be expressed as G/LSB.
605  * @note The sensitivity buffer must be at least the same size of the
606  * BaseCompass axes number.
607  *
608  * @param[in] ip pointer to @p BaseCompass interface.
609  * @param[in] sp a buffer which contains sensitivities.
610  *
611  * @return The operation status.
612  * @retval MSG_OK if the function succeeded.
613  */
614 static msg_t comp_set_sensivity(void *ip, float *sp) {
615  LSM303AGRDriver* devp;
616  uint32_t i;
617  msg_t msg = MSG_OK;
618 
619  /* Getting parent instance pointer.*/
621 
622  osalDbgCheck((ip != NULL) && (sp != NULL));
623 
624  osalDbgAssert((devp->state == LSM303AGR_READY),
625  "comp_set_sensivity(), invalid state");
626 
627  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
628  devp->compsensitivity[i] = sp[i];
629  }
630  return msg;
631 }
632 
633 /**
634  * @brief Reset sensitivity values for the BaseCompass.
635  * @note Default sensitivities value are obtained from device datasheet.
636  *
637  * @param[in] ip pointer to @p BaseCompass interface.
638  *
639  * @return The operation status.
640  * @retval MSG_OK if the function succeeded.
641  * @retval MSG_RESET otherwise.
642  */
643 static msg_t comp_reset_sensivity(void *ip) {
644  LSM303AGRDriver* devp;
645  uint32_t i;
646  msg_t msg = MSG_OK;
647 
648  osalDbgCheck(ip != NULL);
649 
650  /* Getting parent instance pointer.*/
652 
653  osalDbgAssert((devp->state == LSM303AGR_READY),
654  "comp_reset_sensivity(), invalid state");
655 
656  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++)
657  devp->compsensitivity[i] = LSM303AGR_COMP_SENS_50GA;
658 
659  return msg;
660 }
661 
662 static const struct LSM303AGRVMT vmt_device = {
663  (size_t)0,
665 };
666 
667 static const struct BaseAccelerometerVMT vmt_accelerometer = {
668  sizeof(struct LSM303AGRVMT*),
671 };
672 
673 static const struct BaseCompassVMT vmt_compass = {
674  sizeof(struct LSM303AGRVMT*) + sizeof(BaseAccelerometer),
677 };
678 
679 /*===========================================================================*/
680 /* Driver exported functions. */
681 /*===========================================================================*/
682 
683 /**
684  * @brief Initializes an instance.
685  *
686  * @param[out] devp pointer to the @p LSM303AGRDriver object
687  *
688  * @init
689  */
691  devp->vmt = &vmt_device;
692  devp->acc_if.vmt = &vmt_accelerometer;
693  devp->comp_if.vmt = &vmt_compass;
694 
695  devp->config = NULL;
696 
697  devp->accaxes = LSM303AGR_ACC_NUMBER_OF_AXES;
698  devp->compaxes = LSM303AGR_COMP_NUMBER_OF_AXES;
699 
700  devp->state = LSM303AGR_STOP;
701 }
702 
703 /**
704  * @brief Configures and activates LSM303AGR Complex Driver peripheral.
705  *
706  * @param[in] devp pointer to the @p LSM303AGRDriver object
707  * @param[in] config pointer to the @p LSM303AGRConfig object
708  *
709  * @api
710  */
711 void lsm303agrStart(LSM303AGRDriver *devp, const LSM303AGRConfig *config) {
712  uint32_t i;
713  uint8_t cr[6];
714  osalDbgCheck((devp != NULL) && (config != NULL));
715 
716  osalDbgAssert((devp->state == LSM303AGR_STOP) ||
717  (devp->state == LSM303AGR_READY),
718  "lsm303agrStart(), invalid state");
719 
720  devp->config = config;
721 
722  /* Configuring Accelerometer subsystem.*/
723 
724  /* Multiple write starting address.*/
725  cr[0] = LSM303AGR_AD_CTRL_REG1_A;
726 
727  /* Control register 1 configuration block.*/
728  {
729  cr[1] = LSM303AGR_ACC_AE_XYZ | devp->config->accoutdatarate;
730 #if LSM303AGR_ACC_USE_ADVANCED || defined(__DOXYGEN__)
731  if(devp->config->accmode == LSM303AGR_ACC_MODE_LPOW)
732  cr[1] |= LSM303AGR_CTRL_REG1_A_LPEN;
733 #endif
734  }
735 
736  /* Control register 2 configuration block.*/
737  {
738  cr[2] = 0;
739  }
740 
741  /* Control register 3 configuration block.*/
742  {
743  cr[3] = 0;
744  }
745 
746  /* Control register 4 configuration block.*/
747  {
748  cr[4] = devp->config->accfullscale;
749 #if LSM303AGR_ACC_USE_ADVANCED || defined(__DOXYGEN__)
750  cr[4] |= devp->config->accendianess |
751  devp->config->accblockdataupdate;
752  if(devp->config->accmode == LSM303AGR_ACC_MODE_HRES)
753  cr[4] |= LSM303AGR_CTRL_REG4_A_HR;
754 #endif
755  }
756 
757  /* Storing sensitivity according to user settings */
758  if(devp->config->accfullscale == LSM303AGR_ACC_FS_2G) {
759  devp->accfullscale = LSM303AGR_ACC_2G;
760  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
761  if(devp->config->accsensitivity == NULL)
762  devp->accsensitivity[i] = LSM303AGR_ACC_SENS_2G;
763  else
764  devp->accsensitivity[i] = devp->config->accsensitivity[i];
765  }
766  }
767  else if(devp->config->accfullscale == LSM303AGR_ACC_FS_4G) {
768  devp->accfullscale = LSM303AGR_ACC_4G;
769  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
770  if(devp->config->accsensitivity == NULL)
771  devp->accsensitivity[i] = LSM303AGR_ACC_SENS_4G;
772  else
773  devp->accsensitivity[i] = devp->config->accsensitivity[i];
774  }
775  }
776  else if(devp->config->accfullscale == LSM303AGR_ACC_FS_8G) {
777  devp->accfullscale = LSM303AGR_ACC_8G;
778  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
779  if(devp->config->accsensitivity == NULL)
780  devp->accsensitivity[i] = LSM303AGR_ACC_SENS_8G;
781  else
782  devp->accsensitivity[i] = devp->config->accsensitivity[i];
783  }
784  }
785  else if(devp->config->accfullscale == LSM303AGR_ACC_FS_16G) {
786  devp->accfullscale = LSM303AGR_ACC_16G;
787  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
788  if(devp->config->accsensitivity == NULL)
789  devp->accsensitivity[i] = LSM303AGR_ACC_SENS_16G;
790  else
791  devp->accsensitivity[i] = devp->config->accsensitivity[i];
792  }
793  }
794  else
795  osalDbgAssert(FALSE, "lsm303dlhcStart(), accelerometer full scale issue");
796 
797  /* Storing bias information */
798  if(devp->config->accbias != NULL)
799  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
800  devp->accbias[i] = devp->config->accbias[i];
801  else
802  for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
803  devp->accbias[i] = LSM303AGR_ACC_BIAS;
804 
805 #if LSM303AGR_SHARED_I2C
806  i2cAcquireBus((devp)->config->i2cp);
807 #endif /* LSM303AGR_SHARED_I2C */
808  i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
809 
810  lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_ACC, cr, 4);
811 
812 #if LSM303AGR_SHARED_I2C
813  i2cReleaseBus((devp)->config->i2cp);
814 #endif /* LSM303AGR_SHARED_I2C */
815 
816  /* Configuring Compass subsystem */
817  /* Multiple write starting address.*/
818  cr[0] = LSM303AGR_AD_CFG_REG_A_M;
819 
820  /* Control register A configuration block.*/
821  {
822  cr[1] = devp->config->compoutputdatarate;
823 #if LSM303AGR_COMP_USE_ADVANCED || defined(__DOXYGEN__)
824  cr[1] |= devp->config->compmode | devp->config->complp;
825 #endif
826  }
827 
828  /* Control register B configuration block.*/
829  {
830  cr[2] = 0;
831  }
832 
833  /* Control register C configuration block.*/
834  {
835  cr[3] = 0;
836  }
837 
838 #if LSM303AGR_SHARED_I2C
839  i2cAcquireBus((devp)->config->i2cp);
840  i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
841 #endif /* LSM303AGR_SHARED_I2C */
842 
843  lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
844  cr, 3);
845 
846 #if LSM303AGR_SHARED_I2C
847  i2cReleaseBus((devp)->config->i2cp);
848 #endif /* LSM303AGR_SHARED_I2C */
849 
850  devp->compfullscale = LSM303AGR_COMP_50GA;
851  for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
852  if(devp->config->compsensitivity == NULL) {
853  devp->compsensitivity[i] = LSM303AGR_COMP_SENS_50GA;
854  }
855  else {
856  devp->compsensitivity[i] = devp->config->compsensitivity[i];
857  }
858  }
859 
860  /* This is the MEMS transient recovery time */
862 
863  devp->state = LSM303AGR_READY;
864 }
865 
866 /**
867  * @brief Deactivates the LSM303AGR Complex Driver peripheral.
868  *
869  * @param[in] devp pointer to the @p LSM303AGRDriver object
870  *
871  * @api
872  */
874  uint8_t cr[2];
875  osalDbgCheck(devp != NULL);
876 
877  osalDbgAssert((devp->state == LSM303AGR_STOP) ||
878  (devp->state == LSM303AGR_READY),
879  "lsm303agrStop(), invalid state");
880 
881  if (devp->state == LSM303AGR_READY) {
882 #if LSM303AGR_SHARED_I2C
883  i2cAcquireBus((devp)->config->i2cp);
884  i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
885 #endif /* LSM303AGR_SHARED_I2C */
886 
887  /* Disabling accelerometer. */
888  cr[0] = LSM303AGR_AD_CTRL_REG1_A;
890  lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_ACC,
891  cr, 1);
892 
893  /* Disabling compass. */
894  cr[0] = LSM303AGR_AD_CFG_REG_A_M;
895  cr[1] = LSM303AGR_COMP_MODE_IDLE;
896  lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
897  cr, 1);
898 
899  i2cStop((devp)->config->i2cp);
900 #if LSM303AGR_SHARED_I2C
901  i2cReleaseBus((devp)->config->i2cp);
902 #endif /* LSM303AGR_SHARED_I2C */
903  }
904  devp->state = LSM303AGR_STOP;
905 }
906 /** @} */
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
void lsm303agrStop(LSM303AGRDriver *devp)
Deactivates the LSM303AGR Complex Driver peripheral.
Definition: lsm303agr.c:873
static msg_t comp_set_sensivity(void *ip, float *sp)
Set sensitivity values for the BaseCompass.
Definition: lsm303agr.c:614
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:170
const struct LSM303AGRVMT * vmt
Virtual Methods Table.
Definition: lsm303agr.h:645
static msg_t comp_set_bias(void *ip, float *bp)
Set bias values for the BaseCompass.
Definition: lsm303agr.c:555
void i2cStart(I2CDriver *i2cp, const I2CConfig *config)
Configures and activates the I2C peripheral.
Definition: hal_i2c.c:93
void lsm303agrObjectInit(LSM303AGRDriver *devp)
Initializes an instance.
Definition: lsm303agr.c:690
static msg_t acc_read_raw(void *ip, int32_t axes[])
Retrieves raw data from the BaseAccelerometer.
Definition: lsm303agr.c:126
BaseCompass virtual methods table.
Definition: hal_compass.h:70
Base compass class.
Definition: hal_compass.h:86
static msg_t acc_set_full_scale(LSM303AGRDriver *devp, lsm303agr_acc_fs_t fs)
Changes the LSM303AGRDriver accelerometer fullscale value.
Definition: lsm303agr.c:355
HAL subsystem header.
void i2cAcquireBus(I2CDriver *i2cp)
Gains exclusive access to the I2C bus.
Definition: hal_i2c.c:261
void i2cReleaseBus(I2CDriver *i2cp)
Releases exclusive access to the I2C bus.
Definition: hal_i2c.c:277
static msg_t acc_read_cooked(void *ip, float axes[])
Retrieves cooked data from the BaseAccelerometer.
Definition: lsm303agr.c:181
static msg_t acc_reset_bias(void *ip)
Reset bias values for the BaseAccelerometer.
Definition: lsm303agr.c:243
#define objGetInstance(type, ip)
Returns the instance pointer starting from an interface pointer.
Definition: hal_objects.h:80
const struct BaseCompassVMT * vmt
Virtual Methods Table.
Definition: hal_compass.h:88
static msg_t acc_reset_sensivity(void *ip)
Reset sensitivity values for the BaseAccelerometer.
Definition: lsm303agr.c:302
LSM303AGR 6-axis accelerometer/compass class.
Definition: lsm303agr.h:643
LSM303AGR MEMS interface module header.
#define osalThreadSleepMilliseconds(msecs)
Delays the invoking thread for the specified number of milliseconds.
Definition: osal.h:451
static msg_t comp_reset_bias(void *ip)
Reset bias values for the BaseCompass.
Definition: lsm303agr.c:584
void i2cStop(I2CDriver *i2cp)
Deactivates the I2C peripheral.
Definition: hal_i2c.c:113
lsm303agr_sad_t
Accelerometer and Compass Slave Address.
Definition: lsm303agr.c:48
BaseAccelerometer acc_if
Base accelerometer interface.
Definition: lsm303agr.h:647
Structure representing an I2C driver.
Definition: hal_i2c_lld.h:88
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
static size_t acc_get_axes_number(void *ip)
Return the number of axes of the BaseAccelerometer.
Definition: lsm303agr.c:104
LSM303AGR virtual methods table.
Definition: lsm303agr.h:610
#define TIME_INFINITE
Infinite interval specification for all functions with a timeout specification.
Definition: chtime.h:55
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:278
static msg_t comp_read_cooked(void *ip, float axes[])
Retrieves cooked data from the BaseCompass.
Definition: lsm303agr.c:521
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
static msg_t acc_set_sensivity(void *ip, float *sp)
Set sensitivity values for the BaseAccelerometer.
Definition: lsm303agr.c:273
lsm303agr_acc_fs_t
LSM303AGR accelerometer subsystem full scale.
Definition: lsm303agr.h:418
static msg_t acc_set_bias(void *ip, float *bp)
Set bias values for the BaseAccelerometer.
Definition: lsm303agr.c:214
#define LSM303AGR_COMP_NUMBER_OF_AXES
LSM303AGR compass subsystem characteristics.
Definition: lsm303agr.h:94
static size_t comp_get_axes_number(void *ip)
Return the number of axes of the BaseCompass.
Definition: lsm303agr.c:445
LSM303AGR configuration structure.
Definition: lsm303agr.h:527
static msg_t comp_reset_sensivity(void *ip)
Reset sensitivity values for the BaseCompass.
Definition: lsm303agr.c:643
void lsm303agrStart(LSM303AGRDriver *devp, const LSM303AGRConfig *config)
Configures and activates LSM303AGR Complex Driver peripheral.
Definition: lsm303agr.c:711
static msg_t comp_read_raw(void *ip, int32_t axes[])
Retrieves raw data from the BaseCompass.
Definition: lsm303agr.c:467
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:258
const I2CConfig * config
Current configuration data.
Definition: hal_i2c_lld.h:96
#define LSM303AGR_ACC_NUMBER_OF_AXES
LSM303AGR accelerometer subsystem characteristics.
Definition: lsm303agr.h:72
BaseCompass comp_if
Base compass interface.
Definition: lsm303agr.h:649
BaseAccelerometer virtual methods table.
Base accelerometer class.
const struct BaseAccelerometerVMT * vmt
Virtual Methods Table.
int32_t msg_t
Definition: chtypes.h:51
#define FALSE
Generic &#39;false&#39; preprocessor boolean constant.
Definition: rt/include/ch.h:77
I2CDriver * i2cp
I2C driver associated to this LSM303AGR.
Definition: lsm303agr.h:531
#define MSG_RESET
Wakeup caused by a reset condition.
Definition: chschd.h:43