aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/ex/devices/ST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/ex/devices/ST')
-rw-r--r--lib/chibios/os/ex/devices/ST/hts221.c781
-rw-r--r--lib/chibios/os/ex/devices/ST/hts221.h707
-rw-r--r--lib/chibios/os/ex/devices/ST/hts221.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/l3gd20.c642
-rw-r--r--lib/chibios/os/ex/devices/ST/l3gd20.h725
-rw-r--r--lib/chibios/os/ex/devices/ST/l3gd20.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lis302dl.c554
-rw-r--r--lib/chibios/os/ex/devices/ST/lis302dl.h566
-rw-r--r--lib/chibios/os/ex/devices/ST/lis302dl.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lis3dsh.c641
-rw-r--r--lib/chibios/os/ex/devices/ST/lis3dsh.h708
-rw-r--r--lib/chibios/os/ex/devices/ST/lis3dsh.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lis3mdl.c627
-rw-r--r--lib/chibios/os/ex/devices/ST/lis3mdl.h670
-rw-r--r--lib/chibios/os/ex/devices/ST/lis3mdl.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lps22hb.c686
-rw-r--r--lib/chibios/os/ex/devices/ST/lps22hb.h724
-rw-r--r--lib/chibios/os/ex/devices/ST/lps22hb.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lps25h.c696
-rw-r--r--lib/chibios/os/ex/devices/ST/lps25h.h740
-rw-r--r--lib/chibios/os/ex/devices/ST/lps25h.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm303agr.c906
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm303agr.h921
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm303agr.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm303dlhc.c1175
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm303dlhc.h958
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm303dlhc.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm6ds0.c1109
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm6ds0.h1034
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm6ds0.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm6dsl.c1119
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm6dsl.h1055
-rw-r--r--lib/chibios/os/ex/devices/ST/lsm6dsl.mk10
-rw-r--r--lib/chibios/os/ex/devices/ST/vl53l0x.h443
-rw-r--r--lib/chibios/os/ex/devices/ST/vl53l0x.mk10
35 files changed, 18307 insertions, 0 deletions
diff --git a/lib/chibios/os/ex/devices/ST/hts221.c b/lib/chibios/os/ex/devices/ST/hts221.c
new file mode 100644
index 000000000..32963d968
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/hts221.c
@@ -0,0 +1,781 @@
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 hts221.c
23 * @brief HTS221 MEMS interface module code.
24 *
25 * @addtogroup HTS221
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "hts221.h"
32
33/*===========================================================================*/
34/* Driver local definitions. */
35/*===========================================================================*/
36
37#define HTS221_SEL(mask, offset) (int16_t)(mask << offset)
38
39#define HTS221_FLAG_HYGRO_BIAS 0x01
40#define HTS221_FLAG_HYGRO_SENS 0x02
41#define HTS221_FLAG_THERMO_BIAS 0x04
42#define HTS221_FLAG_THERMO_SENS 0x08
43
44/*===========================================================================*/
45/* Driver exported variables. */
46/*===========================================================================*/
47
48/*===========================================================================*/
49/* Driver local variables and types. */
50/*===========================================================================*/
51
52/*===========================================================================*/
53/* Driver local functions. */
54/*===========================================================================*/
55
56#if (HTS221_USE_I2C) || defined(__DOXYGEN__)
57/**
58 * @brief Reads registers value using I2C.
59 * @pre The I2C interface must be initialized and the driver started.
60 *
61 * @param[in] i2cp pointer to the I2C interface
62 * @param[in] reg first sub-register address
63 * @param[out] rxbuf pointer to an output buffer
64 * @param[in] n number of consecutive register to read
65 * @return the operation status.
66 *
67 * @notapi
68 */
69static msg_t hts221I2CReadRegister(I2CDriver *i2cp, uint8_t reg, uint8_t* rxbuf,
70 size_t n) {
71 uint8_t txbuf = reg;
72 if (n > 1)
73 txbuf |= HTS221_SUB_MS;
74
75 return i2cMasterTransmitTimeout(i2cp, HTS221_SAD, &txbuf, 1, rxbuf, n,
76 TIME_INFINITE);
77}
78
79/**
80 * @brief Writes a value into a register using I2C.
81 * @pre The I2C interface must be initialized and the driver started.
82 *
83 * @param[in] i2cp pointer to the I2C interface
84 * @param[in] txbuf buffer containing sub-address value in first position
85 * and values to write
86 * @param[in] n size of txbuf less one (not considering the first
87 * element)
88 * @return the operation status.
89 *
90 * @notapi
91 */
92static msg_t hts221I2CWriteRegister(I2CDriver *i2cp, uint8_t* txbuf, size_t n) {
93 if (n > 1)
94 (*txbuf) |= HTS221_SUB_MS;
95
96 return i2cMasterTransmitTimeout(i2cp, HTS221_SAD, txbuf, n + 1, NULL, 0,
97 TIME_INFINITE);
98}
99#endif /* HTS221_USE_I2C */
100
101/**
102 * @brief Computes biases and sensitivities starting from data stored in
103 * calibration registers.
104 * @note Factory bias and sensitivity values are stored into the driver
105 * structure.
106 *
107 * @param[in] devp pointer to the HTS221 interface
108 * @return the operation status.
109 *
110 * @notapi
111 */
112static msg_t hts221Calibrate(HTS221Driver *devp) {
113 msg_t msg;
114 uint8_t calib[16], H0_rH_x2, H1_rH_x2, msb;
115 int16_t H0_T0_OUT, H1_T0_OUT, T0_degC_x8, T1_degC_x8, T0_OUT, T1_OUT;
116
117 /* Retrieving rH values from Calibration registers */
118 msg = hts221I2CReadRegister(devp->config->i2cp,
119 HTS221_AD_CALIB_0, calib, 16);
120
121 H0_rH_x2 = calib[0];
122 H1_rH_x2 = calib[1];
123 H0_T0_OUT = calib[6];
124 H0_T0_OUT += calib[7] << 8;
125 H1_T0_OUT = calib[10];
126 H1_T0_OUT += calib[11] << 8;
127
128 T0_degC_x8 = calib[2];
129
130 /* Completing T0_degC_x8 value */
131 msb = (calib[5] & HTS221_SEL(0x03, 0));
132 if (msb & HTS221_SEL(0x01, 1)) {
133 msb |= HTS221_SEL(0x3F, 2);
134 }
135 T0_degC_x8 += msb << 8;
136
137 T1_degC_x8 = calib[3];
138 /* Completing T1_degC_x8 value */
139 msb = ((calib[5] & HTS221_SEL(0x03, 2)) >> 2);
140 if (msb & HTS221_SEL(0x01, 1)) {
141 msb |= HTS221_SEL(0x3F, 2);
142 }
143 T1_degC_x8 += msb << 8;
144
145 T0_OUT = calib[12];
146 T0_OUT += calib[13] << 8;
147 T1_OUT = calib[14];
148 T1_OUT += calib[15] << 8;
149
150 devp->hygrofactorysensitivity = ((float)H1_rH_x2 - (float)H0_rH_x2) /
151 (((float)H1_T0_OUT - (float)H0_T0_OUT) * 2.0f);
152
153
154 devp->hygrofactorybias = (devp->hygrofactorysensitivity * (float)H0_T0_OUT) -
155 ((float)H0_rH_x2 / 2.0f);
156
157 devp->thermofactorysensitivity = ((float)T1_degC_x8 - (float)T0_degC_x8) /
158 (((float)T1_OUT - (float)T0_OUT) * 8.0f);
159
160 devp->thermofactorybias = (devp->thermofactorysensitivity * (float)T0_OUT) -
161 ((float)T0_degC_x8 / 8.0f);
162
163 return msg;
164}
165
166/**
167 * @brief Return the number of axes of the BaseHygrometer.
168 *
169 * @param[in] ip pointer to @p BaseHygrometer interface.
170 *
171 * @return the number of axes.
172 */
173static size_t hygro_get_axes_number(void *ip) {
174 (void)ip;
175
176 return HTS221_HYGRO_NUMBER_OF_AXES;
177}
178
179/**
180 * @brief Retrieves raw data from the BaseHygrometer.
181 * @note This data is retrieved from MEMS register without any algebraical
182 * manipulation.
183 * @note The axes array must be at least the same size of the
184 * BaseHygrometer axes number.
185 *
186 * @param[in] ip pointer to @p BaseHygrometer interface.
187 * @param[out] axes a buffer which would be filled with raw data.
188 *
189 * @return The operation status.
190 * @retval MSG_OK if the function succeeded.
191 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
192 * be retrieved using @p i2cGetErrors().
193 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
194 */
195static msg_t hygro_read_raw(void *ip, int32_t axes[]) {
196 HTS221Driver* devp;
197 uint8_t buff[2];
198 int16_t tmp;
199 msg_t msg;
200
201 osalDbgCheck((ip != NULL) && (axes != NULL));
202
203 /* Getting parent instance pointer.*/
204 devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
205
206 osalDbgAssert((devp->state == HTS221_READY),
207 "hygro_read_raw(), invalid state");
208
209 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
210 "hygro_read_raw(), channel not ready");
211
212#if HTS221_SHARED_I2C
213 i2cAcquireBus(devp->config->i2cp);
214 i2cStart(devp->config->i2cp,
215 devp->config->i2ccfg);
216#endif /* HTS221_SHARED_I2C */
217
218 msg = hts221I2CReadRegister(devp->config->i2cp, HTS221_AD_HUMIDITY_OUT_L,
219 buff, 2);
220
221#if HTS221_SHARED_I2C
222 i2cReleaseBus(devp->config->i2cp);
223#endif /* HTS221_SHARED_I2C */
224
225 if (msg == MSG_OK) {
226 tmp = buff[0] + (buff[1] << 8);
227 *axes = (int32_t)tmp;
228 }
229 return msg;
230}
231
232/**
233 * @brief Retrieves cooked data from the BaseHygrometer.
234 * @note This data is manipulated according to the formula
235 * cooked = (raw * sensitivity) - bias.
236 * @note Final data is expressed as %rH.
237 * @note The axes array must be at least the same size of the
238 * BaseHygrometer axes number.
239 *
240 * @param[in] ip pointer to @p BaseHygrometer interface.
241 * @param[out] axes a buffer which would be filled with cooked data.
242 *
243 * @return The operation status.
244 * @retval MSG_OK if the function succeeded.
245 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
246 * be retrieved using @p i2cGetErrors().
247 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
248 */
249static msg_t hygro_read_cooked(void *ip, float axes[]) {
250 HTS221Driver* devp;
251 int32_t raw;
252 msg_t msg;
253
254 osalDbgCheck((ip != NULL) && (axes != NULL));
255
256 /* Getting parent instance pointer.*/
257 devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
258
259 osalDbgAssert((devp->state == HTS221_READY),
260 "hygro_read_cooked(), invalid state");
261
262 msg = hygro_read_raw(ip, &raw);
263
264 *axes = (raw * devp->hygrosensitivity) - devp->hygrobias;
265
266 return msg;
267}
268
269/**
270 * @brief Set bias values for the BaseHygrometer.
271 * @note Bias must be expressed as %rH.
272 * @note The bias buffer must be at least the same size of the
273 * BaseHygrometer axes number.
274 *
275 * @param[in] ip pointer to @p BaseHygrometer interface.
276 * @param[in] bp a buffer which contains biases.
277 *
278 * @return The operation status.
279 * @retval MSG_OK if the function succeeded.
280 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
281 * be retrieved using @p i2cGetErrors().
282 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
283 */
284static msg_t hygro_set_bias(void *ip, float *bp) {
285 HTS221Driver* devp;
286 msg_t msg = MSG_OK;
287
288 osalDbgCheck((ip != NULL) && (bp != NULL));
289
290 /* Getting parent instance pointer.*/
291 devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
292
293 osalDbgAssert((devp->state == HTS221_READY),
294 "hygro_set_bias(), invalid state");
295
296 devp->hygrobias = *bp;
297 return msg;
298}
299
300/**
301 * @brief Reset bias values for the BaseHygrometer.
302 * @note Default biases value are obtained from device datasheet when
303 * available otherwise they are considered zero.
304 *
305 * @param[in] ip pointer to @p BaseHygrometer interface.
306 *
307 * @return The operation status.
308 * @retval MSG_OK if the function succeeded.
309 */
310static msg_t hygro_reset_bias(void *ip) {
311 HTS221Driver* devp;
312 msg_t msg = MSG_OK;
313
314 osalDbgCheck(ip != NULL);
315
316 /* Getting parent instance pointer.*/
317 devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
318
319 osalDbgAssert((devp->state == HTS221_READY),
320 "hygro_reset_bias(), invalid state");
321
322 devp->hygrobias = devp->hygrofactorybias;
323 return msg;
324}
325
326/**
327 * @brief Set sensitivity values for the BaseHygrometer.
328 * @note Sensitivity must be expressed as %rH/LSB.
329 * @note The sensitivity buffer must be at least the same size of the
330 * BaseHygrometer axes number.
331 *
332 * @param[in] ip pointer to @p BaseHygrometer interface.
333 * @param[in] sp a buffer which contains sensitivities.
334 *
335 * @return The operation status.
336 * @retval MSG_OK if the function succeeded.
337 */
338static msg_t hygro_set_sensitivity(void *ip, float *sp) {
339 HTS221Driver* devp;
340 msg_t msg = MSG_OK;
341
342 osalDbgCheck((ip != NULL) && (sp != NULL));
343
344 /* Getting parent instance pointer.*/
345 devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
346
347 osalDbgAssert((devp->state == HTS221_READY),
348 "hygro_set_sensitivity(), invalid state");
349
350 devp->hygrosensitivity = *sp;
351 return msg;
352}
353
354/**
355 * @brief Reset sensitivity values for the BaseHygrometer.
356 * @note Default sensitivities value are obtained from device datasheet.
357 *
358 * @param[in] ip pointer to @p BaseHygrometer interface.
359 *
360 * @return The operation status.
361 * @retval MSG_OK if the function succeeded.
362 */
363static msg_t hygro_reset_sensitivity(void *ip) {
364 HTS221Driver* devp;
365 msg_t msg = MSG_OK;
366
367 osalDbgCheck(ip != NULL);
368
369 /* Getting parent instance pointer.*/
370 devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
371
372 osalDbgAssert((devp->state == HTS221_READY),
373 "hygro_reset_sensitivity(), invalid state");
374
375 devp->hygrosensitivity = devp->hygrofactorysensitivity;
376 return msg;
377}
378
379/**
380 * @brief Return the number of axes of the BaseThermometer.
381 *
382 * @param[in] ip pointer to @p BaseThermometer interface.
383 *
384 * @return the number of axes.
385 */
386static size_t thermo_get_axes_number(void *ip) {
387 (void)ip;
388
389 return HTS221_THERMO_NUMBER_OF_AXES;
390}
391
392/**
393 * @brief Retrieves raw data from the BaseThermometer.
394 * @note This data is retrieved from MEMS register without any algebraical
395 * manipulation.
396 * @note The axes array must be at least the same size of the
397 * BaseThermometer axes number.
398 *
399 * @param[in] ip pointer to @p BaseThermometer interface.
400 * @param[out] axes a buffer which would be filled with raw data.
401 *
402 * @return The operation status.
403 * @retval MSG_OK if the function succeeded.
404 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
405 * be retrieved using @p i2cGetErrors().
406 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
407 */
408static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
409 HTS221Driver* devp;
410 int16_t tmp;
411 uint8_t buff[2];
412 msg_t msg;
413
414 osalDbgCheck((ip != NULL) && (axes != NULL));
415
416 /* Getting parent instance pointer.*/
417 devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
418
419 osalDbgAssert((devp->state == HTS221_READY),
420 "thermo_read_raw(), invalid state");
421
422 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
423 "thermo_read_raw(), channel not ready");
424
425#if HTS221_SHARED_I2C
426 i2cAcquireBus(devp->config->i2cp);
427 i2cStart(devp->config->i2cp,
428 devp->config->i2ccfg);
429#endif /* HTS221_SHARED_I2C */
430
431 msg = hts221I2CReadRegister(devp->config->i2cp, HTS221_AD_TEMP_OUT_L,
432 buff, 2);
433
434#if HTS221_SHARED_I2C
435 i2cReleaseBus(devp->config->i2cp);
436#endif /* HTS221_SHARED_I2C */
437
438 if (msg == MSG_OK) {
439 tmp = buff[0] + (buff[1] << 8);
440 *axes = (int32_t)tmp;
441 }
442 return msg;
443}
444
445/**
446 * @brief Retrieves cooked data from the BaseThermometer.
447 * @note This data is manipulated according to the formula
448 * cooked = (raw * sensitivity) - bias.
449 * @note Final data is expressed as °C.
450 * @note The axes array must be at least the same size of the
451 * BaseThermometer axes number.
452 *
453 * @param[in] ip pointer to @p BaseThermometer interface.
454 * @param[out] axis a buffer which would be filled with cooked data.
455 *
456 * @return The operation status.
457 * @retval MSG_OK if the function succeeded.
458 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
459 * be retrieved using @p i2cGetErrors().
460 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
461 */
462static msg_t thermo_read_cooked(void *ip, float* axis) {
463 HTS221Driver* devp;
464 int32_t raw;
465 msg_t msg;
466
467 osalDbgCheck((ip != NULL) && (axis != NULL));
468
469 /* Getting parent instance pointer.*/
470 devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
471
472 osalDbgAssert((devp->state == HTS221_READY),
473 "thermo_read_cooked(), invalid state");
474
475 msg = thermo_read_raw(devp, &raw);
476
477 *axis = (raw * devp->thermosensitivity) - devp->thermobias;
478
479 return msg;
480}
481
482/**
483 * @brief Set bias values for the BaseThermometer.
484 * @note Bias must be expressed as °C.
485 * @note The bias buffer must be at least the same size of the
486 * BaseThermometer axes number.
487 *
488 * @param[in] ip pointer to @p BaseThermometer interface.
489 * @param[in] bp a buffer which contains biases.
490 *
491 * @return The operation status.
492 * @retval MSG_OK if the function succeeded.
493 */
494static msg_t thermo_set_bias(void *ip, float *bp) {
495 HTS221Driver* devp;
496 msg_t msg = MSG_OK;
497
498 osalDbgCheck((ip != NULL) && (bp != NULL));
499
500 /* Getting parent instance pointer.*/
501 devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
502
503 osalDbgAssert((devp->state == HTS221_READY),
504 "thermo_set_bias(), invalid state");
505
506 devp->thermobias = *bp;
507
508 return msg;
509}
510
511/**
512 * @brief Reset bias values for the BaseThermometer.
513 * @note Default biases value are obtained from device datasheet when
514 * available otherwise they are considered zero.
515 *
516 * @param[in] ip pointer to @p BaseThermometer interface.
517 *
518 * @return The operation status.
519 * @retval MSG_OK if the function succeeded.
520 */
521static msg_t thermo_reset_bias(void *ip) {
522 HTS221Driver* devp;
523 msg_t msg = MSG_OK;
524
525 osalDbgCheck(ip != NULL);
526
527 /* Getting parent instance pointer.*/
528 devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
529
530 osalDbgAssert((devp->state == HTS221_READY),
531 "thermo_reset_bias(), invalid state");
532
533 devp->thermobias = devp->thermofactorybias;
534
535 return msg;
536}
537
538/**
539 * @brief Set sensitivity values for the BaseThermometer.
540 * @note Sensitivity must be expressed as °C/LSB.
541 * @note The sensitivity buffer must be at least the same size of the
542 * BaseThermometer axes number.
543 *
544 * @param[in] ip pointer to @p BaseThermometer interface.
545 * @param[in] sp a buffer which contains sensitivities.
546 *
547 * @return The operation status.
548 * @retval MSG_OK if the function succeeded.
549 */
550static msg_t thermo_set_sensitivity(void *ip, float *sp) {
551 HTS221Driver* devp;
552 msg_t msg = MSG_OK;
553
554 osalDbgCheck((ip != NULL) && (sp != NULL));
555
556 /* Getting parent instance pointer.*/
557 devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
558
559 osalDbgAssert((devp->state == HTS221_READY),
560 "thermo_set_sensitivity(), invalid state");
561
562 devp->thermosensitivity = *sp;
563
564 return msg;
565}
566
567/**
568 * @brief Reset sensitivity values for the BaseThermometer.
569 * @note Default sensitivities value are obtained from device datasheet.
570 *
571 * @param[in] ip pointer to @p BaseThermometer interface.
572 *
573 * @return The operation status.
574 * @retval MSG_OK if the function succeeded.
575 */
576static msg_t thermo_reset_sensitivity(void *ip) {
577 HTS221Driver* devp;
578 msg_t msg = MSG_OK;
579
580 osalDbgCheck(ip != NULL);
581
582 /* Getting parent instance pointer.*/
583 devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
584
585 osalDbgAssert((devp->state == HTS221_READY),
586 "thermo_reset_sensitivity(), invalid state");
587
588 devp->thermosensitivity = devp->thermofactorysensitivity;
589
590 return msg;
591}
592
593static const struct HTS221VMT vmt_device = {
594 (size_t)0
595};
596
597static const struct BaseHygrometerVMT vmt_hygrometer = {
598 sizeof(struct HTS221VMT*),
599 hygro_get_axes_number, hygro_read_raw, hygro_read_cooked,
600 hygro_set_bias, hygro_reset_bias, hygro_set_sensitivity,
601 hygro_reset_sensitivity
602};
603
604static const struct BaseThermometerVMT vmt_thermometer = {
605 sizeof(struct HTS221VMT*) + sizeof(BaseHygrometer),
606 thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
607 thermo_set_bias, thermo_reset_bias, thermo_set_sensitivity,
608 thermo_reset_sensitivity
609};
610
611/*===========================================================================*/
612/* Driver exported functions. */
613/*===========================================================================*/
614
615/**
616 * @brief Initializes an instance.
617 *
618 * @param[out] devp pointer to the @p HTS221Driver object
619 *
620 * @init
621 */
622void hts221ObjectInit(HTS221Driver *devp) {
623
624 devp->vmt = &vmt_device;
625 devp->hygro_if.vmt = &vmt_hygrometer;
626 devp->thermo_if.vmt = &vmt_thermometer;
627
628 devp->config = NULL;
629
630 devp->hygroaxes = HTS221_HYGRO_NUMBER_OF_AXES;
631 devp->thermoaxes = HTS221_THERMO_NUMBER_OF_AXES;
632
633 devp->hygrobias = 0.0f;
634 devp->thermobias = 0.0f;
635
636 devp->state = HTS221_STOP;
637}
638
639/**
640 * @brief Configures and activates HTS221 Complex Driver peripheral.
641 *
642 * @param[in] devp pointer to the @p HTS221Driver object
643 * @param[in] config pointer to the @p HTS221Config object
644 *
645 * @api
646 */
647void hts221Start(HTS221Driver *devp, const HTS221Config *config) {
648 uint8_t cr[2];
649 osalDbgCheck((devp != NULL) && (config != NULL));
650
651 osalDbgAssert((devp->state == HTS221_STOP) || (devp->state == HTS221_READY),
652 "hts221Start(), invalid state");
653
654 devp->config = config;
655
656#if HTS221_SHARED_I2C
657 i2cAcquireBus(devp->config->i2cp);
658#endif /* HTS221_SHARED_I2C */
659
660 /* Intializing the I2C. */
661 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
662
663 hts221Calibrate(devp);
664
665#if HTS221_SHARED_I2C
666 i2cReleaseBus(devp->config->i2cp);
667#endif /* HTS221_SHARED_I2C */
668
669
670 if(devp->config->hygrosensitivity == NULL) {
671 devp->hygrosensitivity = devp->hygrofactorysensitivity;
672 }
673 else{
674 /* Taking hygrometer sensitivity from user configurations */
675 devp->hygrosensitivity = *(devp->config->hygrosensitivity);
676 }
677
678 if(devp->config->hygrobias == NULL) {
679 devp->hygrobias = devp->hygrofactorybias;
680 }
681 else{
682 /* Taking hygrometer bias from user configurations */
683 devp->hygrobias = *(devp->config->hygrobias);
684 }
685
686 if(devp->config->thermosensitivity == NULL) {
687 devp->thermosensitivity = devp->thermofactorysensitivity;
688 }
689 else{
690 /* Taking thermometer sensitivity from user configurations */
691 devp->thermosensitivity = *(devp->config->thermosensitivity);
692 }
693
694 if(devp->config->thermobias == NULL) {
695 devp->thermobias = devp->thermofactorybias;
696 }
697 else{
698 /* Taking thermometer bias from user configurations */
699 devp->thermobias = *(devp->config->thermobias);
700 }
701
702 /* Control register 1 configuration block.*/
703 {
704 cr[0] = HTS221_AD_CTRL_REG1;
705 cr[1] = devp->config->outputdatarate | HTS221_CTRL_REG1_PD;
706#if HTS221_USE_ADVANCED || defined(__DOXYGEN__)
707 cr[1] |= devp->config->blockdataupdate;
708#endif
709
710#if HTS221_SHARED_I2C
711 i2cAcquireBus(devp->config->i2cp);
712 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
713#endif /* HTS221_SHARED_I2C */
714
715 hts221I2CWriteRegister(devp->config->i2cp, cr, 1);
716
717#if HTS221_SHARED_I2C
718 i2cReleaseBus(devp->config->i2cp);
719#endif /* HTS221_SHARED_I2C */
720 }
721
722 /* Average register configuration block.*/
723 {
724 cr[0] = HTS221_AD_AV_CONF;
725 cr[1] = 0x05;
726#if HTS221_USE_ADVANCED || defined(__DOXYGEN__)
727 cr[1] = devp->config->hygroresolution | devp->config->thermoresolution;
728#endif
729
730#if HTS221_SHARED_I2C
731 i2cAcquireBus(devp->config->i2cp);
732 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
733#endif /* HTS221_SHARED_I2C */
734
735 hts221I2CWriteRegister(devp->config->i2cp, cr, 1);
736
737#if HTS221_SHARED_I2C
738 i2cReleaseBus(devp->config->i2cp);
739#endif /* HTS221_SHARED_I2C */
740 }
741
742 /* This is the MEMS transient recovery time */
743 osalThreadSleepMilliseconds(5);
744
745 devp->state = HTS221_READY;
746}
747
748/**
749 * @brief Deactivates the HTS221 Complex Driver peripheral.
750 *
751 * @param[in] devp pointer to the @p HTS221Driver object
752 *
753 * @api
754 */
755void hts221Stop(HTS221Driver *devp) {
756 uint8_t cr[2];
757
758 osalDbgCheck(devp != NULL);
759
760 osalDbgAssert((devp->state == HTS221_STOP) || (devp->state == HTS221_READY),
761 "hts221Stop(), invalid state");
762
763 if (devp->state == HTS221_READY) {
764
765#if HTS221_SHARED_I2C
766 i2cAcquireBus(devp->config->i2cp);
767 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
768#endif /* HTS221_SHARED_I2C */
769
770 cr[0] = HTS221_AD_CTRL_REG1;
771 cr[1] = 0;
772 hts221I2CWriteRegister(devp->config->i2cp, cr, 1);
773
774 i2cStop(devp->config->i2cp);
775#if HTS221_SHARED_I2C
776 i2cReleaseBus(devp->config->i2cp);
777#endif /* HTS221_SHARED_I2C */
778 }
779 devp->state = HTS221_STOP;
780}
781/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/hts221.h b/lib/chibios/os/ex/devices/ST/hts221.h
new file mode 100644
index 000000000..263978ecf
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/hts221.h
@@ -0,0 +1,707 @@
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 hts221.h
23 * @brief HTS221 MEMS interface module header.
24 *
25 *
26 * @addtogroup HTS221
27 * @ingroup EX_ST
28 * @{
29 */
30#ifndef _HTS221_H_
31#define _HTS221_H_
32
33#include "ex_hygrometer.h"
34#include "ex_thermometer.h"
35
36/*===========================================================================*/
37/* Driver constants. */
38/*===========================================================================*/
39
40/**
41 * @name Version identification
42 * @{
43 */
44/**
45 * @brief HTS221 driver version string.
46 */
47#define EX_HTS221_VERSION "1.1.2"
48
49/**
50 * @brief HTS221 driver version major number.
51 */
52#define EX_HTS221_MAJOR 1
53
54/**
55 * @brief HTS221 driver version minor number.
56 */
57#define EX_HTS221_MINOR 1
58
59/**
60 * @brief HTS221 driver version patch number.
61 */
62#define EX_HTS221_PATCH 2
63/** @} */
64
65/**
66 * @brief HTS221 hygrometer subsystem characteristics.
67 * @note Sensitivity is expressed as %rH/LSB whereas %rH stand for percentage
68 * of relative humidity.
69 * @note Bias is expressed as %rH.
70 * @{
71 */
72#define HTS221_HYGRO_NUMBER_OF_AXES 1U
73
74#define HTS221_HYGRO_SENS 0.00390625f
75#define HTS221_HYGRO_BIAS 0.0f
76/** @} */
77
78/**
79 * @brief HTS221 thermometer subsystem characteristics.
80 * @note Sensitivity is expressed as �C/LSB.
81 * @note Bias is expressed as �C.
82 *
83 * @{
84 */
85#define HTS221_THERMO_NUMBER_OF_AXES 1U
86
87#define HTS221_THERMO_SENS 0.0015625f
88#define HTS221_THERMO_BIAS 0.0f
89/** @} */
90
91/**
92 * @name HTS221 communication interfaces related bit masks
93 * @{
94 */
95#define HTS221_DI_MASK 0xFF
96#define HTS221_DI(n) (1 << n)
97#define HTS221_AD_MASK 0x3F
98#define HTS221_AD(n) (1 << n)
99#define HTS221_MS (1 << 6)
100#define HTS221_RW (1 << 7)
101
102#define HTS221_SUB_MS (1 << 7)
103
104#define HTS221_SAD 0x5F
105/** @} */
106
107/**
108 * @name HTS221 register addresses
109 * @{
110 */
111#define HTS221_AD_WHO_AM_I 0x0F
112#define HTS221_AD_AV_CONF 0x10
113#define HTS221_AD_CTRL_REG1 0x20
114#define HTS221_AD_CTRL_REG2 0x21
115#define HTS221_AD_CTRL_REG3 0x22
116#define HTS221_AD_STATUS_REG 0x27
117#define HTS221_AD_HUMIDITY_OUT_L 0x28
118#define HTS221_AD_HUMIDITY_OUT_H 0x29
119#define HTS221_AD_TEMP_OUT_L 0x2A
120#define HTS221_AD_TEMP_OUT_H 0x2B
121#define HTS221_AD_CALIB_0 0x30
122#define HTS221_AD_CALIB_1 0x31
123#define HTS221_AD_CALIB_2 0x32
124#define HTS221_AD_CALIB_3 0x33
125#define HTS221_AD_CALIB_4 0x34
126#define HTS221_AD_CALIB_5 0x35
127#define HTS221_AD_CALIB_6 0x36
128#define HTS221_AD_CALIB_7 0x37
129#define HTS221_AD_CALIB_8 0x38
130#define HTS221_AD_CALIB_9 0x39
131#define HTS221_AD_CALIB_A 0x3A
132#define HTS221_AD_CALIB_B 0x3B
133#define HTS221_AD_CALIB_C 0x3C
134#define HTS221_AD_CALIB_D 0x3D
135#define HTS221_AD_CALIB_E 0x3E
136#define HTS221_AD_CALIB_F 0x3F
137/** @} */
138
139/**
140 * @name HTS221_CTRL_REG1 register bits definitions
141 * @{
142 */
143#define HTS221_CTRL_REG1_MASK 0x87
144#define HTS221_CTRL_REG1_ODR0 (1 << 0)
145#define HTS221_CTRL_REG1_ODR1 (1 << 1)
146#define HTS221_CTRL_REG1_BDU (1 << 2)
147#define HTS221_CTRL_REG1_PD (1 << 7)
148/** @} */
149
150/**
151 * @name HTS221_CTRL_REG2 register bits definitions
152 * @{
153 */
154#define HTS221_CTRL_REG2_MASK 0x83
155#define HTS221_CTRL_REG2_ONE_SHOT (1 << 0)
156#define HTS221_CTRL_REG2_HEATER (1 << 1)
157#define HTS221_CTRL_REG2_BOOT (1 << 7)
158/** @} */
159
160/**
161 * @name HTS221_CTRL_REG3 register bits definitions
162 * @{
163 */
164#define HTS221_CTRL_REG3_MASK 0xC4
165#define HTS221_CTRL_REG3_DRDY (1 << 2)
166#define HTS221_CTRL_REG3_PP_OD (1 << 6)
167#define HTS221_CTRL_REG3_INT_H_L (1 << 7)
168/** @} */
169
170/*===========================================================================*/
171/* Driver pre-compile time settings. */
172/*===========================================================================*/
173
174/**
175 * @name Configuration options
176 * @{
177 */
178/**
179 * @brief HTS221 SPI interface switch.
180 * @details If set to @p TRUE the support for SPI is included.
181 * @note The default is @p FALSE.
182 */
183#if !defined(HTS221_USE_SPI) || defined(__DOXYGEN__)
184#define HTS221_USE_SPI FALSE
185#endif
186
187/**
188 * @brief HTS221 shared SPI switch.
189 * @details If set to @p TRUE the device acquires SPI bus ownership
190 * on each transaction.
191 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION
192 */
193#if !defined(HTS221_SHARED_SPI) || defined(__DOXYGEN__)
194#define HTS221_SHARED_SPI FALSE
195#endif
196
197/**
198 * @brief HTS221 I2C interface switch.
199 * @details If set to @p TRUE the support for I2C is included.
200 * @note The default is @p TRUE.
201 */
202#if !defined(HTS221_USE_I2C) || defined(__DOXYGEN__)
203#define HTS221_USE_I2C TRUE
204#endif
205
206/**
207 * @brief HTS221 shared I2C switch.
208 * @details If set to @p TRUE the device acquires I2C bus ownership
209 * on each transaction.
210 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION
211 */
212#if !defined(HTS221_SHARED_I2C) || defined(__DOXYGEN__)
213#define HTS221_SHARED_I2C FALSE
214#endif
215
216/**
217 * @brief HTS221 advanced configurations switch.
218 * @details If set to @p TRUE more configurations are available.
219 * @note The default is @p FALSE.
220 */
221#if !defined(HTS221_USE_ADVANCED) || defined(__DOXYGEN__)
222#define HTS221_USE_ADVANCED FALSE
223#endif
224/** @} */
225
226/*===========================================================================*/
227/* Derived constants and error checks. */
228/*===========================================================================*/
229
230#if !(HTS221_USE_SPI ^ HTS221_USE_I2C)
231#error "HTS221_USE_SPI and HTS221_USE_I2C cannot be both true or both false"
232#endif
233
234#if HTS221_USE_SPI && !HAL_USE_SPI
235#error "HTS221_USE_SPI requires HAL_USE_SPI"
236#endif
237
238#if HTS221_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
239#error "HTS221_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
240#endif
241
242#if HTS221_USE_I2C && !HAL_USE_I2C
243#error "HTS221_USE_I2C requires HAL_USE_I2C"
244#endif
245
246#if HTS221_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
247#error "HTS221_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
248#endif
249
250/*
251 * CHTODO: Add support for HTS221 over SPI.
252 */
253#if HTS221_USE_SPI
254#error "HTS221 over SPI still not supported."
255#endif
256
257/*===========================================================================*/
258/* Driver data structures and types. */
259/*===========================================================================*/
260
261/**
262 * @name HTS221 data structures and types.
263 * @{
264 */
265/**
266 * @brief Structure representing a HTS221 driver.
267 */
268typedef struct HTS221Driver HTS221Driver;
269
270/**
271 * @brief HTS221 output data rate and bandwidth.
272 */
273typedef enum {
274 HTS221_ODR_ONE_SHOT = 0x00, /**< One shot. */
275 HTS221_ODR_1HZ = 0x01, /**< Output data rate 1 Hz. */
276 HTS221_ODR_7HZ = 0x02, /**< Output data rate 7 Hz. */
277 HTS221_ODR_12P5HZ = 0x03, /**< Output data rate 12.5 Hz. */
278}hts221_odr_t;
279
280/**
281 * @brief HTS221 humidity resolution.
282 */
283typedef enum {
284 HTS221_AVGH_4 = 0x00, /**< Number of internal average is 4. */
285 HTS221_AVGH_8 = 0x01, /**< Number of internal average is 8. */
286 HTS221_AVGH_16 = 0x02, /**< Number of internal average is 16. */
287 HTS221_AVGH_32 = 0x03, /**< Number of internal average is 32. */
288 HTS221_AVGH_64 = 0x04, /**< Number of internal average is 64. */
289 HTS221_AVGH_128 = 0x05, /**< Number of internal average is 128. */
290 HTS221_AVGH_256 = 0x06, /**< Number of internal average is 256. */
291 HTS221_AVGH_512 = 0x07 /**< Number of internal average is 512. */
292}hts221_avgh_t;
293
294/**
295 * @brief HTS221 temperature resolution.
296 */
297typedef enum {
298 HTS221_AVGT_2 = 0x00, /**< Number of internal average is 2. */
299 HTS221_AVGT_4 = 0x08, /**< Number of internal average is 4. */
300 HTS221_AVGT_8 = 0x10, /**< Number of internal average is 8. */
301 HTS221_AVGT_16 = 0x18, /**< Number of internal average is 16. */
302 HTS221_AVGT_32 = 0x20, /**< Number of internal average is 32. */
303 HTS221_AVGT_64 = 0x28, /**< Number of internal average is 64. */
304 HTS221_AVGT_128 = 0x30, /**< Number of internal average is 128. */
305 HTS221_AVGT_256 = 0x38, /**< Number of internal average is 256. */
306}hts221_avgt_t;
307
308/**
309 * @brief HTS221 block data update.
310 */
311typedef enum {
312 HTS221_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
313 HTS221_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
314}hts221_bdu_t;
315
316/**
317 * @brief Driver state machine possible states.
318 */
319typedef enum {
320 HTS221_UNINIT = 0, /**< Not initialized. */
321 HTS221_STOP = 1, /**< Stopped. */
322 HTS221_READY = 2, /**< Ready. */
323} hts221_state_t;
324
325/**
326 * @brief HTS221 configuration structure.
327 */
328typedef struct {
329
330#if HTS221_USE_SPI || defined(__DOXYGEN__)
331 /**
332 * @brief SPI driver associated to this HTS221.
333 */
334 SPIDriver *spip;
335 /**
336 * @brief SPI configuration associated to this HTS221.
337 */
338 const SPIConfig *spicfg;
339#endif /* HTS221_USE_SPI */
340#if HTS221_USE_I2C || defined(__DOXYGEN__)
341 /**
342 * @brief I2C driver associated to this HTS221.
343 */
344 I2CDriver *i2cp;
345 /**
346 * @brief I2C configuration associated to this HTS221.
347 */
348 const I2CConfig *i2ccfg;
349#endif /* HTS221_USE_I2C */
350 /**
351 * @brief HTS221 hygrometer subsystem initial sensitivity.
352 */
353 float *hygrosensitivity;
354 /**
355 * @brief HTS221 hygrometer subsystem initial bias.
356 */
357 float *hygrobias;
358 /**
359 * @brief HTS221 thermometer subsystem initial sensitivity.
360 */
361 float *thermosensitivity;
362 /**
363 * @brief HTS221 thermometer subsystem initial bias.
364 */
365 float *thermobias;
366 /**
367 * @brief HTS221 output data rate selection.
368 */
369 hts221_odr_t outputdatarate;
370#if HTS221_USE_ADVANCED || defined(__DOXYGEN__)
371 /**
372 * @brief HTS221 block data update.
373 */
374 hts221_bdu_t blockdataupdate;
375 /**
376 * @brief HTS221 hygrometer subsystem resolution.
377 */
378 hts221_avgh_t hygroresolution;
379 /**
380 * @brief HTS221 thermometer subsystem resolution.
381 */
382 hts221_avgt_t thermoresolution;
383#endif
384} HTS221Config;
385
386/**
387 * @brief @p HTS221 specific methods.
388 * @note No methods so far, just a common ancestor interface.
389 */
390#define _hts221_methods_alone
391
392/**
393 * @brief @p HTS221 specific methods with inherited ones.
394 */
395#define _hts221_methods \
396 _base_object_methods \
397 _hts221_methods_alone
398
399/**
400 * @extends BaseObjectVMT
401 *
402 * @brief @p HTS221 virtual methods table.
403 */
404struct HTS221VMT {
405 _hts221_methods
406};
407
408/**
409 * @brief @p HTS221Driver specific data.
410 */
411#define _hts221_data \
412 /* Driver state.*/ \
413 hts221_state_t state; \
414 /* Current configuration data.*/ \
415 const HTS221Config *config; \
416 /* Hygrometer subsystem axes number.*/ \
417 size_t hygroaxes; \
418 /* Hygrometer subsystem current sensitivity.*/ \
419 float hygrosensitivity; \
420 /* Hygrometer subsystem current bias .*/ \
421 float hygrobias; \
422 /* Hygrometer subsystem factory sensitivity.*/ \
423 float hygrofactorysensitivity; \
424 /* Hygrometer subsystem factory bias .*/ \
425 float hygrofactorybias; \
426 /* Thermometer subsystem axes number.*/ \
427 size_t thermoaxes; \
428 /* Thermometer subsystem current sensitivity.*/ \
429 float thermosensitivity; \
430 /* Thermometer subsystem current bias.*/ \
431 float thermobias; \
432 /* Thermometer subsystem factory sensitivity.*/ \
433 float thermofactorysensitivity; \
434 /* Thermometer subsystem factory bias.*/ \
435 float thermofactorybias;
436
437/**
438 * @brief HTS221 2-axis hygrometer/thermometer class.
439 */
440struct HTS221Driver {
441 /** @brief Virtual Methods Table.*/
442 const struct HTS221VMT *vmt;
443 /** @brief Base hygrometer interface.*/
444 BaseHygrometer hygro_if;
445 /** @brief Base thermometer interface.*/
446 BaseThermometer thermo_if;
447 _hts221_data
448};
449/** @} */
450
451/*===========================================================================*/
452/* Driver macros. */
453/*===========================================================================*/
454
455/**
456 * @brief Return the number of axes of the BaseHygrometer.
457 *
458 * @param[in] devp pointer to @p HTS221Driver.
459 *
460 * @return the number of axes.
461 *
462 * @api
463 */
464#define hts221HygrometerGetAxesNumber(devp) \
465 hygrometerGetAxesNumber(&((devp)->hygro_if))
466
467/**
468 * @brief Retrieves raw data from the BaseHygrometer.
469 * @note This data is retrieved from MEMS register without any algebraical
470 * manipulation.
471 * @note The axes array must be at least the same size of the
472 * BaseHygrometer axes number.
473 *
474 * @param[in] devp pointer to @p HTS221Driver.
475 * @param[out] axes a buffer which would be filled with raw data.
476 *
477 * @return The operation status.
478 * @retval MSG_OK if the function succeeded.
479 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
480 * be retrieved using @p i2cGetErrors().
481 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
482 *
483 * @api
484 */
485#define hts221HygrometerReadRaw(devp, axes) \
486 hygrometerReadRaw(&((devp)->hygro_if), axes)
487
488/**
489 * @brief Retrieves cooked data from the BaseHygrometer.
490 * @note This data is manipulated according to the formula
491 * cooked = (raw * sensitivity) - bias.
492 * @note Final data is expressed as %rH.
493 * @note The axes array must be at least the same size of the
494 * BaseHygrometer axes number.
495 *
496 * @param[in] devp pointer to @p HTS221Driver.
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 * @api
506 */
507#define hts221HygrometerReadCooked(devp, axes) \
508 hygrometerReadCooked(&((devp)->hygro_if), axes)
509
510/**
511 * @brief Set bias values for the BaseHygrometer.
512 * @note Bias must be expressed as %rH.
513 * @note The bias buffer must be at least the same size of the
514 * BaseHygrometer axes number.
515 *
516 * @param[in] devp pointer to @p HTS221Driver.
517 * @param[in] bp a buffer which contains biases.
518 *
519 * @return The operation status.
520 * @retval MSG_OK if the function succeeded.
521 *
522 * @api
523 */
524#define hts221HygrometerSetBias(devp, bp) \
525 hygrometerSetBias(&((devp)->hygro_if), bp)
526
527/**
528 * @brief Reset bias values for the BaseHygrometer.
529 * @note Default biases value are obtained from device datasheet when
530 * available otherwise they are considered zero.
531 *
532 * @param[in] devp pointer to @p HTS221Driver.
533 *
534 * @return The operation status.
535 * @retval MSG_OK if the function succeeded.
536 *
537 * @api
538 */
539#define hts221HygrometerResetBias(devp) \
540 hygrometerResetBias(&((devp)->hygro_if))
541
542/**
543 * @brief Set sensitivity values for the BaseHygrometer.
544 * @note Sensitivity must be expressed as %rH/LSB.
545 * @note The sensitivity buffer must be at least the same size of the
546 * BaseHygrometer axes number.
547 *
548 * @param[in] devp pointer to @p HTS221Driver.
549 * @param[in] sp a buffer which contains sensitivities.
550 *
551 * @return The operation status.
552 * @retval MSG_OK if the function succeeded.
553 *
554 * @api
555 */
556#define hts221HygrometerSetSensitivity(devp, sp) \
557 hygrometerSetSensitivity(&((devp)->hygro_if), sp)
558
559/**
560 * @brief Reset sensitivity values for the BaseHygrometer.
561 * @note Default sensitivities value are obtained from device datasheet.
562 *
563 * @param[in] devp pointer to @p HTS221Driver.
564 *
565 * @return The operation status.
566 * @retval MSG_OK if the function succeeded.
567 *
568 * @api
569 */
570#define hts221HygrometerResetSensitivity(devp) \
571 hygrometerResetSensitivity(&((devp)->hygro_if))
572
573/**
574 * @brief Return the number of axes of the BaseThermometer.
575 *
576 * @param[in] devp pointer to @p HTS221Driver.
577 *
578 * @return the number of axes.
579 *
580 * @api
581 */
582#define hts221ThermometerGetAxesNumber(devp) \
583 thermometerGetAxesNumber(&((devp)->thermo_if))
584
585/**
586 * @brief Retrieves raw data from the BaseThermometer.
587 * @note This data is retrieved from MEMS register without any algebraical
588 * manipulation.
589 * @note The axes array must be at least the same size of the
590 * BaseThermometer axes number.
591 *
592 * @param[in] devp pointer to @p HTS221Driver.
593 * @param[out] axes a buffer which would be filled with raw data.
594 *
595 * @return The operation status.
596 * @retval MSG_OK if the function succeeded.
597 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
598 * be retrieved using @p i2cGetErrors().
599 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
600 *
601 * @api
602 */
603#define hts221ThermometerReadRaw(devp, axes) \
604 thermometerReadRaw(&((devp)->thermo_if), axes)
605
606/**
607 * @brief Retrieves cooked data from the BaseThermometer.
608 * @note This data is manipulated according to the formula
609 * cooked = (raw * sensitivity) - bias.
610 * @note Final data is expressed as �C.
611 * @note The axes array must be at least the same size of the
612 * BaseThermometer axes number.
613 *
614 * @param[in] devp pointer to @p HTS221Driver.
615 * @param[out] axes a buffer which would be filled with cooked data.
616 *
617 * @return The operation status.
618 * @retval MSG_OK if the function succeeded.
619 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
620 * be retrieved using @p i2cGetErrors().
621 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
622 *
623 * @api
624 */
625#define hts221ThermometerReadCooked(devp, axes) \
626 thermometerReadCooked(&((devp)->thermo_if), axes)
627
628/**
629 * @brief Set bias values for the BaseThermometer.
630 * @note Bias must be expressed as �C.
631 * @note The bias buffer must be at least the same size of the
632 * BaseThermometer axes number.
633 *
634 * @param[in] devp pointer to @p HTS221Driver.
635 * @param[in] bp a buffer which contains biases.
636 *
637 * @return The operation status.
638 * @retval MSG_OK if the function succeeded.
639 *
640 * @api
641 */
642#define hts221ThermometerSetBias(devp, bp) \
643 thermometerSetBias(&((devp)->thermo_if), bp)
644
645/**
646 * @brief Reset bias values for the BaseThermometer.
647 * @note Default biases value are obtained from device datasheet when
648 * available otherwise they are considered zero.
649 *
650 * @param[in] devp pointer to @p HTS221Driver.
651 *
652 * @return The operation status.
653 * @retval MSG_OK if the function succeeded.
654 *
655 * @api
656 */
657#define hts221ThermometerResetBias(devp) \
658 thermometerResetBias(&((devp)->thermo_if))
659
660/**
661 * @brief Set sensitivity values for the BaseThermometer.
662 * @note Sensitivity must be expressed as �C/LSB.
663 * @note The sensitivity buffer must be at least the same size of the
664 * BaseThermometer axes number.
665 *
666 * @param[in] devp pointer to @p HTS221Driver.
667 * @param[in] sp a buffer which contains sensitivities.
668 *
669 * @return The operation status.
670 * @retval MSG_OK if the function succeeded.
671 *
672 * @api
673 */
674#define hts221ThermometerSetSensitivity(devp, sp) \
675 thermometerSetSensitivity(&((devp)->thermo_if), sp)
676
677/**
678 * @brief Reset sensitivity values for the BaseThermometer.
679 * @note Default sensitivities value are obtained from device datasheet.
680 *
681 * @param[in] devp pointer to @p HTS221Driver.
682 *
683 * @return The operation status.
684 * @retval MSG_OK if the function succeeded.
685 *
686 * @api
687 */
688#define hts221ThermometerResetSensitivity(devp) \
689 thermometerResetSensitivity(&((devp)->thermo_if))
690
691/*===========================================================================*/
692/* External declarations. */
693/*===========================================================================*/
694
695#ifdef __cplusplus
696extern "C" {
697#endif
698 void hts221ObjectInit(HTS221Driver *devp);
699 void hts221Start(HTS221Driver *devp, const HTS221Config *config);
700 void hts221Stop(HTS221Driver *devp);
701#ifdef __cplusplus
702}
703#endif
704
705#endif /* _HTS221_H_ */
706
707/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/hts221.mk b/lib/chibios/os/ex/devices/ST/hts221.mk
new file mode 100644
index 000000000..49bcfeb08
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/hts221.mk
@@ -0,0 +1,10 @@
1# List of all the HTS221 device files.
2HTS221SRC := $(CHIBIOS)/os/ex/devices/ST/hts221.c
3
4# Required include directories
5HTS221INC := $(CHIBIOS)/os/ex/include \
6 $(CHIBIOS)/os/ex/devices/ST
7
8# Shared variables
9ALLCSRC += $(HTS221SRC)
10ALLINC += $(HTS221INC) \ No newline at end of file
diff --git a/lib/chibios/os/ex/devices/ST/l3gd20.c b/lib/chibios/os/ex/devices/ST/l3gd20.c
new file mode 100644
index 000000000..82f5d544d
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/l3gd20.c
@@ -0,0 +1,642 @@
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 l3gd20.c
23 * @brief L3GD20 MEMS interface module code.
24 *
25 * @addtogroup L3GD20
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "l3gd20.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 (L3GD20_USE_SPI) || defined(__DOXYGEN__)
50/**
51 * @brief Reads a generic register value using SPI.
52 * @pre The SPI interface must be initialized and the driver started.
53 *
54 * @param[in] spip pointer to the SPI interface
55 * @param[in] reg starting register address
56 * @param[in] n number of consecutive registers to read
57 * @param[in] b pointer to an output buffer.
58 */
59static void l3gd20SPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n,
60 uint8_t* b) {
61 uint8_t cmd;
62 (n == 1) ? (cmd = reg | L3GD20_RW) : (cmd = reg | L3GD20_RW | L3GD20_MS);
63 spiSelect(spip);
64 spiSend(spip, 1, &cmd);
65 spiReceive(spip, n, b);
66 spiUnselect(spip);
67}
68
69/**
70 * @brief Writes a value into a generic register using SPI.
71 * @pre The SPI interface must be initialized and the driver started.
72 *
73 * @param[in] spip pointer to the SPI interface
74 * @param[in] reg starting register address
75 * @param[in] n number of adjacent registers to write
76 * @param[in] b pointer to a buffer of values.
77 */
78static void l3gd20SPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n,
79 uint8_t* b) {
80 uint8_t cmd;
81 (n == 1) ? (cmd = reg) : (cmd = reg | L3GD20_MS);
82 spiSelect(spip);
83 spiSend(spip, 1, &cmd);
84 spiSend(spip, n, b);
85 spiUnselect(spip);
86}
87#endif /* L3GD20_USE_SPI */
88
89/**
90 * @brief Return the number of axes of the BaseGyroscope.
91 *
92 * @param[in] ip pointer to @p BaseGyroscope interface.
93 *
94 * @return the number of axes.
95 */
96static size_t gyro_get_axes_number(void *ip) {
97 (void)ip;
98
99 return L3GD20_GYRO_NUMBER_OF_AXES;
100}
101
102/**
103 * @brief Retrieves raw data from the BaseGyroscope.
104 * @note This data is retrieved from MEMS register without any algebraical
105 * manipulation.
106 * @note The axes array must be at least the same size of the
107 * BaseGyroscope axes number.
108 *
109 * @param[in] ip pointer to @p BaseGyroscope interface.
110 * @param[out] axes a buffer which would be filled with raw data.
111 *
112 * @return The operation status.
113 * @retval MSG_OK if the function succeeded.
114 */
115static msg_t gyro_read_raw(void *ip, int32_t axes[L3GD20_GYRO_NUMBER_OF_AXES]) {
116 L3GD20Driver* devp;
117 int16_t tmp;
118 uint8_t i, buff [2 * L3GD20_GYRO_NUMBER_OF_AXES];
119 msg_t msg = MSG_OK;
120
121 osalDbgCheck((ip != NULL) && (axes != NULL));
122
123 /* Getting parent instance pointer.*/
124 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
125
126 osalDbgAssert((devp->state == L3GD20_READY),
127 "gyro_read_raw(), invalid state");
128#if L3GD20_USE_SPI
129 osalDbgAssert((devp->config->spip->state == SPI_READY),
130 "gyro_read_raw(), channel not ready");
131
132#if L3GD20_SHARED_SPI
133 spiAcquireBus(devp->config->spip);
134 spiStart(devp->config->spip,
135 devp->config->spicfg);
136#endif /* L3GD20_SHARED_SPI */
137
138 l3gd20SPIReadRegister(devp->config->spip, L3GD20_AD_OUT_X_L,
139 L3GD20_GYRO_NUMBER_OF_AXES * 2, buff);
140
141#if L3GD20_SHARED_SPI
142 spiReleaseBus(devp->config->spip);
143#endif /* L3GD20_SHARED_SPI */
144#endif /* L3GD20_USE_SPI */
145
146 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
147 tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
148 axes[i] = (int32_t)tmp;
149 }
150 return msg;
151}
152
153/**
154 * @brief Retrieves cooked data from the BaseGyroscope.
155 * @note This data is manipulated according to the formula
156 * cooked = (raw * sensitivity) - bias.
157 * @note Final data is expressed as DPS.
158 * @note The axes array must be at least the same size of the
159 * BaseGyroscope axes number.
160 *
161 * @param[in] ip pointer to @p BaseGyroscope interface.
162 * @param[out] axes a buffer which would be filled with cooked data.
163 *
164 * @return The operation status.
165 * @retval MSG_OK if the function succeeded.
166 */
167static msg_t gyro_read_cooked(void *ip, float axes[]) {
168 L3GD20Driver* devp;
169 uint32_t i;
170 int32_t raw[L3GD20_GYRO_NUMBER_OF_AXES];
171 msg_t msg;
172
173 osalDbgCheck((ip != NULL) && (axes != NULL));
174
175 /* Getting parent instance pointer.*/
176 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
177
178 osalDbgAssert((devp->state == L3GD20_READY),
179 "gyro_read_cooked(), invalid state");
180
181 msg = gyro_read_raw(ip, raw);
182 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++){
183 axes[i] = (raw[i] * devp->gyrosensitivity[i]) - devp->gyrobias[i];
184 }
185 return msg;
186}
187
188/**
189 * @brief Samples bias values for the BaseGyroscope.
190 * @note The L3GD20 shall not be moved during the whole procedure.
191 * @note After this function internal bias is automatically updated.
192 * @note The behavior of this function depends on @p L3GD20_BIAS_ACQ_TIMES
193 * and @p L3GD20_BIAS_SETTLING_US.
194 *
195 * @param[in] ip pointer to @p BaseGyroscope interface.
196 *
197 * @return The operation status.
198 * @retval MSG_OK if the function succeeded.
199 */
200static msg_t gyro_sample_bias(void *ip) {
201 L3GD20Driver* devp;
202 uint32_t i, j;
203 int32_t raw[L3GD20_GYRO_NUMBER_OF_AXES];
204 int32_t buff[L3GD20_GYRO_NUMBER_OF_AXES] = {0, 0, 0};
205 msg_t msg;
206
207 osalDbgCheck(ip != NULL);
208
209 /* Getting parent instance pointer.*/
210 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
211
212 osalDbgAssert((devp->state == L3GD20_READY),
213 "gyro_sample_bias(), invalid state");
214#if L3GD20_USE_SPI
215 osalDbgAssert((devp->config->spip->state == SPI_READY),
216 "gyro_sample_bias(), channel not ready");
217#endif
218
219 for(i = 0; i < L3GD20_BIAS_ACQ_TIMES; i++){
220 msg = gyro_read_raw(ip, raw);
221 if(msg != MSG_OK)
222 return msg;
223 for(j = 0; j < L3GD20_GYRO_NUMBER_OF_AXES; j++){
224 buff[j] += raw[j];
225 }
226 osalThreadSleepMicroseconds(L3GD20_BIAS_SETTLING_US);
227 }
228
229 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++){
230 devp->gyrobias[i] = (buff[i] / L3GD20_BIAS_ACQ_TIMES);
231 devp->gyrobias[i] *= devp->gyrosensitivity[i];
232 }
233 return msg;
234}
235
236/**
237 * @brief Set bias values for the BaseGyroscope.
238 * @note Bias must be expressed as DPS.
239 * @note The bias buffer must be at least the same size of the BaseGyroscope
240 * axes number.
241 *
242 * @param[in] ip pointer to @p BaseGyroscope interface.
243 * @param[in] bp a buffer which contains biases.
244 *
245 * @return The operation status.
246 * @retval MSG_OK if the function succeeded.
247 */
248static msg_t gyro_set_bias(void *ip, float *bp) {
249 L3GD20Driver* devp;
250 uint32_t i;
251 msg_t msg = MSG_OK;
252
253 osalDbgCheck((ip != NULL) && (bp != NULL));
254
255 /* Getting parent instance pointer.*/
256 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
257
258 osalDbgAssert((devp->state == L3GD20_READY),
259 "gyro_set_bias(), invalid state");
260
261 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
262 devp->gyrobias[i] = bp[i];
263 }
264 return msg;
265}
266
267/**
268 * @brief Reset bias values for the BaseGyroscope.
269 * @note Default biases value are obtained from device datasheet when
270 * available otherwise they are considered zero.
271 *
272 * @param[in] ip pointer to @p BaseGyroscope interface.
273 *
274 * @return The operation status.
275 * @retval MSG_OK if the function succeeded.
276 */
277static msg_t gyro_reset_bias(void *ip) {
278 L3GD20Driver* devp;
279 uint32_t i;
280 msg_t msg = MSG_OK;
281
282 osalDbgCheck(ip != NULL);
283
284 /* Getting parent instance pointer.*/
285 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
286
287 osalDbgAssert((devp->state == L3GD20_READY),
288 "gyro_reset_bias(), invalid state");
289
290 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
291 devp->gyrobias[i] = L3GD20_GYRO_BIAS;
292 return msg;
293}
294
295/**
296 * @brief Set sensitivity values for the BaseGyroscope.
297 * @note Sensitivity must be expressed as DPS/LSB.
298 * @note The sensitivity buffer must be at least the same size of the
299 * BaseGyroscope axes number.
300 *
301 * @param[in] ip pointer to @p BaseGyroscope interface.
302 * @param[in] sp a buffer which contains sensitivities.
303 *
304 * @return The operation status.
305 * @retval MSG_OK if the function succeeded.
306 */
307static msg_t gyro_set_sensivity(void *ip, float *sp) {
308 L3GD20Driver* devp;
309 uint32_t i;
310 msg_t msg = MSG_OK;
311
312 osalDbgCheck((ip != NULL) && (sp !=NULL));
313
314 /* Getting parent instance pointer.*/
315 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
316
317 osalDbgAssert((devp->state == L3GD20_READY),
318 "gyro_set_sensivity(), invalid state");
319
320 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
321 devp->gyrosensitivity[i] = sp[i];
322 }
323 return msg;
324}
325
326/**
327 * @brief Reset sensitivity values for the BaseGyroscope.
328 * @note Default sensitivities value are obtained from device datasheet.
329 *
330 * @param[in] ip pointer to @p BaseGyroscope interface.
331 *
332 * @return The operation status.
333 * @retval MSG_OK if the function succeeded.
334 * @retval MSG_RESET otherwise.
335 */
336static msg_t gyro_reset_sensivity(void *ip) {
337 L3GD20Driver* devp;
338 uint32_t i;
339 msg_t msg = MSG_OK;
340
341 osalDbgCheck(ip != NULL);
342
343 /* Getting parent instance pointer.*/
344 devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
345
346 osalDbgAssert((devp->state == L3GD20_READY),
347 "gyro_reset_sensivity(), invalid state");
348
349 if(devp->config->gyrofullscale == L3GD20_FS_250DPS)
350 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
351 devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_250DPS;
352 else if(devp->config->gyrofullscale == L3GD20_FS_500DPS)
353 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
354 devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_500DPS;
355 else if(devp->config->gyrofullscale == L3GD20_FS_2000DPS)
356 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
357 devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_2000DPS;
358 else {
359 osalDbgAssert(FALSE, "gyro_reset_sensivity(), full scale issue");
360 return MSG_RESET;
361 }
362 return msg;
363}
364
365/**
366 * @brief Changes the L3GD20Driver gyroscope fullscale value.
367 * @note This function also rescale sensitivities and biases based on
368 * previous and next fullscale value.
369 * @note A recalibration is highly suggested after calling this function.
370 *
371 * @param[in] devp pointer to @p BaseGyroscope interface.
372 * @param[in] fs new fullscale value.
373 *
374 * @return The operation status.
375 * @retval MSG_OK if the function succeeded.
376 * @retval MSG_RESET otherwise.
377 */
378static msg_t gyro_set_full_scale(L3GD20Driver *devp, l3gd20_fs_t fs) {
379 float newfs, scale;
380 uint8_t i, cr;
381 msg_t msg = MSG_OK;
382
383 osalDbgCheck(devp != NULL);
384
385 osalDbgAssert((devp->state == L3GD20_READY),
386 "gyro_set_full_scale(), invalid state");
387#if L3GD20_USE_SPI
388 osalDbgAssert((devp->config->spip->state == SPI_READY),
389 "gyro_set_full_scale(), channel not ready");
390#endif
391
392 if(fs == L3GD20_FS_250DPS) {
393 newfs = L3GD20_250DPS;
394 }
395 else if(fs == L3GD20_FS_500DPS) {
396 newfs = L3GD20_500DPS;
397 }
398 else if(fs == L3GD20_FS_2000DPS) {
399 newfs = L3GD20_2000DPS;
400 }
401 else {
402 return MSG_RESET;
403 }
404
405 if(newfs != devp->gyrofullscale) {
406 scale = newfs / devp->gyrofullscale;
407 devp->gyrofullscale = newfs;
408
409#if L3GD20_USE_SPI
410#if L3GD20_SHARED_SPI
411 spiAcquireBus(devp->config->spip);
412 spiStart(devp->config->spip,
413 devp->config->spicfg);
414#endif /* L3GD20_SHARED_SPI */
415
416 /* Updating register.*/
417 l3gd20SPIReadRegister(devp->config->spip,
418 L3GD20_AD_CTRL_REG4, 1, &cr);
419
420#if L3GD20_SHARED_SPI
421 spiReleaseBus(devp->config->spip);
422#endif /* L3GD20_SHARED_SPI */
423#endif /* L3GD20_USE_SPI */
424 cr &= ~(L3GD20_CTRL_REG4_FS_MASK);
425 cr |= fs;
426
427#if L3GD20_USE_SPI
428#if L3GD20_SHARED_SPI
429 spiAcquireBus(devp->config->spip);
430 spiStart(devp->config->spip,
431 devp->config->spicfg);
432#endif /* L3GD20_SHARED_SPI */
433
434 l3gd20SPIWriteRegister(devp->config->spip,
435 L3GD20_AD_CTRL_REG4, 1, &cr);
436#if L3GD20_SHARED_SPI
437 spiReleaseBus(devp->config->spip);
438#endif /* L3GD20_SHARED_SPI */
439#endif /* L3GD20_USE_SPI */
440
441 /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
442 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
443 devp->gyrosensitivity[i] *= scale;
444 devp->gyrobias[i] *= scale;
445 }
446 }
447 return msg;
448}
449
450static const struct L3GD20VMT vmt_device = {
451 (size_t)0,
452 gyro_set_full_scale
453};
454
455static const struct BaseGyroscopeVMT vmt_gyroscope = {
456 sizeof(struct L3GD20VMT*),
457 gyro_get_axes_number, gyro_read_raw, gyro_read_cooked,
458 gyro_sample_bias, gyro_set_bias, gyro_reset_bias,
459 gyro_set_sensivity, gyro_reset_sensivity
460};
461
462/*===========================================================================*/
463/* Driver exported functions. */
464/*===========================================================================*/
465
466/**
467 * @brief Initializes an instance.
468 *
469 * @param[out] devp pointer to the @p L3GD20Driver object
470 *
471 * @init
472 */
473void l3gd20ObjectInit(L3GD20Driver *devp) {
474 devp->vmt = &vmt_device;
475 devp->gyro_if.vmt = &vmt_gyroscope;
476
477 devp->config = NULL;
478
479 devp->state = L3GD20_STOP;
480}
481
482/**
483 * @brief Configures and activates L3GD20 Complex Driver peripheral.
484 *
485 * @param[in] devp pointer to the @p L3GD20Driver object
486 * @param[in] config pointer to the @p L3GD20Config object
487 *
488 * @api
489 */
490void l3gd20Start(L3GD20Driver *devp, const L3GD20Config *config) {
491 uint32_t i;
492 uint8_t cr[5] = {0, 0, 0, 0, 0};
493 osalDbgCheck((devp != NULL) && (config != NULL));
494
495 osalDbgAssert((devp->state == L3GD20_STOP) || (devp->state == L3GD20_READY),
496 "l3gd20Start(), invalid state");
497
498 devp->config = config;
499
500 /* Control register 1 configuration block.*/
501 {
502 cr[0] = L3GD20_CTRL_REG1_XEN | L3GD20_CTRL_REG1_YEN |
503 L3GD20_CTRL_REG1_ZEN | L3GD20_CTRL_REG1_PD |
504 devp->config->gyrooutputdatarate;
505#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
506 cr[0] |= devp->config->gyrobandwidth;
507#endif
508 }
509
510 /* Control register 2 configuration block.*/
511 {
512#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
513 if(devp->config->gyrohpmode != L3GD20_HPM_BYPASSED)
514 cr[1] = devp->config->gyrohpmode | devp->config->gyrohpconfiguration;
515#endif
516 }
517
518 /* Control register 4 configuration block.*/
519 {
520 cr[3] = devp->config->gyrofullscale;
521#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
522 cr[3] |= devp->config->gyroblockdataupdate |
523 devp->config->gyroendianness;
524#endif
525 }
526
527 /* Control register 5 configuration block.*/
528 {
529#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
530 if((devp->config->gyrohpmode != L3GD20_HPM_BYPASSED)) {
531 cr[4] = L3GD20_CTRL_REG5_HPEN;
532 if(devp->config->gyrolp2mode != L3GD20_LP2M_BYPASSED) {
533 cr[4] |= L3GD20_CTRL_REG5_INT1_SEL1 |
534 L3GD20_CTRL_REG5_OUT_SEL1;
535 }
536 else {
537 cr[4] |= L3GD20_CTRL_REG5_INT1_SEL0 |
538 L3GD20_CTRL_REG5_OUT_SEL0;
539 }
540 }
541#endif
542 }
543
544#if L3GD20_USE_SPI
545#if L3GD20_SHARED_SPI
546 spiAcquireBus(devp->config->spip);
547#endif /* L3GD20_SHARED_SPI */
548 spiStart(devp->config->spip,
549 devp->config->spicfg);
550
551 l3gd20SPIWriteRegister(devp->config->spip, L3GD20_AD_CTRL_REG1,
552 5, cr);
553#if L3GD20_SHARED_SPI
554 spiReleaseBus(devp->config->spip);
555#endif /* L3GD20_SHARED_SPI */
556#endif /* L3GD20_USE_SPI */
557
558 /* Storing sensitivity information according to full scale.*/
559 if(devp->config->gyrofullscale == L3GD20_FS_250DPS) {
560 devp->gyrofullscale = L3GD20_250DPS;
561 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
562 if (devp->config->gyrosensitivity == NULL)
563 devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_250DPS;
564 else
565 devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
566 }
567 }
568 else if(devp->config->gyrofullscale == L3GD20_FS_500DPS) {
569 devp->gyrofullscale = L3GD20_500DPS;
570 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
571 if (devp->config->gyrosensitivity == NULL)
572 devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_500DPS;
573 else
574 devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
575 }
576 }
577 else if(devp->config->gyrofullscale == L3GD20_FS_2000DPS) {
578 devp->gyrofullscale = L3GD20_2000DPS;
579 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
580 if (devp->config->gyrosensitivity == NULL)
581 devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_2000DPS;
582 else
583 devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
584 }
585 }
586 else
587 osalDbgAssert(FALSE, "l3gd20Start(), full scale issue");
588
589 /* Storing bias information.*/
590 if(devp->config->gyrobias != NULL) {
591 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
592 devp->gyrobias[i] = devp->config->gyrobias[i];
593 }
594 }
595 else {
596 for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
597 devp->gyrobias[i] = L3GD20_GYRO_BIAS;
598 }
599
600 /* This is the Gyroscope transient recovery time.*/
601 osalThreadSleepMilliseconds(10);
602
603 devp->state = L3GD20_READY;
604}
605
606/**
607 * @brief Deactivates the L3GD20 Complex Driver peripheral.
608 *
609 * @param[in] devp pointer to the @p L3GD20Driver object
610 *
611 * @api
612 */
613void l3gd20Stop(L3GD20Driver *devp) {
614 uint8_t cr1;
615 osalDbgCheck(devp != NULL);
616
617 osalDbgAssert((devp->state == L3GD20_STOP) || (devp->state == L3GD20_READY),
618 "l3gd20Stop(), invalid state");
619
620 if (devp->state == L3GD20_READY) {
621 /* Disabling all axes and enabling power down mode.*/
622 cr1 = 0;
623
624#if L3GD20_USE_SPI
625#if L3GD20_SHARED_SPI
626 spiAcquireBus(devp->config->spip);
627 spiStart(devp->config->spip,
628 devp->config->spicfg);
629#endif /* L3GD20_SHARED_SPI */
630
631 l3gd20SPIWriteRegister(devp->config->spip, L3GD20_AD_CTRL_REG1,
632 1, &cr1);
633 spiStop(devp->config->spip);
634
635#if L3GD20_SHARED_SPI
636 spiReleaseBus(devp->config->spip);
637#endif /* L3GD20_SHARED_SPI */
638#endif /* L3GD20_USE_SPI */
639 }
640 devp->state = L3GD20_STOP;
641}
642/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/l3gd20.h b/lib/chibios/os/ex/devices/ST/l3gd20.h
new file mode 100644
index 000000000..5528ecc05
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/l3gd20.h
@@ -0,0 +1,725 @@
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 l3gd20.h
23 * @brief L3GD20 MEMS interface module header.
24 *
25 * @addtogroup L3GD20
26 * @ingroup EX_ST
27 * @{
28 */
29#ifndef _L3GD20_H_
30#define _L3GD20_H_
31
32#include "ex_gyroscope.h"
33
34/*===========================================================================*/
35/* Driver constants. */
36/*===========================================================================*/
37
38/**
39 * @name Version identification
40 * @{
41 */
42/**
43 * @brief L3GD20 driver version string.
44 */
45#define EX_L3GD20_VERSION "1.1.2"
46
47/**
48 * @brief L3GD20 driver version major number.
49 */
50#define EX_L3GD20_MAJOR 1
51
52/**
53 * @brief L3GD20 driver version minor number.
54 */
55#define EX_L3GD20_MINOR 1
56
57/**
58 * @brief L3GD20 driver version patch number.
59 */
60#define EX_L3GD20_PATCH 2
61/** @} */
62
63/**
64 * @brief L3GD20 gyroscope system characteristics.
65 * @note Sensitivity is expressed as DPS/LSB whereas DPS stand for Degree
66 * per second [°/s].
67 * @note Bias is expressed as DPS.
68 *
69 * @{
70 */
71#define L3GD20_GYRO_NUMBER_OF_AXES 3U
72
73#define L3GD20_250DPS 250.0f
74#define L3GD20_500DPS 500.0f
75#define L3GD20_2000DPS 2000.0f
76
77#define L3GD20_GYRO_SENS_250DPS 0.00875f
78#define L3GD20_GYRO_SENS_500DPS 0.01750f
79#define L3GD20_GYRO_SENS_2000DPS 0.07000f
80
81#define L3GD20_GYRO_BIAS 0.0f
82/** @} */
83
84/**
85 * @name L3GD20 communication interfaces related bit masks
86 * @{
87 */
88#define L3GD20_DI_MASK 0xFF
89#define L3GD20_DI(n) (1 << n)
90#define L3GD20_AD_MASK 0x3F
91#define L3GD20_AD(n) (1 << n)
92#define L3GD20_MS (1 << 6)
93#define L3GD20_RW (1 << 7)
94/** @} */
95
96/**
97 * @name L3GD20 register addresses
98 * @{
99 */
100#define L3GD20_AD_WHO_AM_I 0x0F
101#define L3GD20_AD_CTRL_REG1 0x20
102#define L3GD20_AD_CTRL_REG2 0x21
103#define L3GD20_AD_CTRL_REG3 0x22
104#define L3GD20_AD_CTRL_REG4 0x23
105#define L3GD20_AD_CTRL_REG5 0x24
106#define L3GD20_AD_REFERENCE 0x25
107#define L3GD20_AD_OUT_TEMP 0x26
108#define L3GD20_AD_STATUS_REG 0x27
109#define L3GD20_AD_OUT_X_L 0x28
110#define L3GD20_AD_OUT_X_H 0x29
111#define L3GD20_AD_OUT_Y_L 0x2A
112#define L3GD20_AD_OUT_Y_H 0x2B
113#define L3GD20_AD_OUT_Z_L 0x2C
114#define L3GD20_AD_OUT_Z_H 0x2D
115#define L3GD20_AD_FIFO_CTRL_REG 0x2E
116#define L3GD20_AD_FIFO_SRC_REG 0x2F
117#define L3GD20_AD_INT1_CFG 0x30
118#define L3GD20_AD_INT1_SRC 0x31
119#define L3GD20_AD_INT1_THS_XH 0x32
120#define L3GD20_AD_INT1_THS_XL 0x33
121#define L3GD20_AD_INT1_THS_YH 0x34
122#define L3GD20_AD_INT1_THS_YL 0x35
123#define L3GD20_AD_INT1_THS_ZH 0x36
124#define L3GD20_AD_INT1_THS_ZL 0x37
125#define L3GD20_AD_INT1_DURATION 0x38
126/** @} */
127
128/**
129 * @name L3GD20_CTRL_REG1 register bits definitions
130 * @{
131 */
132#define L3GD20_CTRL_REG1_MASK 0xFF
133#define L3GD20_CTRL_REG1_XEN (1 << 0)
134#define L3GD20_CTRL_REG1_YEN (1 << 1)
135#define L3GD20_CTRL_REG1_ZEN (1 << 2)
136#define L3GD20_CTRL_REG1_PD (1 << 3)
137#define L3GD20_CTRL_REG1_BW0 (1 << 4)
138#define L3GD20_CTRL_REG1_BW1 (1 << 5)
139#define L3GD20_CTRL_REG1_DR0 (1 << 6)
140#define L3GD20_CTRL_REG1_DR1 (1 << 7)
141/** @} */
142
143/**
144 * @name L3GD20_CTRL_REG2 register bits definitions
145 * @{
146 */
147#define L3GD20_CTRL_REG2_MASK 0x3F
148#define L3GD20_CTRL_REG2_HPCF0 (1 << 0)
149#define L3GD20_CTRL_REG2_HPCF1 (1 << 1)
150#define L3GD20_CTRL_REG2_HPCF2 (1 << 2)
151#define L3GD20_CTRL_REG2_HPCF3 (1 << 3)
152#define L3GD20_CTRL_REG2_HPM0 (1 << 4)
153#define L3GD20_CTRL_REG2_HPM1 (1 << 5)
154/** @} */
155
156/**
157 * @name L3GD20_CTRL_REG3 register bits definitions
158 * @{
159 */
160#define L3GD20_CTRL_REG3_MASK 0xFF
161#define L3GD20_CTRL_REG3_I2_EMPTY (1 << 0)
162#define L3GD20_CTRL_REG3_I2_ORUN (1 << 1)
163#define L3GD20_CTRL_REG3_I2_WTM (1 << 2)
164#define L3GD20_CTRL_REG3_I2_DRDY (1 << 3)
165#define L3GD20_CTRL_REG3_PP_OD (1 << 4)
166#define L3GD20_CTRL_REG3_H_LACTIVE (1 << 5)
167#define L3GD20_CTRL_REG3_I1_BOOT (1 << 6)
168#define L3GD20_CTRL_REG3_I1_INT1 (1 << 7)
169/** @} */
170
171/**
172 * @name L3GD20_CTRL_REG4 register bits definitions
173 * @{
174 */
175#define L3GD20_CTRL_REG4_MASK 0xF1
176#define L3GD20_CTRL_REG4_SIM (1 << 0)
177#define L3GD20_CTRL_REG4_FS_MASK 0x30
178#define L3GD20_CTRL_REG4_FS0 (1 << 4)
179#define L3GD20_CTRL_REG4_FS1 (1 << 5)
180#define L3GD20_CTRL_REG4_BLE (1 << 6)
181#define L3GD20_CTRL_REG4_BDU (1 << 7)
182/** @} */
183
184/**
185 * @name L3GD20_CTRL_REG5 register bits definitions
186 * @{
187 */
188#define L3GD20_CTRL_REG5_MASK 0xDF
189#define L3GD20_CTRL_REG5_OUT_SEL0 (1 << 0)
190#define L3GD20_CTRL_REG5_OUT_SEL1 (1 << 1)
191#define L3GD20_CTRL_REG5_INT1_SEL0 (1 << 2)
192#define L3GD20_CTRL_REG5_INT1_SEL1 (1 << 3)
193#define L3GD20_CTRL_REG5_HPEN (1 << 4)
194#define L3GD20_CTRL_REG5_FIFO_EN (1 << 6)
195#define L3GD20_CTRL_REG5_BOOT (1 << 7)
196/** @} */
197
198/**
199 * @name L3GD20_INT1_CFG register bits definitions
200 * @{
201 */
202#define L3GD20_INT1_CFG_MASK 0xFF
203#define L3GD20_INT1_CFG_XLIE (1 << 0)
204#define L3GD20_INT1_CFG_XHIE (1 << 1)
205#define L3GD20_INT1_CFG_YLIE (1 << 2)
206#define L3GD20_INT1_CFG_YHIE (1 << 3)
207#define L3GD20_INT1_CFG_ZLIE (1 << 4)
208#define L3GD20_INT1_CFG_ZHIE (1 << 5)
209#define L3GD20_INT1_CFG_LIR (1 << 6)
210#define L3GD20_INT1_CFG_AND_OR (1 << 7)
211/** @} */
212
213/**
214 * @name L3GD20_INT1_SRC register bits definitions
215 * @{
216 */
217#define L3GD20_INT1_SRC_MASK 0x7F
218#define L3GD20_INT1_SRC_XL (1 << 0)
219#define L3GD20_INT1_SRC_XH (1 << 1)
220#define L3GD20_INT1_SRC_YL (1 << 2)
221#define L3GD20_INT1_SRC_YH (1 << 3)
222#define L3GD20_INT1_SRC_ZL (1 << 4)
223#define L3GD20_INT1_SRC_ZH (1 << 5)
224#define L3GD20_INT1_SRC_IA (1 << 6)
225/** @} */
226
227/*===========================================================================*/
228/* Driver pre-compile time settings. */
229/*===========================================================================*/
230
231/**
232 * @name Configuration options
233 * @{
234 */
235/**
236 * @brief L3GD20 SPI interface switch.
237 * @details If set to @p TRUE the support for SPI is included.
238 * @note The default is @p TRUE.
239 */
240#if !defined(L3GD20_USE_SPI) || defined(__DOXYGEN__)
241#define L3GD20_USE_SPI TRUE
242#endif
243
244/**
245 * @brief L3GD20 shared SPI switch.
246 * @details If set to @p TRUE the device acquires SPI bus ownership
247 * on each transaction.
248 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
249 */
250#if !defined(L3GD20_SHARED_SPI) || defined(__DOXYGEN__)
251#define L3GD20_SHARED_SPI FALSE
252#endif
253
254/**
255 * @brief L3GD20 I2C interface switch.
256 * @details If set to @p TRUE the support for I2C is included.
257 * @note The default is @p FALSE.
258 */
259#if !defined(L3GD20_USE_I2C) || defined(__DOXYGEN__)
260#define L3GD20_USE_I2C FALSE
261#endif
262
263/**
264 * @brief L3GD20 shared I2C switch.
265 * @details If set to @p TRUE the device acquires I2C bus ownership
266 * on each transaction.
267 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
268 */
269#if !defined(L3GD20_SHARED_I2C) || defined(__DOXYGEN__)
270#define L3GD20_SHARED_I2C FALSE
271#endif
272
273/**
274 * @brief L3GD20 advanced configurations switch.
275 * @details If set to @p TRUE more configurations are available.
276 * @note The default is @p FALSE.
277 */
278#if !defined(L3GD20_USE_ADVANCED) || defined(__DOXYGEN__)
279#define L3GD20_USE_ADVANCED FALSE
280#endif
281
282/**
283 * @brief Number of acquisitions for bias removal
284 * @details This is the number of acquisitions performed to compute the
285 * bias. A repetition is required in order to remove noise.
286 */
287#if !defined(L3GD20_BIAS_ACQ_TIMES) || defined(__DOXYGEN__)
288#define L3GD20_BIAS_ACQ_TIMES 50
289#endif
290
291/**
292 * @brief Settling time for bias removal
293 * @details This is the time between each bias acquisition.
294 */
295#if !defined(L3GD20_BIAS_SETTLING_US) || defined(__DOXYGEN__)
296#define L3GD20_BIAS_SETTLING_US 5000
297#endif
298/** @} */
299
300/*===========================================================================*/
301/* Derived constants and error checks. */
302/*===========================================================================*/
303
304#if !(L3GD20_USE_SPI ^ L3GD20_USE_I2C)
305#error "L3GD20_USE_SPI and L3GD20_USE_I2C cannot be both true or both false"
306#endif
307
308#if L3GD20_USE_SPI && !HAL_USE_SPI
309#error "L3GD20_USE_SPI requires HAL_USE_SPI"
310#endif
311
312#if L3GD20_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
313#error "L3GD20_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
314#endif
315
316#if L3GD20_USE_I2C && !HAL_USE_I2C
317#error "L3GD20_USE_I2C requires HAL_USE_I2C"
318#endif
319
320#if L3GD20_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
321#error "L3GD20_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
322#endif
323
324/*
325 * CHTODO: Add support for L3GD20 over I2C.
326 */
327#if L3GD20_USE_I2C
328#error "L3GD20 over I2C still not supported"
329#endif
330
331/*===========================================================================*/
332/* Driver data structures and types. */
333/*===========================================================================*/
334
335/**
336 * @name L3GD20 data structures and types.
337 * @{
338 */
339/**
340 * @brief Structure representing a L3GD20 driver.
341 */
342typedef struct L3GD20Driver L3GD20Driver;
343
344/**
345 * @brief L3GD20 full scale.
346 */
347typedef enum {
348 L3GD20_FS_250DPS = 0x00, /**< Full scale 250 degree per second. */
349 L3GD20_FS_500DPS = 0x10, /**< Full scale 500 degree per second. */
350 L3GD20_FS_2000DPS = 0x20 /**< Full scale 2000 degree per second. */
351} l3gd20_fs_t;
352
353/**
354 * @brief L3GD20 output data rate and bandwidth.
355 */
356typedef enum {
357 L3GD20_ODR_95HZ = 0x00, /**< Output data rate 95 Hz. */
358 L3GD20_ODR_190HZ = 0x40, /**< Output data rate 190 Hz. */
359 L3GD20_ODR_380HZ = 0x80, /**< Output data rate 380 Hz. */
360 L3GD20_ODR_760HZ = 0xC0 /**< Output data rate 760 Hz. */
361} l3gd20_odr_t;
362
363/**
364 * @brief L3GD20 low pass filter 1 bandwidth.
365 */
366typedef enum {
367 L3GD20_BW0 = 0x00, /**< LPF1 bandwidth. Depends on ODR. */
368 L3GD20_BW1 = 0x40, /**< LPF1 bandwidth. Depends on ODR. */
369 L3GD20_BW2 = 0x80, /**< LPF1 bandwidth. Depends on ODR. */
370 L3GD20_BW3 = 0xC0 /**< LPF1 bandwidth. Depends on ODR. */
371} l3gd20_bw_t;
372
373/**
374 * @brief L3GD20 block data update.
375 */
376typedef enum {
377 L3GD20_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
378 L3GD20_BDU_BLOCKED = 0x80 /**< Block data updated after reading. */
379} l3gd20_bdu_t;
380
381/**
382 * @brief L3GD20 HP filter mode.
383 */
384typedef enum {
385 L3GD20_HPM_NORMAL = 0x00, /**< Normal mode. */
386 L3GD20_HPM_REFERENCE = 0x10, /**< Reference signal for filtering. */
387 L3GD20_HPM_AUTORESET = 0x30, /**< Autoreset on interrupt event. */
388 L3GD20_HPM_BYPASSED = 0xFF /**< HP filter bypassed */
389} l3gd20_hpm_t;
390
391/**
392 * @brief L3GD20 HP configuration.
393 */
394typedef enum {
395 L3GD20_HPCF_0 = 0x00, /**< Depends on ODR (Table 26 for more).*/
396 L3GD20_HPCF_1 = 0x01, /**< Depends on ODR (Table 26 for more).*/
397 L3GD20_HPCF_2 = 0x02, /**< Depends on ODR (Table 26 for more).*/
398 L3GD20_HPCF_3 = 0x03, /**< Depends on ODR (Table 26 for more).*/
399 L3GD20_HPCF_4 = 0x04, /**< Depends on ODR (Table 26 for more).*/
400 L3GD20_HPCF_5 = 0x05, /**< Depends on ODR (Table 26 for more).*/
401 L3GD20_HPCF_6 = 0x06, /**< Depends on ODR (Table 26 for more).*/
402 L3GD20_HPCF_7 = 0x07, /**< Depends on ODR (Table 26 for more).*/
403 L3GD20_HPCF_8 = 0x08, /**< Depends on ODR (Table 26 for more).*/
404 L3GD20_HPCF_9 = 0x09 /**< Depends on ODR (Table 26 for more).*/
405} l3gd20_hpcf_t;
406
407/**
408 * @brief L3GD20 LP2 filter mode.
409 * @details To activate LP2 HP should be active
410 */
411typedef enum {
412 L3GD20_LP2M_ON = 0x00, /**< LP2 filter activated. */
413 L3GD20_LP2M_BYPASSED = 0xFF, /**< LP2 filter bypassed. */
414} l3gd20_lp2m_t;
415
416/**
417 * @brief L3GD20 endianness.
418 */
419typedef enum {
420 L3GD20_END_LITTLE = 0x00, /**< Little endian. */
421 L3GD20_END_BIG = 0x40 /**< Big endian. */
422} l3gd20_end_t;
423
424/**
425 * @brief Driver state machine possible states.
426 */
427typedef enum {
428 L3GD20_UNINIT = 0, /**< Not initialized. */
429 L3GD20_STOP = 1, /**< Stopped. */
430 L3GD20_READY = 2 /**< Ready. */
431} l3gd20_state_t;
432
433/**
434 * @brief L3GD20 configuration structure.
435 */
436typedef struct {
437
438#if L3GD20_USE_SPI || defined(__DOXYGEN__)
439 /**
440 * @brief SPI driver associated to this L3GD20.
441 */
442 SPIDriver *spip;
443 /**
444 * @brief SPI configuration associated to this L3GD20.
445 */
446 const SPIConfig *spicfg;
447#endif /* L3GD20_USE_SPI */
448#if L3GD20_USE_I2C || defined(__DOXYGEN__)
449 /**
450 * @brief I2C driver associated to this L3GD20.
451 */
452 I2CDriver *i2cp;
453 /**
454 * @brief I2C configuration associated to this L3GD20.
455 */
456 const I2CConfig *i2ccfg;
457#endif /* L3GD20_USE_I2C */
458 /**
459 * @brief L3GD20 gyroscope system initial sensitivity.
460 */
461 float *gyrosensitivity;
462 /**
463 * @brief L3GD20 gyroscope system initial bias.
464 */
465 float *gyrobias;
466 /**
467 * @brief L3GD20 gyroscope system initial full scale value.
468 */
469 l3gd20_fs_t gyrofullscale;
470 /**
471 * @brief L3GD20 gyroscope system output data rate selection.
472 */
473 l3gd20_odr_t gyrooutputdatarate;
474#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
475 /**
476 * @brief L3GD20 gyroscope system block data update.
477 */
478 l3gd20_bdu_t gyroblockdataupdate;
479 /**
480 * @brief L3GD20 gyroscope system endianness.
481 */
482 l3gd20_end_t gyroendianness;
483 /**
484 * @brief L3GD20 gyroscope system LP1 filter bandwidth.
485 */
486 l3gd20_bw_t gyrobandwidth;
487 /**
488 * @brief L3GD20 gyroscope system HP filter mode.
489 */
490 l3gd20_hpm_t gyrohpmode;
491 /**
492 * @brief L3GD20 gyroscope system HP configuration.
493 */
494 l3gd20_hpcf_t gyrohpconfiguration;
495 /**
496 * @brief L3GD20 gyroscope system LP2 filter mode.
497 * @details To activate LP2 HP should be active
498 */
499 l3gd20_lp2m_t gyrolp2mode;
500#endif
501} L3GD20Config;
502
503/**
504 * @brief @p L3GD20 specific methods.
505 */
506#define _l3gd20_methods_alone \
507 /* Change full scale value of L3GD20.*/ \
508 msg_t (*gyro_set_full_scale)(L3GD20Driver *devp, l3gd20_fs_t fs);
509
510/**
511 * @brief @p L3GD20 specific methods with inherited ones.
512 */
513#define _l3gd20_methods \
514 _base_object_methods \
515 _l3gd20_methods_alone
516
517/**
518 * @extends BaseObjectVMT
519 *
520 * @brief @p L3GD20 virtual methods table.
521 */
522struct L3GD20VMT {
523 _l3gd20_methods
524};
525
526/**
527 * @brief @p L3GD20Driver specific data.
528 */
529#define _l3gd20_data \
530 _base_sensor_data \
531 /* Driver state.*/ \
532 l3gd20_state_t state; \
533 /* Current configuration data.*/ \
534 const L3GD20Config *config; \
535 /* Gyroscope subsystem axes number.*/ \
536 size_t gyroaxes; \
537 /* Gyroscope subsystem current sensitivity.*/ \
538 float gyrosensitivity[L3GD20_GYRO_NUMBER_OF_AXES]; \
539 /* Gyroscope subsystem current Bias.*/ \
540 float gyrobias[L3GD20_GYRO_NUMBER_OF_AXES]; \
541 /* Gyroscope subsystem current full scale value.*/ \
542 float gyrofullscale;
543
544/**
545 * @brief L3GD20 3-axis gyroscope class.
546 */
547struct L3GD20Driver {
548 /** @brief Virtual Methods Table. */
549 const struct L3GD20VMT *vmt;
550 /** @brief Base gyroscope interface.*/
551 BaseGyroscope gyro_if;
552 _l3gd20_data
553};
554/** @} */
555
556/*===========================================================================*/
557/* Driver macros. */
558/*===========================================================================*/
559
560/**
561 * @brief Return the number of axes of the BaseGyroscope.
562 *
563 * @param[in] devp pointer to @p L3GD20Driver.
564 *
565 * @return the number of axes.
566 *
567 * @api
568 */
569#define l3gd20GyroscopeGetAxesNumber(devp) \
570 gyroscopeGetAxesNumber(&((devp)->gyro_if))
571
572/**
573 * @brief Retrieves raw data from the BaseGyroscope.
574 * @note This data is retrieved from MEMS register without any algebraical
575 * manipulation.
576 * @note The axes array must be at least the same size of the
577 * BaseGyroscope axes number.
578 *
579 * @param[in] devp pointer to @p L3GD20Driver.
580 * @param[out] axes a buffer which would be filled with raw data.
581 *
582 * @return The operation status.
583 * @retval MSG_OK if the function succeeded.
584 *
585 * @api
586 */
587#define l3gd20GyroscopeReadRaw(devp, axes) \
588 gyroscopeReadRaw(&((devp)->gyro_if), axes)
589
590/**
591 * @brief Retrieves cooked data from the BaseGyroscope.
592 * @note This data is manipulated according to the formula
593 * cooked = (raw * sensitivity) - bias.
594 * @note Final data is expressed as DPS.
595 * @note The axes array must be at least the same size of the
596 * BaseGyroscope axes number.
597 *
598 * @param[in] devp pointer to @p L3GD20Driver.
599 * @param[out] axes a buffer which would be filled with cooked data.
600 *
601 * @return The operation status.
602 * @retval MSG_OK if the function succeeded.
603 *
604 * @api
605 */
606#define l3gd20GyroscopeReadCooked(devp, axes) \
607 gyroscopeReadCooked(&((devp)->gyro_if), axes)
608
609/**
610 * @brief Samples bias values for the BaseGyroscope.
611 * @note The L3GD20 shall not be moved during the whole procedure.
612 * @note After this function internal bias is automatically updated.
613 * @note The behavior of this function depends on @p L3GD20_BIAS_ACQ_TIMES
614 * and @p L3GD20_BIAS_SETTLING_US.
615 *
616 * @param[in] devp pointer to @p L3GD20Driver.
617 *
618 * @return The operation status.
619 * @retval MSG_OK if the function succeeded.
620 *
621 * @api
622 */
623#define l3gd20GyroscopeSampleBias(devp) \
624 gyroscopeSampleBias(&((devp)->gyro_if))
625
626/**
627 * @brief Set bias values for the BaseGyroscope.
628 * @note Bias must be expressed as DPS.
629 * @note The bias buffer must be at least the same size of the BaseGyroscope
630 * axes number.
631 *
632 * @param[in] devp pointer to @p L3GD20Driver.
633 * @param[in] bp a buffer which contains biases.
634 *
635 * @return The operation status.
636 * @retval MSG_OK if the function succeeded.
637 *
638 * @api
639 */
640#define l3gd20GyroscopeSetBias(devp, bp) \
641 gyroscopeSetBias(&((devp)->gyro_if), bp)
642
643/**
644 * @brief Reset bias values for the BaseGyroscope.
645 * @note Default biases value are obtained from device datasheet when
646 * available otherwise they are considered zero.
647 *
648 * @param[in] devp pointer to @p L3GD20Driver.
649 *
650 * @return The operation status.
651 * @retval MSG_OK if the function succeeded.
652 *
653 * @api
654 */
655#define l3gd20GyroscopeResetBias(devp) \
656 gyroscopeResetBias(&((devp)->gyro_if))
657
658/**
659 * @brief Set sensitivity values for the BaseGyroscope.
660 * @note Sensitivity must be expressed as DPS/LSB.
661 * @note The sensitivity buffer must be at least the same size of the
662 * BaseGyroscope axes number.
663 *
664 * @param[in] devp pointer to @p L3GD20Driver.
665 * @param[in] sp a buffer which contains sensitivities.
666 *
667 * @return The operation status.
668 * @retval MSG_OK if the function succeeded.
669 *
670 * @api
671 */
672#define l3gd20GyroscopeSetSensitivity(devp, sp) \
673 gyroscopeSetSensitivity(&((devp)->gyro_if), sp)
674
675/**
676 * @brief Reset sensitivity values for the BaseGyroscope.
677 * @note Default sensitivities value are obtained from device datasheet.
678 *
679 * @param[in] devp pointer to @p L3GD20Driver.
680 *
681 * @return The operation status.
682 * @retval MSG_OK if the function succeeded.
683 * @retval MSG_RESET otherwise.
684 *
685 * @api
686 */
687#define l3gd20GyroscopeResetSensitivity(devp) \
688 gyroscopeResetSensitivity(&((devp)->gyro_if))
689
690/**
691 * @brief Changes the L3GD20Driver gyroscope fullscale value.
692 * @note This function also rescale sensitivities and biases based on
693 * previous and next fullscale value.
694 * @note A recalibration is highly suggested after calling this function.
695 *
696 * @param[in] devp pointer to @p L3GD20Driver.
697 * @param[in] fs new fullscale value.
698 *
699 * @return The operation status.
700 * @retval MSG_OK if the function succeeded.
701 * @retval MSG_RESET otherwise.
702 *
703 * @api
704 */
705#define l3gd20GyroscopeSetFullScale(devp, fs) \
706 (devp)->vmt->acc_set_full_scale(devp, fs)
707
708/*===========================================================================*/
709/* External declarations. */
710/*===========================================================================*/
711
712#ifdef __cplusplus
713extern "C" {
714#endif
715 void l3gd20ObjectInit(L3GD20Driver *devp);
716 void l3gd20Start(L3GD20Driver *devp, const L3GD20Config *config);
717 void l3gd20Stop(L3GD20Driver *devp);
718#ifdef __cplusplus
719}
720#endif
721
722#endif /* _L3GD20_H_ */
723
724/** @} */
725
diff --git a/lib/chibios/os/ex/devices/ST/l3gd20.mk b/lib/chibios/os/ex/devices/ST/l3gd20.mk
new file mode 100644
index 000000000..b8fae998e
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/l3gd20.mk
@@ -0,0 +1,10 @@
1# List of all the L3GD20 device files.
2L3GD20SRC := $(CHIBIOS)/os/ex/devices/ST/l3gd20.c
3
4# Required include directories
5L3GD20INC := $(CHIBIOS)/os/ex/include \
6 $(CHIBIOS)/os/ex/devices/ST
7
8# Shared variables
9ALLCSRC += $(L3GD20SRC)
10ALLINC += $(L3GD20INC) \ No newline at end of file
diff --git a/lib/chibios/os/ex/devices/ST/lis302dl.c b/lib/chibios/os/ex/devices/ST/lis302dl.c
new file mode 100644
index 000000000..f1e03cacc
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis302dl.c
@@ -0,0 +1,554 @@
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 lis302dl.c
23 * @brief LIS302DL MEMS interface module code.
24 *
25 * @addtogroup LIS302DL
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "lis302dl.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 (LIS302DL_USE_SPI) || defined(__DOXYGEN__)
50/**
51 * @brief Reads a generic register value using SPI.
52 * @pre The SPI interface must be initialized and the driver started.
53 *
54 * @param[in] spip pointer to the SPI interface
55 * @param[in] reg starting register address
56 * @param[in] n number of adjacent registers to write
57 * @param[in] b pointer to a buffer.
58 */
59static void lis302dlSPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n,
60 uint8_t* b) {
61 uint8_t cmd;
62 (n == 1) ? (cmd = reg | LIS302DL_RW) : (cmd = reg | LIS302DL_RW | LIS302DL_MS);
63 spiSelect(spip);
64 spiSend(spip, 1, &cmd);
65 spiReceive(spip, n, b);
66 spiUnselect(spip);
67}
68
69/**
70 * @brief Writes a value into a generic register using SPI.
71 * @pre The SPI interface must be initialized and the driver started.
72 *
73 * @param[in] spip pointer to the SPI interface
74 * @param[in] reg starting register address
75 * @param[in] n number of adjacent registers to write
76 * @param[in] b pointer to a buffer of values.
77 */
78static void lis302dlSPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n,
79 uint8_t* b) {
80 uint8_t cmd;
81 (n == 1) ? (cmd = reg) : (cmd = reg | LIS302DL_MS);
82 spiSelect(spip);
83 spiSend(spip, 1, &cmd);
84 spiSend(spip, n, b);
85 spiUnselect(spip);
86}
87#endif /* LIS302DL_USE_SPI */
88
89/**
90 * @brief Return the number of axes of the BaseAccelerometer.
91 *
92 * @param[in] ip pointer to @p BaseAccelerometer interface.
93 *
94 * @return the number of axes.
95 */
96static size_t acc_get_axes_number(void *ip) {
97 (void)ip;
98
99 return LIS302DL_ACC_NUMBER_OF_AXES;
100}
101
102/**
103 * @brief Retrieves raw data from the BaseAccelerometer.
104 * @note This data is retrieved from MEMS register without any algebraical
105 * manipulation.
106 * @note The axes array must be at least the same size of the
107 * BaseAccelerometer axes number.
108 *
109 * @param[in] ip pointer to @p BaseAccelerometer interface.
110 * @param[out] axes a buffer which would be filled with raw data.
111 *
112 * @return The operation status.
113 * @retval MSG_OK if the function succeeded.
114 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
115 * be retrieved using @p i2cGetErrors().
116 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
117 */
118static msg_t acc_read_raw(void *ip, int32_t axes[]) {
119 LIS302DLDriver* devp;
120 uint8_t i, tmp;
121 msg_t msg = MSG_OK;
122
123 osalDbgCheck((ip != NULL) && (axes != NULL));
124
125 /* Getting parent instance pointer.*/
126 devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
127
128 osalDbgAssert((devp->state == LIS302DL_READY),
129 "acc_read_raw(), invalid state");
130
131#if LIS302DL_USE_SPI
132#if LIS302DL_SHARED_SPI
133 osalDbgAssert((devp->config->spip->state == SPI_READY),
134 "acc_read_raw(), channel not ready");
135
136 spiAcquireBus(devp->config->spip);
137 spiStart(devp->config->spip,
138 devp->config->spicfg);
139#endif /* LIS302DL_SHARED_SPI */
140
141 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
142 lis302dlSPIReadRegister(devp->config->spip,
143 LIS302DL_AD_OUT_X + (i * 2), 1, &tmp);
144 axes[i] = (int32_t)((int8_t)tmp);
145 }
146
147#if LIS302DL_SHARED_SPI
148 spiReleaseBus(devp->config->spip);
149#endif /* LIS302DL_SHARED_SPI */
150#endif /* LIS302DL_USE_SPI */
151 return msg;
152}
153
154/**
155 * @brief Retrieves cooked data from the BaseAccelerometer.
156 * @note This data is manipulated according to the formula
157 * cooked = (raw * sensitivity) - bias.
158 * @note Final data is expressed as milli-G.
159 * @note The axes array must be at least the same size of the
160 * BaseAccelerometer axes number.
161 *
162 * @param[in] ip pointer to @p BaseAccelerometer interface.
163 * @param[out] axes a buffer which would be filled with cooked data.
164 *
165 * @return The operation status.
166 * @retval MSG_OK if the function succeeded.
167 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
168 * be retrieved using @p i2cGetErrors().
169 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
170 */
171static msg_t acc_read_cooked(void *ip, float axes[]) {
172 LIS302DLDriver* devp;
173 uint32_t i;
174 int32_t raw[LIS302DL_ACC_NUMBER_OF_AXES];
175 msg_t msg;
176
177 osalDbgCheck((ip != NULL) && (axes != NULL));
178
179 /* Getting parent instance pointer.*/
180 devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
181
182 osalDbgAssert((devp->state == LIS302DL_READY),
183 "acc_read_cooked(), invalid state");
184
185 msg = acc_read_raw(ip, raw);
186 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
187 axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
188 }
189 return msg;
190}
191
192/**
193 * @brief Set bias values for the BaseAccelerometer.
194 * @note Bias must be expressed as milli-G.
195 * @note The bias buffer must be at least the same size of the
196 * BaseAccelerometer axes number.
197 *
198 * @param[in] ip pointer to @p BaseAccelerometer interface.
199 * @param[in] bp a buffer which contains biases.
200 *
201 * @return The operation status.
202 * @retval MSG_OK if the function succeeded.
203 */
204static msg_t acc_set_bias(void *ip, float *bp) {
205 LIS302DLDriver* devp;
206 uint32_t i;
207 msg_t msg = MSG_OK;
208
209 osalDbgCheck((ip != NULL) && (bp != NULL));
210
211 /* Getting parent instance pointer.*/
212 devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
213
214 osalDbgAssert((devp->state == LIS302DL_READY),
215 "acc_set_bias(), invalid state");
216
217 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
218 devp->accbias[i] = bp[i];
219 }
220 return msg;
221}
222
223/**
224 * @brief Reset bias values for the BaseAccelerometer.
225 * @note Default biases value are obtained from device datasheet when
226 * available otherwise they are considered zero.
227 *
228 * @param[in] ip pointer to @p BaseAccelerometer interface.
229 *
230 * @return The operation status.
231 * @retval MSG_OK if the function succeeded.
232 */
233static msg_t acc_reset_bias(void *ip) {
234 LIS302DLDriver* devp;
235 uint32_t i;
236 msg_t msg = MSG_OK;
237
238 osalDbgCheck(ip != NULL);
239
240 /* Getting parent instance pointer.*/
241 devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
242
243 osalDbgAssert((devp->state == LIS302DL_READY),
244 "acc_reset_bias(), invalid state");
245
246 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
247 devp->accbias[i] = LIS302DL_ACC_BIAS;
248 return msg;
249}
250
251/**
252 * @brief Set sensitivity values for the BaseAccelerometer.
253 * @note Sensitivity must be expressed as milli-G/LSB.
254 * @note The sensitivity buffer must be at least the same size of the
255 * BaseAccelerometer axes number.
256 *
257 * @param[in] ip pointer to @p BaseAccelerometer interface.
258 * @param[in] sp a buffer which contains sensitivities.
259 *
260 * @return The operation status.
261 * @retval MSG_OK if the function succeeded.
262 */
263static msg_t acc_set_sensivity(void *ip, float *sp) {
264 LIS302DLDriver* devp;
265 uint32_t i;
266 msg_t msg = MSG_OK;
267
268 /* Getting parent instance pointer.*/
269 devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
270
271 osalDbgCheck((ip != NULL) && (sp != NULL));
272
273 osalDbgAssert((devp->state == LIS302DL_READY),
274 "acc_set_sensivity(), invalid state");
275
276 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
277 devp->accsensitivity[i] = sp[i];
278 }
279 return msg;
280}
281
282/**
283 * @brief Reset sensitivity values for the BaseAccelerometer.
284 * @note Default sensitivities value are obtained from device datasheet.
285 *
286 * @param[in] ip pointer to @p BaseAccelerometer interface.
287 *
288 * @return The operation status.
289 * @retval MSG_OK if the function succeeded.
290 * @retval MSG_RESET otherwise.
291 */
292static msg_t acc_reset_sensivity(void *ip) {
293 LIS302DLDriver* devp;
294 uint32_t i;
295 msg_t msg = MSG_OK;
296
297 osalDbgCheck(ip != NULL);
298
299 /* Getting parent instance pointer.*/
300 devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
301
302 osalDbgAssert((devp->state == LIS302DL_READY),
303 "acc_reset_sensivity(), invalid state");
304
305 if(devp->config->accfullscale == LIS302DL_ACC_FS_2G)
306 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
307 devp->accsensitivity[i] = LIS302DL_ACC_SENS_2G;
308 else if(devp->config->accfullscale == LIS302DL_ACC_FS_8G)
309 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
310 devp->accsensitivity[i] = LIS302DL_ACC_SENS_8G;
311 else {
312 osalDbgAssert(FALSE,
313 "acc_reset_sensivity(), accelerometer full scale issue");
314 return MSG_RESET;
315 }
316 return msg;
317}
318
319/**
320 * @brief Changes the LIS302DLDriver accelerometer fullscale value.
321 * @note This function also rescale sensitivities and biases based on
322 * previous and next fullscale value.
323 * @note A recalibration is highly suggested after calling this function.
324 *
325 * @param[in] devp pointer to @p LIS302DLDriver interface.
326 * @param[in] fs new fullscale value.
327 *
328 * @return The operation status.
329 * @retval MSG_OK if the function succeeded.
330 * @retval MSG_RESET otherwise.
331 */
332static msg_t acc_set_full_scale(LIS302DLDriver *devp, lis302dl_acc_fs_t fs) {
333 float newfs, scale;
334 uint8_t i, cr;
335 msg_t msg;
336
337 osalDbgCheck(devp != NULL);
338
339 osalDbgAssert((devp->state == LIS302DL_READY),
340 "acc_set_full_scale(), invalid state");
341 osalDbgAssert((devp->config->spip->state == SPI_READY),
342 "acc_set_full_scale(), channel not ready");
343
344 /* Computing new fullscale value.*/
345 if(fs == LIS302DL_ACC_FS_2G) {
346 newfs = LIS302DL_ACC_2G;
347 }
348 else if(fs == LIS302DL_ACC_FS_8G) {
349 newfs = LIS302DL_ACC_8G;
350 }
351 else {
352 msg = MSG_RESET;
353 return msg;
354 }
355
356 if(newfs != devp->accfullscale) {
357 /* Computing scale value.*/
358 scale = newfs / devp->accfullscale;
359 devp->accfullscale = newfs;
360
361#if LIS302DL_USE_SPI
362#if LIS302DL_SHARED_SPI
363 spiAcquireBus(devp->config->spip);
364 spiStart(devp->config->spip,
365 devp->config->spicfg);
366#endif /* LIS302DL_SHARED_SPI */
367
368 /* Getting data from register.*/
369 lis302dlSPIReadRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1, 1, &cr);
370
371#if LIS302DL_SHARED_SPI
372 spiReleaseBus(devp->config->spip);
373#endif /* LIS302DL_SHARED_SPI */
374#endif /* LIS302DL_USE_SPI */
375
376 cr &= ~(LIS302DL_CTRL_REG1_FS_MASK);
377 cr |= fs;
378
379#if LIS302DL_USE_SPI
380#if LIS302DL_SHARED_SPI
381 spiAcquireBus(devp->config->spip);
382 spiStart(devp->config->spip,
383 devp->config->spicfg);
384#endif /* LIS302DL_SHARED_SPI */
385
386 /* Getting data from register.*/
387 lis302dlSPIWriteRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1, 1, &cr);
388
389#if LIS302DL_SHARED_SPI
390 spiReleaseBus(devp->config->spip);
391#endif /* LIS302DL_SHARED_SPI */
392#endif /* LIS302DL_USE_SPI */
393
394 /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
395 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
396 devp->accsensitivity[i] *= scale;
397 devp->accbias[i] *= scale;
398 }
399 }
400 return msg;
401}
402
403static const struct LIS302DLVMT vmt_device = {
404 (size_t)0,
405 acc_set_full_scale
406};
407
408static const struct BaseAccelerometerVMT vmt_accelerometer = {
409 sizeof(struct LIS302DLVMT*),
410 acc_get_axes_number, acc_read_raw, acc_read_cooked,
411 acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
412};
413
414/*===========================================================================*/
415/* Driver exported functions. */
416/*===========================================================================*/
417
418/**
419 * @brief Initializes an instance.
420 *
421 * @param[out] devp pointer to the @p LIS302DLDriver object
422 *
423 * @init
424 */
425void lis302dlObjectInit(LIS302DLDriver *devp) {
426 devp->vmt = &vmt_device;
427 devp->acc_if.vmt = &vmt_accelerometer;
428
429 devp->config = NULL;
430
431 devp->accaxes = LIS302DL_ACC_NUMBER_OF_AXES;
432
433 devp->state = LIS302DL_STOP;
434}
435
436/**
437 * @brief Configures and activates LIS302DL Complex Driver peripheral.
438 *
439 * @param[in] devp pointer to the @p LIS302DLDriver object
440 * @param[in] config pointer to the @p LIS302DLConfig object
441 *
442 * @api
443 */
444void lis302dlStart(LIS302DLDriver *devp, const LIS302DLConfig *config) {
445 uint32_t i;
446 uint8_t cr[2] = {0, 0};
447 osalDbgCheck((devp != NULL) && (config != NULL));
448
449 osalDbgAssert((devp->state == LIS302DL_STOP) || (devp->state == LIS302DL_READY),
450 "lis302dlStart(), invalid state");
451
452 devp->config = config;
453
454 /* Control register 1 configuration block.*/
455 {
456 cr[0] = LIS302DL_CTRL_REG1_XEN | LIS302DL_CTRL_REG1_YEN |
457 LIS302DL_CTRL_REG1_ZEN | LIS302DL_CTRL_REG1_PD |
458 devp->config->accoutputdatarate |
459 devp->config->accfullscale;
460 }
461
462 /* Control register 2 configuration block.*/
463 {
464#if LIS302DL_USE_ADVANCED || defined(__DOXYGEN__)
465 if(devp->config->hpmode != LIS302DL_HPM_BYPASSED)
466 cr[1] = devp->config->acchighpass;
467#endif
468 }
469
470#if LIS302DL_USE_SPI
471#if LIS302DL_SHARED_SPI
472 spiAcquireBus((devp)->config->spip);
473#endif /* LIS302DL_SHARED_SPI */
474 spiStart((devp)->config->spip, (devp)->config->spicfg);
475
476 lis302dlSPIWriteRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1,
477 2, cr);
478
479#if LIS302DL_SHARED_SPI
480 spiReleaseBus((devp)->config->spip);
481#endif /* LIS302DL_SHARED_SPI */
482#endif /* LIS302DL_USE_SPI */
483
484 /* Storing sensitivity information according to full scale value */
485 if(devp->config->accfullscale == LIS302DL_ACC_FS_2G) {
486 devp->accfullscale = LIS302DL_ACC_2G;
487 if(devp->config->accsensitivity == NULL)
488 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
489 devp->accsensitivity[i] = LIS302DL_ACC_SENS_2G;
490 else
491 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
492 devp->accsensitivity[i] = devp->config->accsensitivity[i];
493 }
494 else if(devp->config->accfullscale == LIS302DL_ACC_FS_8G) {
495 devp->accfullscale = LIS302DL_ACC_8G;
496 if(devp->config->accsensitivity == NULL)
497 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
498 devp->accsensitivity[i] = LIS302DL_ACC_SENS_8G;
499 else
500 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
501 devp->accsensitivity[i] = devp->config->accsensitivity[i];
502 }
503 else {
504 osalDbgAssert(FALSE, "lis302dlStart(), accelerometer full scale issue");
505 }
506
507 /* Storing bias information according to user setting */
508 if(devp->config->accbias != NULL)
509 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
510 devp->accbias[i] = devp->config->accbias[i];
511 else
512 for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
513 devp->accbias[i] = LIS302DL_ACC_BIAS;
514
515 /* This is the Accelerometer transient recovery time */
516 osalThreadSleepMilliseconds(10);
517
518 devp->state = LIS302DL_READY;
519}
520
521/**
522 * @brief Deactivates the LIS302DL Complex Driver peripheral.
523 *
524 * @param[in] devp pointer to the @p LIS302DLDriver object
525 *
526 * @api
527 */
528void lis302dlStop(LIS302DLDriver *devp) {
529 uint8_t cr1;
530 osalDbgCheck(devp != NULL);
531
532 osalDbgAssert((devp->state == LIS302DL_STOP) ||
533 (devp->state == LIS302DL_READY),
534 "lis302dlStop(), invalid state");
535
536 if (devp->state == LIS302DL_READY) {
537#if LIS302DL_USE_SPI
538#if LIS302DL_SHARED_SPI
539 spiAcquireBus((devp)->config->spip);
540 spiStart((devp)->config->spip,
541 (devp)->config->spicfg);
542#endif /* LIS302DL_SHARED_SPI */
543 /* Disabling all axes and enabling power down mode.*/
544 cr1 = 0;
545 lis302dlSPIWriteRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1, 1, &cr1);
546 spiStop((devp)->config->spip);
547#if LIS302DL_SHARED_SPI
548 spiReleaseBus((devp)->config->spip);
549#endif /* LIS302DL_SHARED_SPI */
550#endif /* LIS302DL_USE_SPI */
551 }
552 devp->state = LIS302DL_STOP;
553}
554/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/lis302dl.h b/lib/chibios/os/ex/devices/ST/lis302dl.h
new file mode 100644
index 000000000..7a316b64d
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis302dl.h
@@ -0,0 +1,566 @@
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 lis302dl.h
23 * @brief LIS302DL MEMS interface module header.
24 *
25 * @addtogroup LIS302DL
26 * @ingroup EX_ST
27 * @{
28 */
29
30#ifndef _LIS302DL_H_
31#define _LIS302DL_H_
32
33#include "ex_accelerometer.h"
34
35/*===========================================================================*/
36/* Driver constants. */
37/*===========================================================================*/
38
39/**
40 * @name Version identification
41 * @{
42 */
43/**
44 * @brief LIS302DL driver version string.
45 */
46#define EX_LIS302DL_VERSION "1.1.1"
47
48/**
49 * @brief LIS302DL driver version major number.
50 */
51#define EX_LIS302DL_MAJOR 1
52
53/**
54 * @brief LIS302DL driver version minor number.
55 */
56#define EX_LIS302DL_MINOR 1
57
58/**
59 * @brief LIS302DL driver version patch number.
60 */
61#define EX_LIS302DL_PATCH 1
62/** @} */
63
64/**
65 * @brief LIS302DL accelerometer subsystem characteristics.
66 * @note Sensitivity is expressed as milli-G/LSB whereas
67 * 1 milli-G = 0.00980665 m/s^2.
68 * @note Bias is expressed as milli-G.
69 *
70 * @{
71 */
72#define LIS302DL_ACC_NUMBER_OF_AXES 3U
73
74#define LIS302DL_ACC_2G 2.0f
75#define LIS302DL_ACC_8G 8.0f
76
77#define LIS302DL_ACC_SENS_2G 18.0f
78#define LIS302DL_ACC_SENS_8G 72.0f
79
80#define LIS302DL_ACC_BIAS 0.0f
81/** @} */
82
83/**
84 * @name LIS302DL communication interfaces related bit masks
85 * @{
86 */
87#define LIS302DL_DI_MASK 0xFF
88#define LIS302DL_DI(n) (1 << n)
89#define LIS302DL_AD_MASK 0x3F
90#define LIS302DL_AD(n) (1 << n)
91#define LIS302DL_MS (1 << 6)
92#define LIS302DL_RW (1 << 7)
93/** @} */
94
95/**
96 * @name LIS302DL register addresses
97 * @{
98 */
99#define LIS302DL_AD_WHO_AM_I 0x0F
100#define LIS302DL_AD_CTRL_REG1 0x20
101#define LIS302DL_AD_CTRL_REG2 0x21
102#define LIS302DL_AD_CTRL_REG3 0x22
103#define LIS302DL_AD_HP_FILER_RESET 0x23
104#define LIS302DL_AD_STATUS_REG 0x27
105#define LIS302DL_AD_OUT_X 0x29
106#define LIS302DL_AD_OUT_Y 0x2B
107#define LIS302DL_AD_OUT_Z 0x2D
108#define LIS302DL_AD_FF_WU_CFG_1 0x30
109#define LIS302DL_AD_FF_WU_SRC_1 0x31
110#define LIS302DL_AD_FF_WU_THS_1 0x32
111#define LIS302DL_AD_FF_WU_DURATION_1 0x33
112#define LIS302DL_AD_FF_WU_CFG_2 0x34
113#define LIS302DL_AD_FF_WU_SRC_2 0x35
114#define LIS302DL_AD_FF_WU_THS_2 0x36
115#define LIS302DL_AD_FF_WU_DURATION_2 0x37
116#define LIS302DL_AD_CLICK_CFG 0x38
117#define LIS302DL_AD_CLICK_SRC 0x39
118#define LIS302DL_AD_CLICK_THSY_X 0x3B
119#define LIS302DL_AD_CLICK_THSZ 0x3C
120#define LIS302DL_AD_CLICK_TIME_LIMIT 0x3D
121#define LIS302DL_AD_CLICK_LATENCY 0x3E
122#define LIS302DL_AD_CLICK_WINDOW 0x3F
123/** @} */
124
125/**
126 * @name LIS302DL_CTRL_REG1 register bits definitions
127 * @{
128 */
129#define LIS302DL_CTRL_REG1_MASK 0xFF
130#define LIS302DL_CTRL_REG1_XEN (1 << 0)
131#define LIS302DL_CTRL_REG1_YEN (1 << 1)
132#define LIS302DL_CTRL_REG1_ZEN (1 << 2)
133#define LIS302DL_CTRL_REG1_STM (1 << 3)
134#define LIS302DL_CTRL_REG1_STP (1 << 4)
135#define LIS302DL_CTRL_REG1_FS_MASK 0x20
136#define LIS302DL_CTRL_REG1_FS (1 << 5)
137#define LIS302DL_CTRL_REG1_PD (1 << 6)
138#define LIS302DL_CTRL_REG1_DR (1 << 7)
139/** @} */
140
141/**
142 * @name LIS302DL_CTRL_REG2 register bits definitions
143 * @{
144 */
145#define LIS302DL_CTRL_REG2_MASK 0xDF
146#define LIS302DL_CTRL_REG2_HPCF1 (1 << 0)
147#define LIS302DL_CTRL_REG2_HPCF2 (1 << 1)
148#define LIS302DL_CTRL_REG2_HPFFWU1 (1 << 2)
149#define LIS302DL_CTRL_REG2_HPFFWU2 (1 << 3)
150#define LIS302DL_CTRL_REG2_FDS (1 << 4)
151#define LIS302DL_CTRL_REG2_BOOT (1 << 6)
152#define LIS302DL_CTRL_REG2_SIM (1 << 7)
153/** @} */
154
155/**
156 * @name LIS302DL_CTRL_REG3 register bits definitions
157 * @{
158 */
159#define LIS302DL_CTRL_REG3_MASK 0xFF
160#define LIS302DL_CTRL_REG3_I1CFG0 (1 << 0)
161#define LIS302DL_CTRL_REG3_I1CFG1 (1 << 1)
162#define LIS302DL_CTRL_REG3_I1CFG2 (1 << 2)
163#define LIS302DL_CTRL_REG3_I2CFG0 (1 << 3)
164#define LIS302DL_CTRL_REG3_I2CFG1 (1 << 4)
165#define LIS302DL_CTRL_REG3_I2CFG2 (1 << 5)
166#define LIS302DL_CTRL_REG3_PP_OD (1 << 6)
167#define LIS302DL_CTRL_REG3_IHL (1 << 7)
168/** @} */
169
170/*===========================================================================*/
171/* Driver pre-compile time settings. */
172/*===========================================================================*/
173
174/**
175 * @name Configuration options
176 * @{
177 */
178/**
179 * @brief LIS302DL SPI interface switch.
180 * @details If set to @p TRUE the support for SPI is included.
181 * @note The default is @p TRUE.
182 */
183#if !defined(LIS302DL_USE_SPI) || defined(__DOXYGEN__)
184#define LIS302DL_USE_SPI TRUE
185#endif
186
187/**
188 * @brief LIS302DL shared SPI switch.
189 * @details If set to @p TRUE the device acquires SPI bus ownership
190 * on each transaction.
191 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
192 */
193#if !defined(LIS302DL_SHARED_SPI) || defined(__DOXYGEN__)
194#define LIS302DL_SHARED_SPI FALSE
195#endif
196
197/**
198 * @brief LIS302DL I2C interface switch.
199 * @details If set to @p TRUE the support for I2C is included.
200 * @note The default is @p FALSE.
201 */
202#if !defined(LIS302DL_USE_I2C) || defined(__DOXYGEN__)
203#define LIS302DL_USE_I2C FALSE
204#endif
205
206/**
207 * @brief LIS302DL shared I2C switch.
208 * @details If set to @p TRUE the device acquires I2C bus ownership
209 * on each transaction.
210 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
211 */
212#if !defined(LIS302DL_SHARED_I2C) || defined(__DOXYGEN__)
213#define LIS302DL_SHARED_I2C FALSE
214#endif
215
216/**
217 * @brief LIS302DL advanced configurations switch.
218 * @details If set to @p TRUE more configurations are available.
219 * @note The default is @p FALSE.
220 */
221#if !defined(LIS302DL_USE_ADVANCED) || defined(__DOXYGEN__)
222#define LIS302DL_USE_ADVANCED FALSE
223#endif
224/** @} */
225
226/*===========================================================================*/
227/* Derived constants and error checks. */
228/*===========================================================================*/
229
230#if !(LIS302DL_USE_SPI ^ LIS302DL_USE_I2C)
231#error "LIS302DL_USE_SPI and LIS302DL_USE_I2C cannot be both true or both false"
232#endif
233
234#if LIS302DL_USE_SPI && !HAL_USE_SPI
235#error "LIS302DL_USE_SPI requires HAL_USE_SPI"
236#endif
237
238#if LIS302DL_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
239#error "LIS302DL_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
240#endif
241
242#if LIS302DL_USE_I2C && !HAL_USE_I2C
243#error "LIS302DL_USE_I2C requires HAL_USE_I2C"
244#endif
245
246#if LIS302DL_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
247#error "LIS302DL_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
248#endif
249
250/*
251 * CHTODO: Add support for LIS302DL over I2C.
252 */
253#if LIS302DL_USE_I2C
254#error "LIS302DL over I2C still not supported"
255#endif
256
257/*===========================================================================*/
258/* Driver data structures and types. */
259/*===========================================================================*/
260
261/**
262 * @name LIS302DL data structures and types
263 * @{
264 */
265/**
266 * @brief Structure representing a LIS302DL driver.
267 */
268typedef struct LIS302DLDriver LIS302DLDriver;
269
270/**
271 * @brief LIS302DL full scale.
272 */
273typedef enum {
274 LIS302DL_ACC_FS_2G = 0x00, /**< Full scale �2g. */
275 LIS302DL_ACC_FS_8G = 0x20 /**< Full scale �8g. */
276}lis302dl_acc_fs_t;
277
278/**
279 * @brief LIS302DL output data rate and bandwidth.
280 */
281typedef enum {
282 LIS302DL_ACC_ODR_100HZ = 0x00, /**< ODR 100 Hz. */
283 LIS302DL_ACC_ODR_400HZ = 0x80 /**< ODR 400 Hz. */
284}lis302dl_acc_odr_t;
285
286/**
287 * @brief LIS302DL high pass filtering.
288 */
289typedef enum {
290 LIS302DL_ACC_HP_DISABLED = 0x00, /**< HP bypassed. */
291 LIS302DL_ACC_HP_0 = 0x10, /**< HP cutoff 2Hz (ODR 100Hz) or 8Hz */
292 LIS302DL_ACC_HP_1 = 0x11, /**< HP cutoff 1Hz or 4Hz */
293 LIS302DL_ACC_HP_2 = 0x12, /**< HP cutoff 0.5Hz or 2Hz */
294 LIS302DL_ACC_HP_3 = 0x13 /**< HP cutoff 0.25Hz or 1Hz */
295}lis302dl_acc_hp_t;
296
297/**
298 * @brief Driver state machine possible states.
299 */
300typedef enum {
301 LIS302DL_UNINIT = 0, /**< Not initialized. */
302 LIS302DL_STOP = 1, /**< Stopped. */
303 LIS302DL_READY = 2, /**< Ready. */
304} lis302dl_state_t;
305
306/**
307 * @brief LIS302DL configuration structure.
308 */
309typedef struct {
310
311#if (LIS302DL_USE_SPI) || defined(__DOXYGEN__)
312 /**
313 * @brief SPI driver associated to this LIS302DL.
314 */
315 SPIDriver *spip;
316 /**
317 * @brief SPI configuration associated to this LIS302DL.
318 */
319 const SPIConfig *spicfg;
320#endif /* LIS302DL_USE_SPI */
321#if (LIS302DL_USE_I2C) || defined(__DOXYGEN__)
322 /**
323 * @brief I2C driver associated to this LIS302DL.
324 */
325 I2CDriver *i2cp;
326 /**
327 * @brief I2C configuration associated to this LIS302DL.
328 */
329 const I2CConfig *i2ccfg;
330#endif /* LIS302DL_USE_I2C */
331 /**
332 * @brief LIS302DL accelerometer subsystem initial sensitivity.
333 */
334 float *accsensitivity;
335 /**
336 * @brief LIS302DL accelerometer subsystem initial bias.
337 */
338 float *accbias;
339 /**
340 * @brief LIS302DL accelerometer subsystem initial full scale.
341 */
342 lis302dl_acc_fs_t accfullscale;
343 /**
344 * @brief LIS302DL output data rate selection.
345 */
346 lis302dl_acc_odr_t accoutputdatarate;
347#if LIS302DL_USE_ADVANCED || defined(__DOXYGEN__)
348 /**
349 * @brief LIS302DL high pass filtering.
350 */
351 lis302dl_acc_hp_t acchighpass;
352#endif
353} LIS302DLConfig;
354
355/**
356 * @brief @p LIS302DL specific methods.
357 */
358#define _lis302dl_methods_alone \
359 /* Change full scale value of LIS302DL .*/ \
360 msg_t (*set_full_scale)(LIS302DLDriver *devp, lis302dl_acc_fs_t fs);
361
362
363/**
364 * @brief @p LIS302DL specific methods with inherited ones.
365 */
366#define _lis302dl_methods \
367 _base_object_methods \
368 _lis302dl_methods_alone
369
370/**
371 * @extends BaseObjectVMT
372 *
373 * @brief @p LIS302DL accelerometer virtual methods table.
374 */
375struct LIS302DLVMT {
376 _lis302dl_methods
377};
378
379/**
380 * @brief @p LIS302DLDriver specific data.
381 */
382#define _lis302dl_data \
383 /* Driver state.*/ \
384 lis302dl_state_t state; \
385 /* Current configuration data.*/ \
386 const LIS302DLConfig *config; \
387 /* Accelerometer subsystem axes number.*/ \
388 size_t accaxes; \
389 /* Current sensitivity.*/ \
390 float accsensitivity[LIS302DL_ACC_NUMBER_OF_AXES]; \
391 /* Bias data.*/ \
392 int32_t accbias[LIS302DL_ACC_NUMBER_OF_AXES]; \
393 /* Current full scale value.*/ \
394 float accfullscale;
395
396/**
397 * @brief LIS302DL 3-axis accelerometer class.
398 */
399struct LIS302DLDriver {
400 /** @brief Virtual Methods Table.*/
401 const struct LIS302DLVMT *vmt;
402 /** @brief Base accelerometer interface.*/
403 BaseAccelerometer acc_if;
404 _lis302dl_data
405};
406/** @} */
407
408/*===========================================================================*/
409/* Driver macros. */
410/*===========================================================================*/
411
412/**
413 * @brief Return the number of axes of the BaseAccelerometer.
414 *
415 * @param[in] devp pointer to @p LIS302DLDriver.
416 *
417 * @return the number of axes.
418 *
419 * @api
420 */
421#define lis302dlAccelerometerGetAxesNumber(devp) \
422 accelerometerGetAxesNumber(&((devp)->acc_if))
423
424/**
425 * @brief Retrieves raw data from the BaseAccelerometer.
426 * @note This data is retrieved from MEMS register without any algebraical
427 * manipulation.
428 * @note The axes array must be at least the same size of the
429 * BaseAccelerometer axes number.
430 *
431 * @param[in] devp pointer to @p LIS302DLDriver.
432 * @param[out] axes a buffer which would be filled with raw data.
433 *
434 * @return The operation status.
435 * @retval MSG_OK if the function succeeded.
436 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
437 * be retrieved using @p i2cGetErrors().
438 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
439 *
440 * @api
441 */
442#define lis302dlAccelerometerReadRaw(devp, axes) \
443 accelerometerReadRaw(&((devp)->acc_if), axes)
444
445/**
446 * @brief Retrieves cooked data from the BaseAccelerometer.
447 * @note This data is manipulated according to the formula
448 * cooked = (raw * sensitivity) - bias.
449 * @note Final data is expressed as milli-G.
450 * @note The axes array must be at least the same size of the
451 * BaseAccelerometer axes number.
452 *
453 * @param[in] devp pointer to @p LIS302DLDriver.
454 * @param[out] axes a buffer which would be filled with cooked data.
455 *
456 * @return The operation status.
457 * @retval MSG_OK if the function succeeded.
458 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
459 * be retrieved using @p i2cGetErrors().
460 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
461 *
462 * @api
463 */
464#define lis302dlAccelerometerReadCooked(devp, axes) \
465 accelerometerReadCooked(&((devp)->acc_if), axes)
466
467/**
468 * @brief Set bias values for the BaseAccelerometer.
469 * @note Bias must be expressed as milli-G.
470 * @note The bias buffer must be at least the same size of the
471 * BaseAccelerometer axes number.
472 *
473 * @param[in] devp pointer to @p LIS302DLDriver.
474 * @param[in] bp a buffer which contains biases.
475 *
476 * @return The operation status.
477 * @retval MSG_OK if the function succeeded.
478 *
479 * @api
480 */
481#define lis302dlAccelerometerSetBias(devp, bp) \
482 accelerometerSetBias(&((devp)->acc_if), bp)
483
484/**
485 * @brief Reset bias values for the BaseAccelerometer.
486 * @note Default biases value are obtained from device datasheet when
487 * available otherwise they are considered zero.
488 *
489 * @param[in] devp pointer to @p LIS302DLDriver.
490 *
491 * @return The operation status.
492 * @retval MSG_OK if the function succeeded.
493 *
494 * @api
495 */
496#define lis302dlAccelerometerResetBias(devp) \
497 accelerometerResetBias(&((devp)->acc_if))
498
499/**
500 * @brief Set sensitivity values for the BaseAccelerometer.
501 * @note Sensitivity must be expressed as milli-G/LSB.
502 * @note The sensitivity buffer must be at least the same size of the
503 * BaseAccelerometer axes number.
504 *
505 * @param[in] devp pointer to @p LIS302DLDriver.
506 * @param[in] sp a buffer which contains sensitivities.
507 *
508 * @return The operation status.
509 * @retval MSG_OK if the function succeeded.
510 *
511 * @api
512 */
513#define lis302dlAccelerometerSetSensitivity(devp, sp) \
514 accelerometerSetSensitivity(&((devp)->acc_if), sp)
515
516/**
517 * @brief Reset sensitivity values for the BaseAccelerometer.
518 * @note Default sensitivities value are obtained from device datasheet.
519 *
520 * @param[in] devp pointer to @p LIS302DLDriver.
521 *
522 * @return The operation status.
523 * @retval MSG_OK if the function succeeded.
524 * @retval MSG_RESET otherwise.
525 *
526 * @api
527 */
528#define lis302dlAccelerometerResetSensitivity(devp) \
529 accelerometerResetSensitivity(&((devp)->acc_if))
530
531/**
532 * @brief Changes the LIS302DLDriver accelerometer fullscale value.
533 * @note This function also rescale sensitivities and biases based on
534 * previous and next fullscale value.
535 * @note A recalibration is highly suggested after calling this function.
536 *
537 * @param[in] devp pointer to @p LIS302DLDriver.
538 * @param[in] fs new fullscale value.
539 *
540 * @return The operation status.
541 * @retval MSG_OK if the function succeeded.
542 * @retval MSG_RESET otherwise.
543 *
544 * @api
545 */
546#define lis302dlAccelerometerSetFullScale(devp, fs) \
547 (devp)->vmt->acc_set_full_scale(devp, fs)
548
549/*===========================================================================*/
550/* External declarations. */
551/*===========================================================================*/
552
553#ifdef __cplusplus
554extern "C" {
555#endif
556 void lis302dlObjectInit(LIS302DLDriver *devp);
557 void lis302dlStart(LIS302DLDriver *devp, const LIS302DLConfig *config);
558 void lis302dlStop(LIS302DLDriver *devp);
559#ifdef __cplusplus
560}
561#endif
562
563#endif /* _LIS302DL_H_ */
564
565/** @} */
566
diff --git a/lib/chibios/os/ex/devices/ST/lis302dl.mk b/lib/chibios/os/ex/devices/ST/lis302dl.mk
new file mode 100644
index 000000000..5f5ccf4f6
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis302dl.mk
@@ -0,0 +1,10 @@
1# List of all the LIS302DL device files.
2LIS302DLSRC := $(CHIBIOS)/os/ex/devices/ST/lis302dl.c
3
4# Required include directories
5LIS302DLINC := $(CHIBIOS)/os/ex/include \
6 $(CHIBIOS)/os/ex/devices/ST
7
8# Shared variables
9ALLCSRC += $(LIS302DLSRC)
10ALLINC += $(LIS302DLINC) \ No newline at end of file
diff --git a/lib/chibios/os/ex/devices/ST/lis3dsh.c b/lib/chibios/os/ex/devices/ST/lis3dsh.c
new file mode 100644
index 000000000..f8f34788e
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis3dsh.c
@@ -0,0 +1,641 @@
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 lis3dsh.c
23 * @brief LIS3DSH MEMS interface module code.
24 *
25 * @addtogroup LIS3DSH
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "lis3dsh.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 (LIS3DSH_USE_SPI) || defined(__DOXYGEN__)
50/**
51 * @brief Reads a generic register value using SPI.
52 * @pre The SPI interface must be initialized and the driver started.
53 * @note Multiple write/read requires proper settings in CTRL_REG6.
54 *
55 * @param[in] spip pointer to the SPI interface
56 * @param[in] reg starting register address
57 * @param[in] n number of adjacent registers to write
58 * @param[in] b pointer to a buffer.
59 */
60static void lis3dshSPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n,
61 uint8_t* b) {
62 uint8_t cmd;
63 cmd = reg | LIS3DSH_RW;
64 spiSelect(spip);
65 spiSend(spip, 1, &cmd);
66 spiReceive(spip, n, b);
67 spiUnselect(spip);
68}
69
70/**
71 * @brief Writes a value into a generic register using SPI.
72 * @pre The SPI interface must be initialized and the driver started.
73 * @note Multiple write/read requires proper settings in CTRL_REG6.
74 *
75 * @param[in] spip pointer to the SPI interface
76 * @param[in] reg starting register address
77 * @param[in] n number of adjacent registers to write
78 * @param[in] b pointer to a buffer of values.
79 */
80static void lis3dshSPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n,
81 uint8_t* b) {
82 uint8_t cmd;
83 cmd = reg;
84 spiSelect(spip);
85 spiSend(spip, 1, &cmd);
86 spiSend(spip, n, b);
87 spiUnselect(spip);
88}
89#endif /* LIS3DSH_USE_SPI */
90
91/**
92 * @brief Return the number of axes of the BaseAccelerometer.
93 *
94 * @param[in] ip pointer to @p BaseAccelerometer interface.
95 *
96 * @return the number of axes.
97 */
98static size_t acc_get_axes_number(void *ip) {
99 (void)ip;
100
101 return LIS3DSH_ACC_NUMBER_OF_AXES;
102}
103
104/**
105 * @brief Retrieves raw data from the BaseAccelerometer.
106 * @note This data is retrieved from MEMS register without any algebraical
107 * manipulation.
108 * @note The axes array must be at least the same size of the
109 * BaseAccelerometer axes number.
110 *
111 * @param[in] ip pointer to @p BaseAccelerometer interface.
112 * @param[out] axes a buffer which would be filled with raw data.
113 *
114 * @return The operation status.
115 * @retval MSG_OK if the function succeeded.
116 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
117 * be retrieved using @p i2cGetErrors().
118 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
119 */
120static msg_t acc_read_raw(void *ip, int32_t axes[]) {
121 LIS3DSHDriver* devp;
122 uint8_t buff [LIS3DSH_ACC_NUMBER_OF_AXES * 2], i;
123 int16_t tmp;
124 msg_t msg = MSG_OK;
125
126 osalDbgCheck((ip != NULL) && (axes != NULL));
127
128 /* Getting parent instance pointer.*/
129 devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
130
131 osalDbgAssert((devp->state == LIS3DSH_READY),
132 "acc_read_raw(), invalid state");
133
134#if LIS3DSH_USE_SPI
135#if LIS3DSH_SHARED_SPI
136 osalDbgAssert((devp->config->spip->state == SPI_READY),
137 "acc_read_raw(), channel not ready");
138
139 spiAcquireBus(devp->config->spip);
140 spiStart(devp->config->spip,
141 devp->config->spicfg);
142#endif /* LIS3DSH_SHARED_SPI */
143
144 lis3dshSPIReadRegister(devp->config->spip, LIS3DSH_AD_OUT_X_L,
145 LIS3DSH_ACC_NUMBER_OF_AXES * 2, buff);
146
147#if LIS3DSH_SHARED_SPI
148 spiReleaseBus(devp->config->spip);
149#endif /* LIS3DSH_SHARED_SPI */
150#endif /* LIS3DSH_USE_SPI */
151
152 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
153 tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
154 axes[i] = (int32_t)tmp;
155 }
156 return msg;
157}
158
159/**
160 * @brief Retrieves cooked data from the BaseAccelerometer.
161 * @note This data is manipulated according to the formula
162 * cooked = (raw * sensitivity) - bias.
163 * @note Final data is expressed as milli-G.
164 * @note The axes array must be at least the same size of the
165 * BaseAccelerometer axes number.
166 *
167 * @param[in] ip pointer to @p BaseAccelerometer interface.
168 * @param[out] axes a buffer which would be filled with cooked data.
169 *
170 * @return The operation status.
171 * @retval MSG_OK if the function succeeded.
172 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
173 * be retrieved using @p i2cGetErrors().
174 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
175 */
176static msg_t acc_read_cooked(void *ip, float axes[]) {
177 LIS3DSHDriver* devp;
178 uint32_t i;
179 int32_t raw[LIS3DSH_ACC_NUMBER_OF_AXES];
180 msg_t msg;
181
182 osalDbgCheck((ip != NULL) && (axes != NULL));
183
184 /* Getting parent instance pointer.*/
185 devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
186
187 osalDbgAssert((devp->state == LIS3DSH_READY),
188 "acc_read_cooked(), invalid state");
189
190 msg = acc_read_raw(ip, raw);
191 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
192 axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
193 }
194 return msg;
195}
196
197/**
198 * @brief Set bias values for the BaseAccelerometer.
199 * @note Bias must be expressed as milli-G.
200 * @note The bias buffer must be at least the same size of the
201 * BaseAccelerometer axes number.
202 *
203 * @param[in] ip pointer to @p BaseAccelerometer interface.
204 * @param[in] bp a buffer which contains biases.
205 *
206 * @return The operation status.
207 * @retval MSG_OK if the function succeeded.
208 */
209static msg_t acc_set_bias(void *ip, float *bp) {
210 LIS3DSHDriver* devp;
211 uint32_t i;
212 msg_t msg = MSG_OK;
213
214 osalDbgCheck((ip != NULL) && (bp != NULL));
215
216 /* Getting parent instance pointer.*/
217 devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
218
219 osalDbgAssert((devp->state == LIS3DSH_READY),
220 "acc_set_bias(), invalid state");
221
222 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
223 devp->accbias[i] = bp[i];
224 }
225 return msg;
226}
227
228/**
229 * @brief Reset bias values for the BaseAccelerometer.
230 * @note Default biases value are obtained from device datasheet when
231 * available otherwise they are considered zero.
232 *
233 * @param[in] ip pointer to @p BaseAccelerometer interface.
234 *
235 * @return The operation status.
236 * @retval MSG_OK if the function succeeded.
237 */
238static msg_t acc_reset_bias(void *ip) {
239 LIS3DSHDriver* devp;
240 uint32_t i;
241 msg_t msg = MSG_OK;
242
243 osalDbgCheck(ip != NULL);
244
245 /* Getting parent instance pointer.*/
246 devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
247
248 osalDbgAssert((devp->state == LIS3DSH_READY),
249 "acc_reset_bias(), invalid state");
250
251 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
252 devp->accbias[i] = LIS3DSH_ACC_BIAS;
253 return msg;
254}
255
256/**
257 * @brief Set sensitivity values for the BaseAccelerometer.
258 * @note Sensitivity must be expressed as milli-G/LSB.
259 * @note The sensitivity buffer must be at least the same size of the
260 * BaseAccelerometer axes number.
261 *
262 * @param[in] ip pointer to @p BaseAccelerometer interface.
263 * @param[in] sp a buffer which contains sensitivities.
264 *
265 * @return The operation status.
266 * @retval MSG_OK if the function succeeded.
267 */
268static msg_t acc_set_sensivity(void *ip, float *sp) {
269 LIS3DSHDriver* devp;
270 uint32_t i;
271 msg_t msg = MSG_OK;
272
273 /* Getting parent instance pointer.*/
274 devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
275
276 osalDbgCheck((ip != NULL) && (sp != NULL));
277
278 osalDbgAssert((devp->state == LIS3DSH_READY),
279 "acc_set_sensivity(), invalid state");
280
281 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
282 devp->accsensitivity[i] = sp[i];
283 }
284 return msg;
285}
286
287/**
288 * @brief Reset sensitivity values for the BaseAccelerometer.
289 * @note Default sensitivities value are obtained from device datasheet.
290 *
291 * @param[in] ip pointer to @p BaseAccelerometer interface.
292 *
293 * @return The operation status.
294 * @retval MSG_OK if the function succeeded.
295 * @retval MSG_RESET otherwise.
296 */
297static msg_t acc_reset_sensivity(void *ip) {
298 LIS3DSHDriver* devp;
299 uint32_t i;
300 msg_t msg = MSG_OK;
301
302 osalDbgCheck(ip != NULL);
303
304 /* Getting parent instance pointer.*/
305 devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
306
307 osalDbgAssert((devp->state == LIS3DSH_READY),
308 "acc_reset_sensivity(), invalid state");
309
310 if(devp->config->accfullscale == LIS3DSH_ACC_FS_2G)
311 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
312 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_2G;
313 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_4G)
314 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
315 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_4G;
316 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_6G)
317 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
318 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_6G;
319 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_8G)
320 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
321 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_8G;
322 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_16G)
323 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
324 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_16G;
325 else {
326 osalDbgAssert(FALSE,
327 "acc_reset_sensivity(), accelerometer full scale issue");
328 return MSG_RESET;
329 }
330 return msg;
331}
332
333/**
334 * @brief Changes the LIS3DSHDriver accelerometer fullscale value.
335 * @note This function also rescale sensitivities and biases based on
336 * previous and next fullscale value.
337 * @note A recalibration is highly suggested after calling this function.
338 *
339 * @param[in] devp pointer to @p LIS3DSHDriver interface.
340 * @param[in] fs new fullscale value.
341 *
342 * @return The operation status.
343 * @retval MSG_OK if the function succeeded.
344 * @retval MSG_RESET otherwise.
345 */
346static msg_t acc_set_full_scale(LIS3DSHDriver *devp, lis3dsh_acc_fs_t fs) {
347 float newfs, scale;
348 uint8_t i, cr;
349 msg_t msg;
350
351 osalDbgCheck(devp != NULL);
352
353 osalDbgAssert((devp->state == LIS3DSH_READY),
354 "acc_set_full_scale(), invalid state");
355 osalDbgAssert((devp->config->spip->state == SPI_READY),
356 "acc_set_full_scale(), channel not ready");
357
358 /* Computing new fullscale value.*/
359 if(fs == LIS3DSH_ACC_FS_2G) {
360 newfs = LIS3DSH_ACC_2G;
361 }
362 else if(fs == LIS3DSH_ACC_FS_4G) {
363 newfs = LIS3DSH_ACC_4G;
364 }
365 else if(fs == LIS3DSH_ACC_FS_6G) {
366 newfs = LIS3DSH_ACC_6G;
367 }
368 else if(fs == LIS3DSH_ACC_FS_8G) {
369 newfs = LIS3DSH_ACC_8G;
370 }
371 else if(fs == LIS3DSH_ACC_FS_16G) {
372 newfs = LIS3DSH_ACC_16G;
373 }
374 else {
375 msg = MSG_RESET;
376 return msg;
377 }
378
379 if(newfs != devp->accfullscale) {
380 /* Computing scale value.*/
381 scale = newfs / devp->accfullscale;
382 devp->accfullscale = newfs;
383
384#if LIS3DSH_USE_SPI
385#if LIS3DSH_SHARED_SPI
386 spiAcquireBus(devp->config->spip);
387 spiStart(devp->config->spip,
388 devp->config->spicfg);
389#endif /* LIS3DSH_SHARED_SPI */
390
391 /* Getting data from register.*/
392 lis3dshSPIReadRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG5, 1, &cr);
393
394#if LIS3DSH_SHARED_SPI
395 spiReleaseBus(devp->config->spip);
396#endif /* LIS3DSH_SHARED_SPI */
397#endif /* LIS3DSH_USE_SPI */
398
399 cr &= ~(LIS3DSH_CTRL_REG5_FS_MASK);
400 cr |= fs;
401
402#if LIS3DSH_USE_SPI
403#if LIS3DSH_SHARED_SPI
404 spiAcquireBus(devp->config->spip);
405 spiStart(devp->config->spip,
406 devp->config->spicfg);
407#endif /* LIS3DSH_SHARED_SPI */
408
409 /* Getting data from register.*/
410 lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG5, 1, &cr);
411
412#if LIS3DSH_SHARED_SPI
413 spiReleaseBus(devp->config->spip);
414#endif /* LIS3DSH_SHARED_SPI */
415#endif /* LIS3DSH_USE_SPI */
416
417 /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
418 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
419 devp->accsensitivity[i] *= scale;
420 devp->accbias[i] *= scale;
421 }
422 }
423 return msg;
424}
425
426static const struct LIS3DSHVMT vmt_device = {
427 (size_t)0,
428 acc_set_full_scale
429};
430
431static const struct BaseAccelerometerVMT vmt_accelerometer = {
432 sizeof(struct LIS3DSHVMT*),
433 acc_get_axes_number, acc_read_raw, acc_read_cooked,
434 acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
435};
436
437/*===========================================================================*/
438/* Driver exported functions. */
439/*===========================================================================*/
440
441/**
442 * @brief Initializes an instance.
443 *
444 * @param[out] devp pointer to the @p LIS3DSHDriver object
445 *
446 * @init
447 */
448void lis3dshObjectInit(LIS3DSHDriver *devp) {
449 devp->vmt = &vmt_device;
450 devp->acc_if.vmt = &vmt_accelerometer;
451
452 devp->config = NULL;
453
454 devp->accaxes = LIS3DSH_ACC_NUMBER_OF_AXES;
455
456 devp->state = LIS3DSH_STOP;
457}
458
459/**
460 * @brief Configures and activates LIS3DSH Complex Driver peripheral.
461 *
462 * @param[in] devp pointer to the @p LIS3DSHDriver object
463 * @param[in] config pointer to the @p LIS3DSHConfig object
464 *
465 * @api
466 */
467void lis3dshStart(LIS3DSHDriver *devp, const LIS3DSHConfig *config) {
468 uint32_t i;
469 uint8_t cr;
470 osalDbgCheck((devp != NULL) && (config != NULL));
471
472 osalDbgAssert((devp->state == LIS3DSH_STOP) ||
473 (devp->state == LIS3DSH_READY),
474 "lis3dshStart(), invalid state");
475
476 devp->config = config;
477
478 /* Control register 4 configuration block.*/
479 {
480 cr = LIS3DSH_CTRL_REG4_XEN | LIS3DSH_CTRL_REG4_YEN | LIS3DSH_CTRL_REG4_ZEN |
481 devp->config->accoutputdatarate;
482#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
483 cr |= devp->config->accblockdataupdate;
484#endif
485 }
486
487#if LIS3DSH_USE_SPI
488#if LIS3DSH_SHARED_SPI
489 spiAcquireBus(devp->config->spip);
490#endif /* LIS3DSH_SHARED_SPI */
491 spiStart(devp->config->spip, devp->config->spicfg);
492
493 lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG4, 1, &cr);
494
495#if LIS3DSH_SHARED_SPI
496 spiReleaseBus(devp->config->spip);
497#endif /* LIS3DSH_SHARED_SPI */
498#endif /* LIS3DSH_USE_SPI */
499
500 /* Control register 5 configuration block.*/
501 {
502 cr = devp->config->accfullscale;
503#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
504 cr |= devp->config->accantialiasing;
505#endif
506 }
507
508#if LIS3DSH_USE_SPI
509#if LIS3DSH_SHARED_SPI
510 spiAcquireBus(devp->config->spip);
511 spiStart(devp->config->spip, devp->config->spicfg);
512#endif /* LIS3DSH_SHARED_SPI */
513
514 lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG5, 1, &cr);
515
516#if LIS3DSH_SHARED_SPI
517 spiReleaseBus(devp->config->spip);
518#endif /* LIS3DSH_SHARED_SPI */
519#endif /* LIS3DSH_USE_SPI */
520
521 /* Control register 6 configuration block.*/
522 {
523 cr = LIS3DSH_CTRL_REG6_ADD_INC;
524#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
525 cr |= devp->config->accblockdataupdate;
526#endif
527 }
528
529#if LIS3DSH_USE_SPI
530#if LIS3DSH_SHARED_SPI
531 spiAcquireBus(devp->config->spip);
532 spiStart(devp->config->spip, devp->config->spicfg);
533#endif /* LIS3DSH_SHARED_SPI */
534
535 lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG6, 1, &cr);
536
537#if LIS3DSH_SHARED_SPI
538 spiReleaseBus(devp->config->spip);
539#endif /* LIS3DSH_SHARED_SPI */
540#endif /* LIS3DSH_USE_SPI */
541
542 /* Storing sensitivity information according to user setting */
543 if(devp->config->accfullscale == LIS3DSH_ACC_FS_2G) {
544 devp->accfullscale = LIS3DSH_ACC_2G;
545 if(devp->config->accsensitivity == NULL)
546 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
547 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_2G;
548 else
549 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
550 devp->accsensitivity[i] = devp->config->accsensitivity[i];
551 }
552 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_4G) {
553 devp->accfullscale = LIS3DSH_ACC_4G;
554 if(devp->config->accsensitivity == NULL)
555 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
556 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_4G;
557 else
558 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
559 devp->accsensitivity[i] = devp->config->accsensitivity[i];
560 }
561 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_6G) {
562 devp->accfullscale = LIS3DSH_ACC_6G;
563 if(devp->config->accsensitivity == NULL)
564 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
565 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_6G;
566 else
567 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
568 devp->accsensitivity[i] = devp->config->accsensitivity[i];
569 }
570 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_8G) {
571 devp->accfullscale = LIS3DSH_ACC_8G;
572 if(devp->config->accsensitivity == NULL)
573 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
574 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_8G;
575 else
576 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
577 devp->accsensitivity[i] = devp->config->accsensitivity[i];
578 }
579 else if(devp->config->accfullscale == LIS3DSH_ACC_FS_16G) {
580 devp->accfullscale = LIS3DSH_ACC_16G;
581 if(devp->config->accsensitivity == NULL)
582 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
583 devp->accsensitivity[i] = LIS3DSH_ACC_SENS_16G;
584 else
585 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
586 devp->accsensitivity[i] = devp->config->accsensitivity[i];
587 }
588 else {
589 osalDbgAssert(FALSE, "lis3dshStart(), accelerometer full scale issue");
590 }
591
592 /* Storing bias information according to user setting */
593 if(devp->config->accbias != NULL)
594 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
595 devp->accbias[i] = devp->config->accbias[i];
596 else
597 for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
598 devp->accbias[i] = LIS3DSH_ACC_BIAS;
599
600 /* This is the Accelerometer transient recovery time */
601 osalThreadSleepMilliseconds(10);
602
603 devp->state = LIS3DSH_READY;
604}
605
606/**
607 * @brief Deactivates the LIS3DSH Complex Driver peripheral.
608 *
609 * @param[in] devp pointer to the @p LIS3DSHDriver object
610 *
611 * @api
612 */
613void lis3dshStop(LIS3DSHDriver *devp) {
614 uint8_t cr4;
615 osalDbgCheck(devp != NULL);
616
617 osalDbgAssert((devp->state == LIS3DSH_STOP) ||
618 (devp->state == LIS3DSH_READY),
619 "lis3dshStop(), invalid state");
620
621 if (devp->state == LIS3DSH_READY) {
622#if (LIS3DSH_USE_SPI)
623#if LIS3DSH_SHARED_SPI
624 spiAcquireBus(devp->config->spip);
625 spiStart(devp->config->spip,
626 devp->config->spicfg);
627#endif /* LIS3DSH_SHARED_SPI */
628 /* Disabling all axes and enabling power down mode.*/
629 cr4 = 0;
630 lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG4,
631 1, &cr4);
632
633 spiStop(devp->config->spip);
634#if LIS3DSH_SHARED_SPI
635 spiReleaseBus(devp->config->spip);
636#endif /* LIS3DSH_SHARED_SPI */
637#endif /* LIS3DSH_USE_SPI */
638 }
639 devp->state = LIS3DSH_STOP;
640}
641/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/lis3dsh.h b/lib/chibios/os/ex/devices/ST/lis3dsh.h
new file mode 100644
index 000000000..6f569091d
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis3dsh.h
@@ -0,0 +1,708 @@
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 lis3dsh.h
23 * @brief LIS3DSH MEMS interface module header.
24 *
25 * @addtogroup LIS3DSH
26 * @ingroup EX_ST
27 * @{
28 */
29
30#ifndef _LIS3DSH_H_
31#define _LIS3DSH_H_
32
33#include "ex_accelerometer.h"
34
35/*===========================================================================*/
36/* Driver constants. */
37/*===========================================================================*/
38
39/**
40 * @name Version identification
41 * @{
42 */
43/**
44 * @brief LIS3DSH driver version string.
45 */
46#define EX_LIS3DSH_VERSION "1.1.2"
47
48/**
49 * @brief LIS3DSH driver version major number.
50 */
51#define EX_LIS3DSH_MAJOR 1
52
53/**
54 * @brief LIS3DSH driver version minor number.
55 */
56#define EX_LIS3DSH_MINOR 1
57
58/**
59 * @brief LIS3DSH driver version patch number.
60 */
61#define EX_LIS3DSH_PATCH 2
62/** @} */
63
64/**
65 * @brief LIS3DSH accelerometer subsystem characteristics.
66 * @note Sensitivity is expressed as milli-G/LSB whereas
67 * 1 milli-G = 0.00980665 m/s^2.
68 * @note Bias is expressed as milli-G.
69 *
70 * @{
71 */
72#define LIS3DSH_ACC_NUMBER_OF_AXES 3U
73
74#define LIS3DSH_ACC_2G 2.0f
75#define LIS3DSH_ACC_4G 4.0f
76#define LIS3DSH_ACC_6G 6.0f
77#define LIS3DSH_ACC_8G 8.0f
78#define LIS3DSH_ACC_16G 16.0f
79
80#define LIS3DSH_ACC_SENS_2G 0.06f
81#define LIS3DSH_ACC_SENS_4G 0.12f
82#define LIS3DSH_ACC_SENS_6G 0.18f
83#define LIS3DSH_ACC_SENS_8G 0.24f
84#define LIS3DSH_ACC_SENS_16G 0.73f
85
86#define LIS3DSH_ACC_BIAS 0.0f
87/** @} */
88
89/**
90 * @name LIS3DSH communication interfaces related bit masks
91 * @{
92 */
93#define LIS3DSH_DI_MASK 0xFF
94#define LIS3DSH_DI(n) (1 << n)
95#define LIS3DSH_AD_MASK 0x3F
96#define LIS3DSH_AD(n) (1 << n)
97#define LIS3DSH_MS (1 << 6)
98#define LIS3DSH_RW (1 << 7)
99/** @} */
100
101/**
102 * @name LIS3DSH register addresses
103 * @{
104 */
105#define LIS3DSH_AD_OUT_T 0x0C
106#define LIS3DSH_AD_INFO1 0x0D
107#define LIS3DSH_AD_INFO2 0x0E
108#define LIS3DSH_AD_WHO_AM_I 0x0F
109#define LIS3DSH_AD_OFF_X 0x10
110#define LIS3DSH_AD_OFF_Y 0x11
111#define LIS3DSH_AD_OFF_Z 0x12
112#define LIS3DSH_AD_CS_X 0x13
113#define LIS3DSH_AD_CS_Y 0x14
114#define LIS3DSH_AD_CS_Z 0x15
115#define LIS3DSH_AD_LC_L 0x16
116#define LIS3DSH_AD_LC_H 0x17
117#define LIS3DSH_AD_STAT 0x18
118#define LIS3DSH_AD_PEAK1 0x19
119#define LIS3DSH_AD_PEAK2 0x1A
120#define LIS3DSH_AD_VFC_1 0x1B
121#define LIS3DSH_AD_VFC_2 0x1C
122#define LIS3DSH_AD_VFC_3 0x1D
123#define LIS3DSH_AD_VFC_4 0x1E
124#define LIS3DSH_AD_THRS3 0x1F
125#define LIS3DSH_AD_CTRL_REG4 0x20
126#define LIS3DSH_AD_CTRL_REG1 0x21
127#define LIS3DSH_AD_CTRL_REG2 0x22
128#define LIS3DSH_AD_CTRL_REG3 0x23
129#define LIS3DSH_AD_CTRL_REG5 0x24
130#define LIS3DSH_AD_CTRL_REG6 0x25
131#define LIS3DSH_AD_STATUS 0x27
132#define LIS3DSH_AD_OUT_X_L 0x28
133#define LIS3DSH_AD_OUT_X_H 0x29
134#define LIS3DSH_AD_OUT_Y_L 0x2A
135#define LIS3DSH_AD_OUT_Y_H 0x2B
136#define LIS3DSH_AD_OUT_Z_L 0x2C
137#define LIS3DSH_AD_OUT_Z_H 0x2D
138#define LIS3DSH_AD_FIFO_CTRL 0x2E
139#define LIS3DSH_AD_FIFO_SRC 0x2F
140#define LIS3DSH_AD_ST1_0 0x40
141#define LIS3DSH_AD_ST1_1 0x41
142#define LIS3DSH_AD_ST1_2 0x42
143#define LIS3DSH_AD_ST1_3 0x43
144#define LIS3DSH_AD_ST1_4 0x44
145#define LIS3DSH_AD_ST1_5 0x45
146#define LIS3DSH_AD_ST1_6 0x46
147#define LIS3DSH_AD_ST1_7 0x47
148#define LIS3DSH_AD_ST1_8 0x48
149#define LIS3DSH_AD_ST1_9 0x49
150#define LIS3DSH_AD_ST1_A 0x4A
151#define LIS3DSH_AD_ST1_B 0x4B
152#define LIS3DSH_AD_ST1_C 0x4C
153#define LIS3DSH_AD_ST1_D 0x4D
154#define LIS3DSH_AD_ST1_E 0x4E
155#define LIS3DSH_AD_ST1_F 0x4F
156#define LIS3DSH_AD_TIM4_1 0x50
157#define LIS3DSH_AD_TIM3_1 0x51
158#define LIS3DSH_AD_TIM2_1_L 0x52
159#define LIS3DSH_AD_TIM2_1_H 0x53
160#define LIS3DSH_AD_TIM1_1_L 0x54
161#define LIS3DSH_AD_TIM1_1_H 0x55
162#define LIS3DSH_AD_THRS2_1 0x56
163#define LIS3DSH_AD_THRS1_1 0x57
164#define LIS3DSH_AD_MASK1_B 0x59
165#define LIS3DSH_AD_MASK1_A 0x5A
166#define LIS3DSH_AD_SETT1 0x5B
167#define LIS3DSH_AD_PR1 0x5C
168#define LIS3DSH_AD_TC1_L 0x5D
169#define LIS3DSH_AD_TC1_H 0x5E
170#define LIS3DSH_AD_OUTS1 0x5F
171#define LIS3DSH_AD_ST2_0 0x60
172#define LIS3DSH_AD_ST2_1 0x61
173#define LIS3DSH_AD_ST2_2 0x62
174#define LIS3DSH_AD_ST2_3 0x63
175#define LIS3DSH_AD_ST2_4 0x64
176#define LIS3DSH_AD_ST2_5 0x65
177#define LIS3DSH_AD_ST2_6 0x66
178#define LIS3DSH_AD_ST2_7 0x67
179#define LIS3DSH_AD_ST2_8 0x68
180#define LIS3DSH_AD_ST2_9 0x69
181#define LIS3DSH_AD_ST2_A 0x6A
182#define LIS3DSH_AD_ST2_B 0x6B
183#define LIS3DSH_AD_ST2_C 0x6C
184#define LIS3DSH_AD_ST2_D 0x6D
185#define LIS3DSH_AD_ST2_E 0x6E
186#define LIS3DSH_AD_ST2_F 0x6F
187#define LIS3DSH_AD_TIM4_2 0x70
188#define LIS3DSH_AD_TIM3_2 0x71
189#define LIS3DSH_AD_TIM2_2_L 0x72
190#define LIS3DSH_AD_TIM2_2_H 0x73
191#define LIS3DSH_AD_TIM1_2_L 0x74
192#define LIS3DSH_AD_TIM1_2_H 0x75
193#define LIS3DSH_AD_THRS2_2 0x76
194#define LIS3DSH_AD_THRS1_2 0x77
195#define LIS3DSH_AD_DES2 0x78
196#define LIS3DSH_AD_MASK2_B 0x79
197#define LIS3DSH_AD_MASK2_A 0x7A
198#define LIS3DSH_AD_SETT2 0x7B
199#define LIS3DSH_AD_PR2 0x7C
200#define LIS3DSH_AD_TC2_L 0x7D
201#define LIS3DSH_AD_TC2_H 0x7E
202#define LIS3DSH_AD_OUTS2 0x7F
203/** @} */
204
205/**
206 * @name LIS3DSH_CTRL_REG1 register bits definitions
207 * @{
208 */
209#define LIS3DSH_CTRL_REG1_MASK 0xE9
210#define LIS3DSH_CTRL_REG1_SM1_EN (1 << 0)
211#define LIS3DSH_CTRL_REG1_SM1_PIN (1 << 3)
212#define LIS3DSH_CTRL_REG1_HYST0_1 (1 << 5)
213#define LIS3DSH_CTRL_REG1_HYST1_1 (1 << 6)
214#define LIS3DSH_CTRL_REG1_HYST2_1 (1 << 7)
215/** @} */
216
217/**
218 * @name LIS3DSH_CTRL_REG2 register bits definitions
219 * @{
220 */
221#define LIS3DSH_CTRL_REG2_MASK 0xE9
222#define LIS3DSH_CTRL_REG2_SM2_EN (1 << 0)
223#define LIS3DSH_CTRL_REG2_SM2_PIN (1 << 3)
224#define LIS3DSH_CTRL_REG2_HYST0_2 (1 << 5)
225#define LIS3DSH_CTRL_REG2_HYST1_2 (1 << 6)
226#define LIS3DSH_CTRL_REG2_HYST2_2 (1 << 7)
227/** @} */
228
229/**
230 * @name LIS3DSH_CTRL_REG3 register bits definitions
231 * @{
232 */
233#define LIS3DSH_CTRL_REG3_MASK 0xFF
234#define LIS3DSH_CTRL_REG3_STRT (1 << 0)
235#define LIS3DSH_CTRL_REG3_VFILT (1 << 2)
236#define LIS3DSH_CTRL_REG3_INT1_EN (1 << 3)
237#define LIS3DSH_CTRL_REG3_INT2_EN (1 << 4)
238#define LIS3DSH_CTRL_REG3_IEL (1 << 5)
239#define LIS3DSH_CTRL_REG3_IEA (1 << 6)
240#define LIS3DSH_CTRL_REG3_DR_EN (1 << 7)
241/** @} */
242
243/**
244 * @name LIS3DSH_CTRL_REG4 register bits definitions
245 * @{
246 */
247#define LIS3DSH_CTRL_REG4_MASK 0xFF
248#define LIS3DSH_CTRL_REG4_XEN (1 << 0)
249#define LIS3DSH_CTRL_REG4_YEN (1 << 1)
250#define LIS3DSH_CTRL_REG4_ZEN (1 << 2)
251#define LIS3DSH_CTRL_REG4_BDU (1 << 3)
252#define LIS3DSH_CTRL_REG4_ODR_0 (1 << 4)
253#define LIS3DSH_CTRL_REG4_ODR_1 (1 << 5)
254#define LIS3DSH_CTRL_REG4_ODR_2 (1 << 6)
255#define LIS3DSH_CTRL_REG4_ODR_3 (1 << 7)
256/** @} */
257
258/**
259 * @name LIS3DSH_CTRL_REG5 register bits definitions
260 * @{
261 */
262#define LIS3DSH_CTRL_REG5_MASK 0xFF
263#define LIS3DSH_CTRL_REG5_SIM (1 << 0)
264#define LIS3DSH_CTRL_REG5_ST1 (1 << 1)
265#define LIS3DSH_CTRL_REG5_ST2 (1 << 2)
266#define LIS3DSH_CTRL_REG5_FS_MASK 0x38
267#define LIS3DSH_CTRL_REG5_FS0 (1 << 3)
268#define LIS3DSH_CTRL_REG5_FS1 (1 << 4)
269#define LIS3DSH_CTRL_REG5_FS2 (1 << 5)
270#define LIS3DSH_CTRL_REG5_BW1 (1 << 6)
271#define LIS3DSH_CTRL_REG5_BW2 (1 << 7)
272/** @} */
273
274/**
275 * @name LIS3DSH_CTRL_REG6 register bits definitions
276 * @{
277 */
278#define LIS3DSH_CTRL_REG6_MASK 0xFF
279#define LIS3DSH_CTRL_REG6_P2_BOOT (1 << 0)
280#define LIS3DSH_CTRL_REG6_P1_OVRUN (1 << 1)
281#define LIS3DSH_CTRL_REG6_P1_WTM (1 << 2)
282#define LIS3DSH_CTRL_REG6_P1_EMPTY (1 << 3)
283#define LIS3DSH_CTRL_REG6_ADD_INC (1 << 4)
284#define LIS3DSH_CTRL_REG6_WTM_EN (1 << 5)
285#define LIS3DSH_CTRL_REG6_FIFO_EN (1 << 6)
286#define LIS3DSH_CTRL_REG6_BOOT (1 << 7)
287/** @} */
288
289/*===========================================================================*/
290/* Driver pre-compile time settings. */
291/*===========================================================================*/
292
293/**
294 * @name Configuration options
295 * @{
296 */
297/**
298 * @brief LIS3DSH SPI interface switch.
299 * @details If set to @p TRUE the support for SPI is included.
300 * @note The default is @p TRUE.
301 */
302#if !defined(LIS3DSH_USE_SPI) || defined(__DOXYGEN__)
303#define LIS3DSH_USE_SPI TRUE
304#endif
305
306/**
307 * @brief LIS3DSH shared SPI switch.
308 * @details If set to @p TRUE the device acquires SPI bus ownership
309 * on each transaction.
310 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
311 */
312#if !defined(LIS3DSH_SHARED_SPI) || defined(__DOXYGEN__)
313#define LIS3DSH_SHARED_SPI FALSE
314#endif
315
316/**
317 * @brief LIS3DSH I2C interface switch.
318 * @details If set to @p TRUE the support for I2C is included.
319 * @note The default is @p FALSE.
320 */
321#if !defined(LIS3DSH_USE_I2C) || defined(__DOXYGEN__)
322#define LIS3DSH_USE_I2C FALSE
323#endif
324
325/**
326 * @brief LIS3DSH shared I2C switch.
327 * @details If set to @p TRUE the device acquires I2C bus ownership
328 * on each transaction.
329 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
330 */
331#if !defined(LIS3DSH_SHARED_I2C) || defined(__DOXYGEN__)
332#define LIS3DSH_SHARED_I2C FALSE
333#endif
334
335/**
336 * @brief LIS3DSH advanced configurations switch.
337 * @details If set to @p TRUE more configurations are available.
338 * @note The default is @p FALSE.
339 */
340#if !defined(LIS3DSH_USE_ADVANCED) || defined(__DOXYGEN__)
341#define LIS3DSH_USE_ADVANCED FALSE
342#endif
343/** @} */
344
345/*===========================================================================*/
346/* Derived constants and error checks. */
347/*===========================================================================*/
348
349#if !(LIS3DSH_USE_SPI ^ LIS3DSH_USE_I2C)
350#error "LIS3DSH_USE_SPI and LIS3DSH_USE_I2C cannot be both true or both false"
351#endif
352
353#if LIS3DSH_USE_SPI && !HAL_USE_SPI
354#error "LIS3DSH_USE_SPI requires HAL_USE_SPI"
355#endif
356
357#if LIS3DSH_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
358#error "LIS3DSH_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
359#endif
360
361#if LIS3DSH_USE_I2C && !HAL_USE_I2C
362#error "LIS3DSH_USE_I2C requires HAL_USE_I2C"
363#endif
364
365#if LIS3DSH_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
366#error "LIS3DSH_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
367#endif
368
369/*
370 * CHTODO: Add support for LIS3DSH over I2C.
371 */
372#if LIS3DSH_USE_I2C
373#error "LIS3DSH over I2C still not supported"
374#endif
375
376/*===========================================================================*/
377/* Driver data structures and types. */
378/*===========================================================================*/
379
380/**
381 * @name LIS3DSH data structures and types
382 * @{
383 */
384/**
385 * @brief Structure representing a LIS3DSH driver.
386 */
387typedef struct LIS3DSHDriver LIS3DSHDriver;
388
389/**
390 * @brief LIS3DSH full scale.
391 */
392typedef enum {
393 LIS3DSH_ACC_FS_2G = 0x00, /**< Full scale �2g. */
394 LIS3DSH_ACC_FS_4G = 0x08, /**< Full scale �4g. */
395 LIS3DSH_ACC_FS_6G = 0x10, /**< Full scale �6g. */
396 LIS3DSH_ACC_FS_8G = 0x18, /**< Full scale �8g. */
397 LIS3DSH_ACC_FS_16G = 0x20 /**< Full scale �16g. */
398}lis3dsh_acc_fs_t;
399
400/**
401 * @brief LIS3DSH output data rate.
402 */
403typedef enum {
404 LIS3DSH_ACC_ODR_PD = 0x00, /**< ODR 100 Hz. */
405 LIS3DSH_ACC_ODR_3_125HZ = 0x10, /**< ODR 3.125 Hz. */
406 LIS3DSH_ACC_ODR_6_25HZ = 0x20, /**< ODR 6.25 Hz. */
407 LIS3DSH_ACC_ODR_12_5HZ = 0x30, /**< ODR 12.5 Hz. */
408 LIS3DSH_ACC_ODR_25HZ = 0x40, /**< ODR 25 Hz. */
409 LIS3DSH_ACC_ODR_50HZ = 0x50, /**< ODR 50 Hz. */
410 LIS3DSH_ACC_ODR_100HZ = 0x60, /**< ODR 100 Hz. */
411 LIS3DSH_ACC_ODR_400HZ = 0x70, /**< ODR 400 Hz. */
412 LIS3DSH_ACC_ODR_800HZ = 0x80, /**< ODR 800 Hz. */
413 LIS3DSH_ACC_ODR_1600HZ = 0x90 /**< ODR 1600 Hz. */
414}lis3dsh_acc_odr_t;
415
416/**
417 * @brief LIS3DSH anti-aliasing bandwidth.
418 */
419typedef enum {
420 LIS3DSH_ACC_BW_800HZ = 0x00, /**< AA filter BW 800Hz. */
421 LIS3DSH_ACC_BW_200HZ = 0x40, /**< AA filter BW 200Hz. */
422 LIS3DSH_ACC_BW_400HZ = 0x80, /**< AA filter BW 400Hz. */
423 LIS3DSH_ACC_BW_50HZ = 0xC0 /**< AA filter BW 50Hz. */
424}lis3dsh_acc_bw_t;
425
426/**
427 * @brief LIS3DSH block data update.
428 */
429typedef enum {
430 LIS3DSH_ACC_BDU_CONTINUOUS = 0x00,/**< Block data continuously updated. */
431 LIS3DSH_ACC_BDU_BLOCKED = 0x80 /**< Block data updated after reading. */
432} lis3dsh_acc_bdu_t;
433
434/**
435 * @brief Driver state machine possible states.
436 */
437typedef enum {
438 LIS3DSH_UNINIT = 0, /**< Not initialized. */
439 LIS3DSH_STOP = 1, /**< Stopped. */
440 LIS3DSH_READY = 2, /**< Ready. */
441} lis3dsh_state_t;
442
443/**
444 * @brief LIS3DSH configuration structure.
445 */
446typedef struct {
447
448#if (LIS3DSH_USE_SPI) || defined(__DOXYGEN__)
449 /**
450 * @brief SPI driver associated to this LIS3DSH.
451 */
452 SPIDriver *spip;
453 /**
454 * @brief SPI configuration associated to this LIS3DSH.
455 */
456 const SPIConfig *spicfg;
457#endif /* LIS3DSH_USE_SPI */
458#if (LIS3DSH_USE_I2C) || defined(__DOXYGEN__)
459 /**
460 * @brief I2C driver associated to this LIS3DSH.
461 */
462 I2CDriver *i2cp;
463 /**
464 * @brief I2C configuration associated to this LIS3DSH.
465 */
466 const I2CConfig *i2ccfg;
467#endif /* LIS3DSH_USE_I2C */
468 /**
469 * @brief LIS3DSH accelerometer subsystem initial sensitivity.
470 */
471 float *accsensitivity;
472 /**
473 * @brief LIS3DSH accelerometer subsystem initial bias.
474 */
475 float *accbias;
476 /**
477 * @brief LIS3DSH accelerometer subsystem initial full scale.
478 */
479 lis3dsh_acc_fs_t accfullscale;
480 /**
481 * @brief LIS3DSH output data rate selection.
482 */
483 lis3dsh_acc_odr_t accoutputdatarate;
484#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
485 /**
486 * @brief LIS3DSH anti-aliasing bandwidth.
487 */
488 lis3dsh_acc_bw_t accantialiasing;
489 /**
490 * @brief LIS3DSH block data update.
491 */
492 lis3dsh_acc_bdu_t accblockdataupdate;
493#endif
494} LIS3DSHConfig;
495
496/**
497 * @brief @p LIS3DSH specific methods.
498 */
499#define _lis3dsh_methods_alone \
500 /* Change full scale value of LIS3DSH accelerometer subsystem.*/ \
501 msg_t (*acc_set_full_scale)(LIS3DSHDriver *devp, lis3dsh_acc_fs_t fs);
502
503
504/**
505 * @brief @p LIS3DSH specific methods with inherited ones.
506 */
507#define _lis3dsh_methods \
508 _base_object_methods \
509 _lis3dsh_methods_alone
510
511/**
512 * @extends BaseObjectVMT
513 *
514 * @brief @p LIS3DSH virtual methods table.
515 */
516struct LIS3DSHVMT {
517 _lis3dsh_methods
518};
519
520/**
521 * @brief @p LIS3DSHDriver specific data.
522 */
523#define _lis3dsh_data \
524 _base_sensor_data \
525 /* Driver state.*/ \
526 lis3dsh_state_t state; \
527 /* Current configuration data.*/ \
528 const LIS3DSHConfig *config; \
529 /* Accelerometer subsystem axes number.*/ \
530 size_t accaxes; \
531 /* Accelerometer subsystem current sensitivity.*/ \
532 float accsensitivity[LIS3DSH_ACC_NUMBER_OF_AXES]; \
533 /* Accelerometer subsystem current bias .*/ \
534 float accbias[LIS3DSH_ACC_NUMBER_OF_AXES]; \
535 /* Accelerometer subsystem current full scale value.*/ \
536 float accfullscale;
537
538/**
539 * @brief LIS3DSH 3-axis accelerometer class.
540 */
541struct LIS3DSHDriver {
542 /** @brief Virtual Methods Table.*/
543 const struct LIS3DSHVMT *vmt;
544 /** @brief Base accelerometer interface.*/
545 BaseAccelerometer acc_if;
546 _lis3dsh_data
547};
548/** @} */
549
550/*===========================================================================*/
551/* Driver macros. */
552/*===========================================================================*/
553
554/**
555 * @brief Return the number of axes of the BaseAccelerometer.
556 *
557 * @param[in] devp pointer to @p LIS3DSHDriver.
558 *
559 * @return the number of axes.
560 *
561 * @api
562 */
563#define lis3dshAccelerometerGetAxesNumber(devp) \
564 accelerometerGetAxesNumber(&((devp)->acc_if))
565
566/**
567 * @brief Retrieves raw data from the BaseAccelerometer.
568 * @note This data is retrieved from MEMS register without any algebraical
569 * manipulation.
570 * @note The axes array must be at least the same size of the
571 * BaseAccelerometer axes number.
572 *
573 * @param[in] devp pointer to @p LIS3DSHDriver.
574 * @param[out] axes a buffer which would be filled with raw data.
575 *
576 * @return The operation status.
577 * @retval MSG_OK if the function succeeded.
578 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
579 * be retrieved using @p i2cGetErrors().
580 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
581 *
582 * @api
583 */
584#define lis3dshAccelerometerReadRaw(devp, axes) \
585 accelerometerReadRaw(&((devp)->acc_if), axes)
586
587/**
588 * @brief Retrieves cooked data from the BaseAccelerometer.
589 * @note This data is manipulated according to the formula
590 * cooked = (raw * sensitivity) - bias.
591 * @note Final data is expressed as milli-G.
592 * @note The axes array must be at least the same size of the
593 * BaseAccelerometer axes number.
594 *
595 * @param[in] devp pointer to @p LIS3DSHDriver.
596 * @param[out] axes a buffer which would be filled with cooked data.
597 *
598 * @return The operation status.
599 * @retval MSG_OK if the function succeeded.
600 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
601 * be retrieved using @p i2cGetErrors().
602 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
603 *
604 * @api
605 */
606#define lis3dshAccelerometerReadCooked(devp, axes) \
607 accelerometerReadCooked(&((devp)->acc_if), axes)
608
609/**
610 * @brief Set bias values for the BaseAccelerometer.
611 * @note Bias must be expressed as milli-G.
612 * @note The bias buffer must be at least the same size of the
613 * BaseAccelerometer axes number.
614 *
615 * @param[in] devp pointer to @p LIS3DSHDriver.
616 * @param[in] bp a buffer which contains biases.
617 *
618 * @return The operation status.
619 * @retval MSG_OK if the function succeeded.
620 *
621 * @api
622 */
623#define lis3dshAccelerometerSetBias(devp, bp) \
624 accelerometerSetBias(&((devp)->acc_if), bp)
625
626/**
627 * @brief Reset bias values for the BaseAccelerometer.
628 * @note Default biases value are obtained from device datasheet when
629 * available otherwise they are considered zero.
630 *
631 * @param[in] devp pointer to @p LIS3DSHDriver.
632 *
633 * @return The operation status.
634 * @retval MSG_OK if the function succeeded.
635 *
636 * @api
637 */
638#define lis3dshAccelerometerResetBias(devp) \
639 accelerometerResetBias(&((devp)->acc_if))
640
641/**
642 * @brief Set sensitivity values for the BaseAccelerometer.
643 * @note Sensitivity must be expressed as milli-G/LSB.
644 * @note The sensitivity buffer must be at least the same size of the
645 * BaseAccelerometer axes number.
646 *
647 * @param[in] devp pointer to @p LIS3DSHDriver.
648 * @param[in] sp a buffer which contains sensitivities.
649 *
650 * @return The operation status.
651 * @retval MSG_OK if the function succeeded.
652 *
653 * @api
654 */
655#define lis3dshAccelerometerSetSensitivity(devp, sp) \
656 accelerometerSetSensitivity(&((devp)->acc_if), sp)
657
658/**
659 * @brief Reset sensitivity values for the BaseAccelerometer.
660 * @note Default sensitivities value are obtained from device datasheet.
661 *
662 * @param[in] devp pointer to @p LIS3DSHDriver.
663 *
664 * @return The operation status.
665 * @retval MSG_OK if the function succeeded.
666 * @retval MSG_RESET otherwise.
667 *
668 * @api
669 */
670#define lis3dshAccelerometerResetSensitivity(devp) \
671 accelerometerResetSensitivity(&((devp)->acc_if))
672
673/**
674 * @brief Changes the LIS3DSHDriver accelerometer fullscale value.
675 * @note This function also rescale sensitivities and biases based on
676 * previous and next fullscale value.
677 * @note A recalibration is highly suggested after calling this function.
678 *
679 * @param[in] devp pointer to @p LIS3DSHDriver.
680 * @param[in] fs new fullscale value.
681 *
682 * @return The operation status.
683 * @retval MSG_OK if the function succeeded.
684 * @retval MSG_RESET otherwise.
685 *
686 * @api
687 */
688#define lis3dshAccelerometerSetFullScale(devp, fs) \
689 (devp)->vmt->acc_set_full_scale(devp, fs)
690
691/*===========================================================================*/
692/* External declarations. */
693/*===========================================================================*/
694
695#ifdef __cplusplus
696extern "C" {
697#endif
698 void lis3dshObjectInit(LIS3DSHDriver *devp);
699 void lis3dshStart(LIS3DSHDriver *devp, const LIS3DSHConfig *config);
700 void lis3dshStop(LIS3DSHDriver *devp);
701#ifdef __cplusplus
702}
703#endif
704
705#endif /* _LIS3DSH_H_ */
706
707/** @} */
708
diff --git a/lib/chibios/os/ex/devices/ST/lis3dsh.mk b/lib/chibios/os/ex/devices/ST/lis3dsh.mk
new file mode 100644
index 000000000..270c78d9e
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis3dsh.mk
@@ -0,0 +1,10 @@
1# List of all the LIS3DSH device files.
2LIS3DSHSRC := $(CHIBIOS)/os/ex/devices/ST/lis3dsh.c
3
4# Required include directories
5LIS3DSHINC := $(CHIBIOS)/os/ex/include \
6 $(CHIBIOS)/os/ex/devices/ST
7
8# Shared variables
9ALLCSRC += $(LIS3DSHSRC)
10ALLINC += $(LIS3DSHINC) \ No newline at end of file
diff --git a/lib/chibios/os/ex/devices/ST/lis3mdl.c b/lib/chibios/os/ex/devices/ST/lis3mdl.c
new file mode 100644
index 000000000..6f167e929
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis3mdl.c
@@ -0,0 +1,627 @@
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 lis3mdl.c
23 * @brief LIS3MDL MEMS interface module code.
24 *
25 * @addtogroup LIS3MDL
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "lis3mdl.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 (LIS3MDL_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 *
54 * @param[in] i2cp pointer to the I2C interface
55 * @param[in] sad slave address without R bit
56 * @param[in] reg first sub-register address
57 * @param[out] rxbuf pointer to an output buffer
58 * @param[in] n number of consecutive register to read
59 * @return the operation status.
60 * @notapi
61 */
62msg_t lis3mdlI2CReadRegister(I2CDriver *i2cp, lis3mdl_sad_t sad, uint8_t reg,
63 uint8_t* rxbuf, size_t n) {
64 uint8_t txbuf = reg;
65 if(n > 1)
66 txbuf |= LIS3MDL_SUB_MS;
67
68 return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
69 TIME_INFINITE);
70}
71
72/**
73 * @brief Writes a value into a register using I2C.
74 * @pre The I2C interface must be initialized and the driver started.
75 *
76 * @param[in] i2cp pointer to the I2C interface
77 * @param[in] sad slave address without R bit
78 * @param[in] txbuf buffer containing sub-address value in first position
79 * and values to write
80 * @param[in] n size of txbuf less one (not considering the first
81 * element)
82 * @return the operation status.
83 * @notapi
84 */
85msg_t lis3mdlI2CWriteRegister(I2CDriver *i2cp, lis3mdl_sad_t sad, uint8_t* txbuf,
86 uint8_t n) {
87 if (n > 1)
88 (*txbuf) |= LIS3MDL_SUB_MS;
89
90 return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
91 TIME_INFINITE);
92}
93#endif /* LIS3MDL_USE_I2C */
94
95/**
96 * @brief Return the number of axes of the BaseCompass.
97 *
98 * @param[in] ip pointer to @p BaseCompass interface
99 *
100 * @return the number of axes.
101 */
102static size_t comp_get_axes_number(void *ip) {
103
104 osalDbgCheck(ip != NULL);
105 return LIS3MDL_COMP_NUMBER_OF_AXES;
106}
107
108/**
109 * @brief Retrieves raw data from the BaseCompass.
110 * @note This data is retrieved from MEMS register without any algebraical
111 * manipulation.
112 * @note The axes array must be at least the same size of the
113 * BaseCompass axes number.
114 *
115 * @param[in] ip pointer to @p BaseCompass interface.
116 * @param[out] axes a buffer which would be filled with raw data.
117 *
118 * @return The operation status.
119 * @retval MSG_OK if the function succeeded.
120 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
121 * be retrieved using @p i2cGetErrors().
122 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
123 */
124static msg_t comp_read_raw(void *ip, int32_t axes[]) {
125 LIS3MDLDriver* devp;
126 uint8_t buff [LIS3MDL_COMP_NUMBER_OF_AXES * 2], i;
127 int16_t tmp;
128 msg_t msg;
129
130 osalDbgCheck((ip != NULL) && (axes != NULL));
131
132 /* Getting parent instance pointer.*/
133 devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
134
135 osalDbgAssert((devp->state == LIS3MDL_READY),
136 "comp_read_raw(), invalid state");
137 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
138 "comp_read_raw(), channel not ready");
139
140#if LIS3MDL_SHARED_I2C
141 i2cAcquireBus(devp->config->i2cp);
142 i2cStart(devp->config->i2cp,
143 devp->config->i2ccfg);
144#endif /* LIS3MDL_SHARED_I2C */
145 msg = lis3mdlI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
146 LIS3MDL_AD_OUT_X_L, buff,
147 LIS3MDL_COMP_NUMBER_OF_AXES * 2);
148
149#if LIS3MDL_SHARED_I2C
150 i2cReleaseBus(devp->config->i2cp);
151#endif /* LIS3MDL_SHARED_I2C */
152
153 if(msg == MSG_OK)
154 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
155 tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
156 axes[i] = (int32_t)tmp;
157 }
158 return msg;
159}
160
161/**
162 * @brief Retrieves cooked data from the BaseCompass.
163 * @note This data is manipulated according to the formula
164 * cooked = (raw * sensitivity) - bias.
165 * @note Final data is expressed as G.
166 * @note The axes array must be at least the same size of the
167 * BaseCompass axes number.
168 *
169 * @param[in] ip pointer to @p BaseCompass interface.
170 * @param[out] axes a buffer which would be filled with cooked data.
171 *
172 * @return The operation status.
173 * @retval MSG_OK if the function succeeded.
174 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
175 * be retrieved using @p i2cGetErrors().
176 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
177 */
178static msg_t comp_read_cooked(void *ip, float axes[]) {
179 LIS3MDLDriver* devp;
180 uint32_t i;
181 int32_t raw[LIS3MDL_COMP_NUMBER_OF_AXES];
182 msg_t msg;
183
184 osalDbgCheck((ip != NULL) && (axes != NULL));
185
186
187 /* Getting parent instance pointer.*/
188 devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
189
190 osalDbgAssert((devp->state == LIS3MDL_READY),
191 "comp_read_cooked(), invalid state");
192
193 msg = comp_read_raw(ip, raw);
194 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES ; i++) {
195 axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i];
196 }
197 return msg;
198}
199
200/**
201 * @brief Set bias values for the BaseCompass.
202 * @note Bias must be expressed as G.
203 * @note The bias buffer must be at least the same size of the
204 * BaseCompass axes number.
205 *
206 * @param[in] ip pointer to @p BaseCompass interface.
207 * @param[in] bp a buffer which contains biases.
208 *
209 * @return The operation status.
210 * @retval MSG_OK if the function succeeded.
211 */
212static msg_t comp_set_bias(void *ip, float *bp) {
213 LIS3MDLDriver* devp;
214 uint32_t i;
215 msg_t msg = MSG_OK;
216
217 osalDbgCheck((ip != NULL) && (bp != NULL));
218
219 /* Getting parent instance pointer.*/
220 devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
221
222 osalDbgAssert((devp->state == LIS3MDL_READY),
223 "comp_set_bias(), invalid state");
224
225 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
226 devp->compbias[i] = bp[i];
227 }
228 return msg;
229}
230
231/**
232 * @brief Reset bias values for the BaseCompass.
233 * @note Default biases value are obtained from device datasheet when
234 * available otherwise they are considered zero.
235 *
236 * @param[in] ip pointer to @p BaseCompass interface.
237 *
238 * @return The operation status.
239 * @retval MSG_OK if the function succeeded.
240 */
241static msg_t comp_reset_bias(void *ip) {
242 LIS3MDLDriver* devp;
243 uint32_t i;
244 msg_t msg = MSG_OK;
245
246 osalDbgCheck(ip != NULL);
247
248 /* Getting parent instance pointer.*/
249 devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
250
251 osalDbgAssert((devp->state == LIS3MDL_READY),
252 "comp_reset_bias(), invalid state");
253
254 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
255 devp->compbias[i] = LIS3MDL_COMP_BIAS;
256 return msg;
257}
258
259/**
260 * @brief Set sensitivity values for the BaseCompass.
261 * @note Sensitivity must be expressed as G/LSB.
262 * @note The sensitivity buffer must be at least the same size of the
263 * BaseCompass axes number.
264 *
265 * @param[in] ip pointer to @p BaseCompass interface.
266 * @param[in] sp a buffer which contains sensitivities.
267 *
268 * @return The operation status.
269 * @retval MSG_OK if the function succeeded.
270 */
271static msg_t comp_set_sensivity(void *ip, float *sp) {
272 LIS3MDLDriver* devp;
273 uint32_t i;
274 msg_t msg = MSG_OK;
275
276 /* Getting parent instance pointer.*/
277 devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
278
279 osalDbgCheck((ip != NULL) && (sp != NULL));
280
281 osalDbgAssert((devp->state == LIS3MDL_READY),
282 "comp_set_sensivity(), invalid state");
283
284 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
285 devp->compsensitivity[i] = sp[i];
286 }
287 return msg;
288}
289
290/**
291 * @brief Reset sensitivity values for the BaseCompass.
292 * @note Default sensitivities value are obtained from device datasheet.
293 *
294 * @param[in] ip pointer to @p BaseCompass interface.
295 *
296 * @return The operation status.
297 * @retval MSG_OK if the function succeeded.
298 * @retval MSG_RESET otherwise.
299 */
300static msg_t comp_reset_sensivity(void *ip) {
301 LIS3MDLDriver* devp;
302 uint32_t i;
303 msg_t msg = MSG_OK;
304
305 osalDbgCheck(ip != NULL);
306
307 /* Getting parent instance pointer.*/
308 devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
309
310 osalDbgAssert((devp->state == LIS3MDL_READY),
311 "comp_reset_sensivity(), invalid state");
312
313 if(devp->config->compfullscale == LIS3MDL_COMP_FS_4GA)
314 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
315 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_4GA;
316 else if(devp->config->compfullscale == LIS3MDL_COMP_FS_8GA)
317 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
318 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_8GA;
319 else if(devp->config->compfullscale == LIS3MDL_COMP_FS_12GA)
320 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
321 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_12GA;
322 else if(devp->config->compfullscale == LIS3MDL_COMP_FS_16GA)
323 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
324 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_16GA;
325 else {
326 osalDbgAssert(FALSE, "comp_reset_sensivity(), compass full scale issue");
327 msg = MSG_RESET;
328 }
329 return msg;
330}
331
332/**
333 * @brief Changes the LIS3MDLDriver compass fullscale value.
334 * @note This function also rescale sensitivities and biases based on
335 * previous and next fullscale value.
336 * @note A recalibration is highly suggested after calling this function.
337 *
338 * @param[in] devp pointer to @p LIS3MDLDriver interface.
339 * @param[in] fs new fullscale value.
340 *
341 * @return The operation status.
342 * @retval MSG_OK if the function succeeded.
343 * @retval MSG_RESET otherwise.
344 */
345static msg_t comp_set_full_scale(LIS3MDLDriver *devp, lis3mdl_comp_fs_t fs) {
346 float newfs, scale;
347 uint8_t i, buff[2];
348 msg_t msg;
349
350 osalDbgCheck(devp != NULL);
351
352 osalDbgAssert((devp->state == LIS3MDL_READY),
353 "comp_set_full_scale(), invalid state");
354 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
355 "comp_set_full_scale(), channel not ready");
356
357 /* Computing new fullscale value.*/
358 if(fs == LIS3MDL_COMP_FS_4GA) {
359 newfs = LIS3MDL_COMP_4GA;
360 }
361 else if(fs == LIS3MDL_COMP_FS_8GA) {
362 newfs = LIS3MDL_COMP_8GA;
363 }
364 else if(fs == LIS3MDL_COMP_FS_12GA) {
365 newfs = LIS3MDL_COMP_12GA;
366 }
367 else if(fs == LIS3MDL_COMP_FS_16GA) {
368 newfs = LIS3MDL_COMP_16GA;
369 }
370 else {
371 msg = MSG_RESET;
372 return msg;
373 }
374
375 if(newfs != devp->compfullscale) {
376 /* Computing scale value.*/
377 scale = newfs / devp->compfullscale;
378 devp->compfullscale = newfs;
379
380#if LIS3MDL_SHARED_I2C
381 i2cAcquireBus(devp->config->i2cp);
382 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
383#endif /* LIS3MDL_SHARED_I2C */
384
385 /* Updating register.*/
386 msg = lis3mdlI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
387 LIS3MDL_AD_CTRL_REG2, &buff[1], 1);
388
389#if LIS3MDL_SHARED_I2C
390 i2cReleaseBus(devp->config->i2cp);
391#endif /* LIS3MDL_SHARED_I2C */
392
393 if(msg != MSG_OK)
394 return msg;
395 buff[1] &= ~(LIS3MDL_CTRL_REG2_FS_MASK);
396 buff[1] |= fs;
397 buff[0] = LIS3MDL_AD_CTRL_REG2;
398
399#if LIS3MDL_SHARED_I2C
400 i2cAcquireBus(devp->config->i2cp);
401 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
402#endif /* LIS3MDL_SHARED_I2C */
403
404 msg = lis3mdlI2CWriteRegister(devp->config->i2cp,
405 devp->config->slaveaddress,
406 buff, 1);
407
408#if LIS3MDL_SHARED_I2C
409 i2cReleaseBus(devp->config->i2cp);
410#endif /* LIS3MDL_SHARED_I2C */
411
412 if(msg != MSG_OK)
413 return msg;
414
415 /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
416 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
417 devp->compsensitivity[i] *= scale;
418 devp->compbias[i] *= scale;
419 }
420 }
421 return msg;
422}
423
424static const struct LIS3MDLVMT vmt_device = {
425 (size_t)0,
426 comp_set_full_scale
427};
428
429static const struct BaseCompassVMT vmt_compass = {
430 sizeof(struct LIS3MDLVMT*),
431 comp_get_axes_number, comp_read_raw, comp_read_cooked,
432 comp_set_bias, comp_reset_bias, comp_set_sensivity, comp_reset_sensivity
433};
434
435/*===========================================================================*/
436/* Driver exported functions. */
437/*===========================================================================*/
438
439/**
440 * @brief Initializes an instance.
441 *
442 * @param[out] devp pointer to the @p LIS3MDLDriver object
443 *
444 * @init
445 */
446void lis3mdlObjectInit(LIS3MDLDriver *devp) {
447 devp->vmt = &vmt_device;
448 devp->comp_if.vmt = &vmt_compass;
449
450 devp->config = NULL;
451
452 devp->compaxes = LIS3MDL_COMP_NUMBER_OF_AXES;
453
454 devp->state = LIS3MDL_STOP;
455}
456
457/**
458 * @brief Configures and activates LIS3MDL Complex Driver peripheral.
459 *
460 * @param[in] devp pointer to the @p LIS3MDLDriver object
461 * @param[in] config pointer to the @p LIS3MDLConfig object
462 *
463 * @api
464 */
465void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config) {
466 uint32_t i;
467 uint8_t cr[6];
468 osalDbgCheck((devp != NULL) && (config != NULL));
469
470 osalDbgAssert((devp->state == LIS3MDL_STOP) || (devp->state == LIS3MDL_READY),
471 "lis3mdlStart(), invalid state");
472
473 devp->config = config;
474
475 /* Control register 1 configuration block.*/
476 {
477 cr[0] = LIS3MDL_AD_CTRL_REG1;
478 cr[1] = devp->config->compoutputdatarate;
479#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
480 cr[1] |= devp->config->compoperationmodexy;
481#else
482 cr[1] |= LIS3MDL_CTRL_REG1_OM0 | LIS3MDL_CTRL_REG1_OM1;
483#endif
484 }
485
486 /* Control register 2 configuration block.*/
487 {
488 cr[2] = devp->config->compfullscale;
489 }
490
491 /* Control register 3 configuration block.*/
492 {
493 cr[3] = 0;
494#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
495 cr[3] = devp->config->compconversionmode;
496#endif
497 }
498
499 /* Control register 4 configuration block.*/
500 {
501 cr[4] = 0;
502#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
503 cr[4] = devp->config->compoperationmodez | devp->config->endianness;
504#endif
505 }
506
507 /* Control register 5 configuration block.*/
508 {
509 cr[5] = 0;
510#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
511 cr[5] = devp->config->blockdataupdate;
512#endif
513 }
514
515#if LIS3MDL_USE_I2C
516#if LIS3MDL_SHARED_I2C
517 i2cAcquireBus((devp)->config->i2cp);
518#endif /* LIS3MDL_SHARED_I2C */
519 i2cStart((devp)->config->i2cp,
520 (devp)->config->i2ccfg);
521
522 lis3mdlI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
523 cr, 5);
524
525#if LIS3MDL_SHARED_I2C
526 i2cReleaseBus((devp)->config->i2cp);
527#endif /* LIS3MDL_SHARED_I2C */
528#endif /* LIS3MDL_USE_I2C */
529
530 if(devp->config->compfullscale == LIS3MDL_COMP_FS_4GA) {
531 devp->compfullscale = LIS3MDL_COMP_4GA;
532 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
533 if(devp->config->compsensitivity == NULL) {
534 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_4GA;
535 }
536 else {
537 devp->compsensitivity[i] = devp->config->compsensitivity[i];
538 }
539 }
540 }
541 else if(devp->config->compfullscale == LIS3MDL_COMP_FS_8GA) {
542 devp->compfullscale = LIS3MDL_COMP_8GA;
543 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
544 if(devp->config->compsensitivity == NULL) {
545 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_8GA;
546 }
547 else {
548 devp->compsensitivity[i] = devp->config->compsensitivity[i];
549 }
550 }
551 }
552 else if(devp->config->compfullscale == LIS3MDL_COMP_FS_12GA) {
553 devp->compfullscale = LIS3MDL_COMP_12GA;
554 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
555 if(devp->config->compsensitivity == NULL) {
556 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_12GA;
557 }
558 else {
559 devp->compsensitivity[i] = devp->config->compsensitivity[i];
560 }
561 }
562 }
563 else if(devp->config->compfullscale == LIS3MDL_COMP_FS_16GA) {
564 devp->compfullscale = LIS3MDL_COMP_16GA;
565 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
566 if(devp->config->compsensitivity == NULL) {
567 devp->compsensitivity[i] = LIS3MDL_COMP_SENS_16GA;
568 }
569 else {
570 devp->compsensitivity[i] = devp->config->compsensitivity[i];
571 }
572 }
573 }
574 else
575 osalDbgAssert(FALSE, "lis3mdlStart(), compass full scale issue");
576
577 /* Storing bias information */
578 if(devp->config->compbias != NULL)
579 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
580 devp->compbias[i] = devp->config->compbias[i];
581 else
582 for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
583 devp->compbias[i] = LIS3MDL_COMP_BIAS;
584
585 /* This is the MEMS transient recovery time */
586 osalThreadSleepMilliseconds(5);
587
588 devp->state = LIS3MDL_READY;
589}
590
591/**
592 * @brief Deactivates the LIS3MDL Complex Driver peripheral.
593 *
594 * @param[in] devp pointer to the @p LIS3MDLDriver object
595 *
596 * @api
597 */
598void lis3mdlStop(LIS3MDLDriver *devp) {
599 uint8_t cr[2];
600 osalDbgCheck(devp != NULL);
601
602 osalDbgAssert((devp->state == LIS3MDL_STOP) || (devp->state == LIS3MDL_READY),
603 "lis3mdlStop(), invalid state");
604
605 if (devp->state == LIS3MDL_READY) {
606#if (LIS3MDL_USE_I2C)
607#if LIS3MDL_SHARED_I2C
608 i2cAcquireBus((devp)->config->i2cp);
609 i2cStart((devp)->config->i2cp,
610 (devp)->config->i2ccfg);
611#endif /* LIS3MDL_SHARED_I2C */
612
613 /* Disabling compass. */
614 cr[0] = LIS3MDL_AD_CTRL_REG3;
615 cr[1] = LIS3MDL_CTRL_REG3_MD0 | LIS3MDL_CTRL_REG3_MD1;
616 lis3mdlI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
617 cr, 1);
618
619 i2cStop((devp)->config->i2cp);
620#if LIS3MDL_SHARED_I2C
621 i2cReleaseBus((devp)->config->i2cp);
622#endif /* LIS3MDL_SHARED_I2C */
623#endif /* LIS3MDL_USE_I2C */
624 }
625 devp->state = LIS3MDL_STOP;
626}
627/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/lis3mdl.h b/lib/chibios/os/ex/devices/ST/lis3mdl.h
new file mode 100644
index 000000000..4adf2954f
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis3mdl.h
@@ -0,0 +1,670 @@
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 lis3mdl.h
23 * @brief LIS3MDL MEMS interface module header.
24 *
25 * @addtogroup LIS3MDL
26 * @ingroup EX_ST
27 * @{
28 */
29#ifndef _LIS3MDL_H_
30#define _LIS3MDL_H_
31
32#include "ex_compass.h"
33
34/*===========================================================================*/
35/* Driver constants. */
36/*===========================================================================*/
37
38/**
39 * @name Version identification
40 * @{
41 */
42/**
43 * @brief LIS3MDL driver version string.
44 */
45#define EX_LIS3MDL_VERSION "1.1.2"
46
47/**
48 * @brief LIS3MDL driver version major number.
49 */
50#define EX_LIS3MDL_MAJOR 1
51
52/**
53 * @brief LIS3MDL driver version minor number.
54 */
55#define EX_LIS3MDL_MINOR 1
56
57/**
58 * @brief LIS3MDL driver version patch number.
59 */
60#define EX_LIS3MDL_PATCH 2
61/** @} */
62
63/**
64 * @brief LIS3MDL compass subsystem characteristics.
65 * @note Sensitivity is expressed as G/LSB whereas G stands for Gauss.
66 * @note Bias is expressed as G.
67 *
68 * @{
69 */
70#define LIS3MDL_COMP_NUMBER_OF_AXES 3U
71
72#define LIS3MDL_COMP_4GA 4.0f
73#define LIS3MDL_COMP_8GA 8.0f
74#define LIS3MDL_COMP_12GA 12.0f
75#define LIS3MDL_COMP_16GA 16.0f
76
77#define LIS3MDL_COMP_SENS_4GA 0.00014615f
78#define LIS3MDL_COMP_SENS_8GA 0.00029231f
79#define LIS3MDL_COMP_SENS_12GA 0.0004384f
80#define LIS3MDL_COMP_SENS_16GA 0.00058445f
81
82#define LIS3MDL_COMP_BIAS 0.0f
83/** @} */
84
85/**
86 * @name LIS3MDL communication interfaces related bit masks
87 * @{
88 */
89#define LIS3MDL_DI_MASK 0xFF
90#define LIS3MDL_DI(n) (1 << n)
91#define LIS3MDL_AD_MASK 0x3F
92#define LIS3MDL_AD(n) (1 << n)
93#define LIS3MDL_MS (1 << 6)
94#define LIS3MDL_RW (1 << 7)
95
96#define LIS3MDL_SUB_MS (1 << 7)
97/** @} */
98
99/**
100 * @name LIS3MDL register addresses
101 * @{
102 */
103#define LIS3MDL_AD_WHO_AM_I 0x0F
104#define LIS3MDL_AD_CTRL_REG1 0x20
105#define LIS3MDL_AD_CTRL_REG2 0x21
106#define LIS3MDL_AD_CTRL_REG3 0x22
107#define LIS3MDL_AD_CTRL_REG4 0x23
108#define LIS3MDL_AD_CTRL_REG5 0x24
109#define LIS3MDL_AD_STATUS_REG 0x27
110#define LIS3MDL_AD_OUT_X_L 0x28
111#define LIS3MDL_AD_OUT_X_H 0x29
112#define LIS3MDL_AD_OUT_Y_L 0x2A
113#define LIS3MDL_AD_OUT_Y_H 0x2B
114#define LIS3MDL_AD_OUT_Z_L 0x2C
115#define LIS3MDL_AD_OUT_Z_H 0x2D
116#define LIS3MDL_AD_TEMP_OUT_L 0x2E
117#define LIS3MDL_AD_TEMP_OUT_H 0x2F
118#define LIS3MDL_AD_INT_CFG 0x30
119#define LIS3MDL_AD_INT_SOURCE 0x31
120#define LIS3MDL_AD_INT_THS_L 0x32
121#define LIS3MDL_AD_INT_THS_H 0x33
122/** @} */
123
124/**
125 * @name LIS3MDL_CTRL_REG1 register bits definitions
126 * @{
127 */
128#define LIS3MDL_CTRL_REG1_MASK 0xFF
129#define LIS3MDL_CTRL_REG1_ST (1 << 0)
130#define LIS3MDL_CTRL_REG1_FAST_ODR (1 << 1)
131#define LIS3MDL_CTRL_REG1_DO0 (1 << 2)
132#define LIS3MDL_CTRL_REG1_DO1 (1 << 3)
133#define LIS3MDL_CTRL_REG1_DO2 (1 << 4)
134#define LIS3MDL_CTRL_REG1_OM0 (1 << 5)
135#define LIS3MDL_CTRL_REG1_OM1 (1 << 6)
136#define LIS3MDL_CTRL_REG1_TEMP_EN (1 << 7)
137/** @} */
138
139/**
140 * @name LIS3MDL_CTRL_REG2 register bits definitions
141 * @{
142 */
143#define LIS3MDL_CTRL_REG2_MASK 0x6C
144#define LIS3MDL_CTRL_REG2_SOFT_RST (1 << 2)
145#define LIS3MDL_CTRL_REG2_REBOOT (1 << 3)
146#define LIS3MDL_CTRL_REG2_FS_MASK 0x60
147#define LIS3MDL_CTRL_REG2_FS0 (1 << 5)
148#define LIS3MDL_CTRL_REG2_FS1 (1 << 6)
149/** @} */
150
151/**
152 * @name LIS3MDL_CTRL_REG3 register bits definitions
153 * @{
154 */
155#define LIS3MDL_CTRL_REG3_MASK 0x27
156#define LIS3MDL_CTRL_REG3_MD0 (1 << 0)
157#define LIS3MDL_CTRL_REG3_MD1 (1 << 1)
158#define LIS3MDL_CTRL_REG3_SIM (1 << 2)
159#define LIS3MDL_CTRL_REG3_LP (1 << 5)
160/** @} */
161
162/**
163 * @name LIS3MDL_CTRL_REG4 register bits definitions
164 * @{
165 */
166#define LIS3MDL_CTRL_REG4_MASK 0x0E
167#define LIS3MDL_CTRL_REG4_BLE (1 << 1)
168#define LIS3MDL_CTRL_REG4_OMZ0 (1 << 2)
169#define LIS3MDL_CTRL_REG4_OMZ1 (1 << 3)
170/** @} */
171
172/**
173 * @name LIS3MDL_CTRL_REG5 register bits definitions
174 * @{
175 */
176#define LIS3MDL_CTRL_REG5_MASK 0xC0
177#define LIS3MDL_CTRL_REG5_BDU (1 << 6)
178#define LIS3MDL_CTRL_REG5_FAST_READ (1 << 7)
179/** @} */
180
181/*===========================================================================*/
182/* Driver pre-compile time settings. */
183/*===========================================================================*/
184
185/**
186 * @name Configuration options
187 * @{
188 */
189/**
190 * @brief LIS3MDL SPI interface switch.
191 * @details If set to @p TRUE the support for SPI is included.
192 * @note The default is @p FALSE.
193 */
194#if !defined(LIS3MDL_USE_SPI) || defined(__DOXYGEN__)
195#define LIS3MDL_USE_SPI FALSE
196#endif
197
198/**
199 * @brief LIS3MDL shared SPI switch.
200 * @details If set to @p TRUE the device acquires SPI bus ownership
201 * on each transaction.
202 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
203 */
204#if !defined(LIS3MDL_SHARED_SPI) || defined(__DOXYGEN__)
205#define LIS3MDL_SHARED_SPI FALSE
206#endif
207
208/**
209 * @brief LIS3MDL I2C interface switch.
210 * @details If set to @p TRUE the support for I2C is included.
211 * @note The default is @p TRUE.
212 */
213#if !defined(LIS3MDL_USE_I2C) || defined(__DOXYGEN__)
214#define LIS3MDL_USE_I2C TRUE
215#endif
216
217/**
218 * @brief LIS3MDL shared I2C switch.
219 * @details If set to @p TRUE the device acquires I2C bus ownership
220 * on each transaction.
221 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION
222 */
223#if !defined(LIS3MDL_SHARED_I2C) || defined(__DOXYGEN__)
224#define LIS3MDL_SHARED_I2C FALSE
225#endif
226
227/**
228 * @brief LIS3MDL advanced configurations switch.
229 * @details If set to @p TRUE more configurations are available.
230 * @note The default is @p FALSE.
231 */
232#if !defined(LIS3MDL_USE_ADVANCED) || defined(__DOXYGEN__)
233#define LIS3MDL_USE_ADVANCED FALSE
234#endif
235/** @} */
236
237/*===========================================================================*/
238/* Derived constants and error checks. */
239/*===========================================================================*/
240
241#if !(LIS3MDL_USE_SPI ^ LIS3MDL_USE_I2C)
242#error "LIS3MDL_USE_SPI and LIS3MDL_USE_I2C cannot be both true or both false"
243#endif
244
245#if LIS3MDL_USE_SPI && !HAL_USE_SPI
246#error "LIS3MDL_USE_SPI requires HAL_USE_SPI"
247#endif
248
249#if LIS3MDL_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
250#error "LIS3MDL_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
251#endif
252
253#if LIS3MDL_USE_I2C && !HAL_USE_I2C
254#error "LIS3MDL_USE_I2C requires HAL_USE_I2C"
255#endif
256
257#if LIS3MDL_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
258#error "LIS3MDL_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
259#endif
260
261/*
262 * CHTODO: Add support for LIS3MDL over SPI.
263 */
264#if LIS3MDL_USE_SPI
265#error "LIS3MDL over SPI still not supported"
266#endif
267
268/*===========================================================================*/
269/* Driver data structures and types. */
270/*===========================================================================*/
271
272/**
273 * @name LIS3MDL data structures and types
274 * @{
275 */
276
277/**
278 * @brief LIS3MDL slave address
279 */
280/**
281 * @brief Structure representing a LIS3MDL driver.
282 */
283typedef struct LIS3MDLDriver LIS3MDLDriver;
284
285/**
286 * @brief LIS3MDL slave address
287 */
288typedef enum {
289 LIS3MDL_SAD_GND = 0x1C, /**< Slave Address when SA1 is to GND */
290 LIS3MDL_SAD_VCC = 0x1E /**< Slave Address when SA1 is to VCC */
291}lis3mdl_sad_t;
292
293/**
294 * @brief LIS3MDL full scale
295 */
296typedef enum {
297 LIS3MDL_COMP_FS_4GA = 0x00, /**< �4 Gauss */
298 LIS3MDL_COMP_FS_8GA = 0x20, /**< �8 Gauss */
299 LIS3MDL_COMP_FS_12GA = 0x40, /**< �12 Gauss */
300 LIS3MDL_COMP_FS_16GA = 0x60 /**< �16 Gauss */
301}lis3mdl_comp_fs_t;
302
303/**
304 * @brief LIS3MDL output data rate
305 */
306typedef enum {
307 LIS3MDL_COMP_ODR_0_625HZ = 0x00, /**< Output Data Rate = 0.625 Hz */
308 LIS3MDL_COMP_ODR_1_25HZ = 0x04, /**< Output Data Rate = 1.25 Hz */
309 LIS3MDL_COMP_ODR_2_5HZ = 0x08, /**< Output Data Rate = 2.5 Hz */
310 LIS3MDL_COMP_ODR_5HZ = 0x0C, /**< Output Data Rate = 5 Hz */
311 LIS3MDL_COMP_ODR_10HZ = 0x10, /**< Output Data Rate = 10 Hz */
312 LIS3MDL_COMP_ODR_20HZ = 0x14, /**< Output Data Rate = 20 Hz */
313 LIS3MDL_COMP_ODR_40HZ = 0x18, /**< Output Data Rate = 40 Hz */
314 LIS3MDL_COMP_ODR_80HZ = 0x1C /**< Output Data Rate = 80 Hz */
315}lis3mdl_comp_odr_t;
316
317/**
318 * @brief LIS3MDL low power mode configuration
319 */
320typedef enum {
321 LIS3MDL_COMP_LP_DISABLED = 0x00, /**< Low Power mode disabled */
322 LIS3MDL_COMP_LP_ENABLED = 0x20 /**< Low Power mode enabled */
323}lis3mdl_comp_lp_t;
324
325/**
326 * @brief LIS3MDL conversion mode
327 */
328typedef enum {
329 LIS3MDL_COMP_MD_CONTINUOUS = 0x00,/**< Continuous conversion mode */
330 LIS3MDL_COMP_MD_SINGLE = 0x01, /**< Single conversion mode */
331 LIS3MDL_COMP_MD_POWER_DOWN = 0x02 /**< Power down mode */
332}lis3mdl_comp_md_t;
333
334/**
335 * @brief LIS3MDL operation mode for X and Y axes
336 */
337typedef enum {
338 LIS3MDL_COMP_OMXY_LP = 0x00, /**< X-Y axes low power mode */
339 LIS3MDL_COMP_OMXY_MEDIUM = 0x20, /**< X-Y axes medium performance mode */
340 LIS3MDL_COMP_OMXY_HIGH = 0x40, /**< X-Y axes high performance mode */
341 LIS3MDL_COMP_OMXY_ULTRA = 0x60 /**< X-Y axes ultra performance mode */
342}lis3mdl_comp_omxy_t;
343
344/**
345 * @brief LIS3MDL operation mode for Z axis
346 */
347typedef enum {
348 LIS3MDL_COMP_OMZ_LP = 0x00, /**< Z axis low power mode */
349 LIS3MDL_COMP_OMZ_MEDIUM = 0x04, /**< Z axis medium performance mode */
350 LIS3MDL_COMP_OMZ_HIGH = 0x08, /**< Z axis high performance mode */
351 LIS3MDL_COMP_OMZ_ULTRA = 0x0C /**< Z axis ultra performance mode */
352}lis3mdl_comp_omz_t;
353
354/**
355 * @brief LIS3MDL temperature sensor enabling
356 */
357typedef enum {
358 LIS3MDL_TEMP_DISABLED = 0x00, /**< Temperature sensor disabled. */
359 LIS3MDL_TEMP_ENABLED = 0x80 /**< Temperature sensor enabled. */
360}lis3mdl_temp_t;
361
362/**
363 * @brief LIS3MDL block data update
364 */
365typedef enum {
366 LIS3MDL_BDU_CONTINUOUS = 0x00, /**< Continuous Update */
367 LIS3MDL_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
368}lis3mdl_bdu_t;
369
370/**
371 * @brief LIS3MDL endianness
372 */
373typedef enum {
374 LIS3MDL_END_LITTLE = 0x00, /**< Little endian. */
375 LIS3MDL_END_BIG = 0x02 /**< Big endian. */
376}lis3mdl_end_t;
377
378/**
379 * @brief Driver state machine possible states.
380 */
381typedef enum {
382 LIS3MDL_UNINIT = 0, /**< Not initialized. */
383 LIS3MDL_STOP = 1, /**< Stopped. */
384 LIS3MDL_READY = 2, /**< Ready. */
385} lis3mdl_state_t;
386
387/**
388 * @brief LIS3MDL configuration structure.
389 */
390typedef struct {
391#if (LIS3MDL_USE_SPI) || defined(__DOXYGEN__)
392 /**
393 * @brief SPI driver associated to this LIS3MDL.
394 */
395 SPIDriver *spip;
396 /**
397 * @brief SPI configuration associated to this LIS3MDL.
398 */
399 const SPIConfig *spicfg;
400#endif /* LIS3MDL_USE_SPI */
401#if (LIS3MDL_USE_I2C) || defined(__DOXYGEN__)
402 /**
403 * @brief I2C driver associated to this LIS3MDL.
404 */
405 I2CDriver *i2cp;
406 /**
407 * @brief I2C configuration associated to this LIS3MDL.
408 */
409 const I2CConfig *i2ccfg;
410 /**
411 * @brief LIS3MDL slave address
412 */
413 lis3mdl_sad_t slaveaddress;
414#endif /* LIS3MDL_USE_I2C */
415 /**
416 * @brief LIS3MDL compass subsystem initial sensitivity.
417 */
418 float *compsensitivity;
419 /**
420 * @brief LIS3MDL compass subsystem initial bias.
421 */
422 float *compbias;
423 /**
424 * @brief LIS3MDL compass subsystem full scale.
425 */
426 lis3mdl_comp_fs_t compfullscale;
427 /**
428 * @brief LIS3MDL compass subsystem output data rate.
429 */
430 lis3mdl_comp_odr_t compoutputdatarate;
431#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
432 /**
433 * @brief LIS3MDL compass subsystem low power mode configuration.
434 */
435 lis3mdl_comp_lp_t complowpowermode;
436 /**
437 * @brief LIS3MDL compass subsystem conversion mode.
438 */
439 lis3mdl_comp_md_t compconversionmode;
440 /**
441 * @brief LIS3MDL compass subsystem operation mode for X and Y axes.
442 */
443 lis3mdl_comp_omxy_t compoperationmodexy;
444 /**
445 * @brief LIS3MDL compass subsystem operation mode for Z axis.
446 */
447 lis3mdl_comp_omz_t compoperationmodez;
448 /**
449 * @brief LIS3MDL block data update.
450 */
451 lis3mdl_bdu_t blockdataupdate;
452 /**
453 * @brief LIS3MDL endianness.
454 */
455 lis3mdl_end_t endianness;
456#endif
457} LIS3MDLConfig;
458
459/**
460 * @brief @p LIS3MDL specific methods.
461 */
462#define _lis3msl_methods_alone \
463 /* Change full scale value of LIS3MDL compass subsystem.*/ \
464 msg_t (*comp_set_full_scale)(LIS3MDLDriver *devp, lis3mdl_comp_fs_t fs);
465
466/**
467 * @brief @p LIS3MDL specific methods with inherited ones.
468 */
469#define _lis3mdl_methods \
470 _base_object_methods \
471 _lis3msl_methods_alone
472
473/**
474 * @extends BaseCompassVMT
475 *
476 * @brief @p LIS3MDL virtual methods table.
477 */
478struct LIS3MDLVMT {
479 _lis3mdl_methods
480};
481
482/**
483 * @brief @p LIS3MDLDriver specific data.
484 */
485#define _lis3mdl_data \
486 _base_compass_data \
487 /* Driver state.*/ \
488 lis3mdl_state_t state; \
489 /* Current configuration data.*/ \
490 const LIS3MDLConfig *config; \
491 /* Compass subsystem axes number.*/ \
492 size_t compaxes; \
493 /* Compass subsystem current sensitivity.*/ \
494 float compsensitivity[LIS3MDL_COMP_NUMBER_OF_AXES]; \
495 /* Compass subsystem current bias.*/ \
496 float compbias[LIS3MDL_COMP_NUMBER_OF_AXES]; \
497 /* Compass subsystem current full scale value.*/ \
498 float compfullscale;
499
500/**
501 * @brief LIS3MDL 3-axis compass class.
502 */
503struct LIS3MDLDriver {
504 /** @brief Virtual Methods Table.*/
505 const struct LIS3MDLVMT *vmt;
506 /** @brief Base compass interface.*/
507 BaseCompass comp_if;
508 _lis3mdl_data
509};
510/** @} */
511
512/*===========================================================================*/
513/* Driver macros. */
514/*===========================================================================*/
515
516/**
517 * @brief Return the number of axes of the BaseCompass.
518 *
519 * @param[in] devp pointer to @p LIS3MDLDriver.
520 *
521 * @return the number of axes.
522 *
523 * @api
524 */
525#define lis3mdlCompassGetAxesNumber(devp) \
526 compassGetAxesNumber(&((devp)->comp_if))
527
528/**
529 * @brief Retrieves raw data from the BaseCompass.
530 * @note This data is retrieved from MEMS register without any algebraical
531 * manipulation.
532 * @note The axes array must be at least the same size of the
533 * BaseCompass axes number.
534 *
535 * @param[in] devp pointer to @p BaseCompass interface.
536 * @param[out] axes a buffer which would be filled with raw data.
537 *
538 * @return The operation status.
539 * @retval MSG_OK if the function succeeded.
540 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
541 * be retrieved using @p i2cGetErrors().
542 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
543 *
544 * @api
545 */
546#define lis3mdlCompassReadRaw(devp, axes) \
547 compassReadRaw(&((devp)->comp_if), axes)
548
549/**
550 * @brief Retrieves cooked data from the BaseCompass.
551 * @note This data is manipulated according to the formula
552 * cooked = (raw * sensitivity) - bias.
553 * @note Final data is expressed as G.
554 * @note The axes array must be at least the same size of the
555 * BaseCompass axes number.
556 *
557 * @param[in] devp pointer to @p BaseCompass interface.
558 * @param[out] axes a buffer which would be filled with cooked data.
559 *
560 * @return The operation status.
561 * @retval MSG_OK if the function succeeded.
562 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
563 * be retrieved using @p i2cGetErrors().
564 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
565 *
566 * @api
567 */
568#define lis3mdlCompassReadCooked(devp, axes) \
569 compassReadCooked(&((devp)->comp_if), axes)
570
571/**
572 * @brief Set bias values for the BaseCompass.
573 * @note Bias must be expressed as G.
574 * @note The bias buffer must be at least the same size of the
575 * BaseCompass axes number.
576 *
577 * @param[in] devp pointer to @p BaseCompass interface.
578 * @param[in] bp a buffer which contains biases.
579 *
580 * @return The operation status.
581 * @retval MSG_OK if the function succeeded.
582 *
583 * @api
584 */
585#define lis3mdlCompassSetBias(devp, bp) \
586 compassSetBias(&((devp)->comp_if), bp)
587
588/**
589 * @brief Reset bias values for the BaseCompass.
590 * @note Default biases value are obtained from device datasheet when
591 * available otherwise they are considered zero.
592 *
593 * @param[in] devp pointer to @p LIS3MDLDriver.
594 *
595 * @return The operation status.
596 * @retval MSG_OK if the function succeeded.
597 *
598 * @api
599 */
600#define lis3mdlCompassResetBias(devp) \
601 compassResetBias(&((devp)->comp_if))
602
603/**
604 * @brief Set sensitivity values for the BaseCompass.
605 * @note Sensitivity must be expressed as G/LSB.
606 * @note The sensitivity buffer must be at least the same size of the
607 * BaseCompass axes number.
608 *
609 * @param[in] devp pointer to @p LIS3MDLDriver.
610 * @param[in] sp a buffer which contains sensitivities.
611 *
612 * @return The operation status.
613 * @retval MSG_OK if the function succeeded.
614 *
615 * @api
616 */
617#define lis3mdlCompassSetSensitivity(devp, sp) \
618 compassSetSensitivity(&((devp)->comp_if), sp)
619
620/**
621 * @brief Reset sensitivity values for the BaseCompass.
622 * @note Default sensitivities value are obtained from device datasheet.
623 *
624 * @param[in] devp pointer to @p LIS3MDLDriver.
625 *
626 * @return The operation status.
627 * @retval MSG_OK if the function succeeded.
628 * @retval MSG_RESET otherwise.
629 *
630 * @api
631 */
632#define lis3mdlCompassResetSensitivity(devp) \
633 compassResetSensitivity(&((devp)->comp_if))
634
635/**
636 * @brief Changes the LIS3MDLDriver compass fullscale value.
637 * @note This function also rescale sensitivities and biases based on
638 * previous and next fullscale value.
639 * @note A recalibration is highly suggested after calling this function.
640 *
641 * @param[in] devp pointer to @p LIS3MDLDriver.
642 * @param[in] fs new fullscale value.
643 *
644 * @return The operation status.
645 * @retval MSG_OK if the function succeeded.
646 * @retval MSG_RESET otherwise.
647 *
648 * @api
649 */
650#define lis3mdlCompassSetFullScale(devp, fs) \
651 (devp)->vmt->comp_set_full_scale(devp, fs)
652
653/*===========================================================================*/
654/* External declarations. */
655/*===========================================================================*/
656
657#ifdef __cplusplus
658extern "C" {
659#endif
660 void lis3mdlObjectInit(LIS3MDLDriver *devp);
661 void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config);
662 void lis3mdlStop(LIS3MDLDriver *devp);
663#ifdef __cplusplus
664}
665#endif
666
667#endif /* _LIS3MDL_H_ */
668
669/** @} */
670
diff --git a/lib/chibios/os/ex/devices/ST/lis3mdl.mk b/lib/chibios/os/ex/devices/ST/lis3mdl.mk
new file mode 100644
index 000000000..941c34e17
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lis3mdl.mk
@@ -0,0 +1,10 @@
1# List of all the LIS3MDL device files.
2LIS3MDLSRC := $(CHIBIOS)/os/ex/devices/ST/lis3mdl.c
3
4# Required include directories
5LIS3MDLINC := $(CHIBIOS)/os/ex/include \
6 $(CHIBIOS)/os/ex/devices/ST
7
8# Shared variables
9ALLCSRC += $(LIS3MDLSRC)
10ALLINC += $(LIS3MDLINC) \ No newline at end of file
diff --git a/lib/chibios/os/ex/devices/ST/lps22hb.c b/lib/chibios/os/ex/devices/ST/lps22hb.c
new file mode 100644
index 000000000..d153a0d67
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lps22hb.c
@@ -0,0 +1,686 @@
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 lps22hb.c
23 * @brief LPS22HB MEMS interface module code.
24 *
25 * @addtogroup LPS22HB
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "lps22hb.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 (LPS22HB_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 *
54 * @param[in] i2cp pointer to the I2C interface
55 * @param[in] sad slave address without R bit
56 * @param[in] reg first sub-register address
57 * @param[out] rxbuf pointer to an output buffer
58 * @param[in] n number of consecutive register to read
59 * @return the operation status.
60 *
61 * @notapi
62 */
63static msg_t lps22hbI2CReadRegister(I2CDriver *i2cp, lps22hb_sad_t sad,
64 uint8_t reg, uint8_t* rxbuf, size_t n) {
65
66 return i2cMasterTransmitTimeout(i2cp, sad, &reg, 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 *
82 * @notapi
83 */
84#define lps22hbI2CWriteRegister(i2cp, sad, txbuf, n) \
85 i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0, \
86 TIME_INFINITE)
87#endif /* LPS22HB_USE_I2C */
88
89/**
90 * @brief Return the number of axes of the BaseBarometer.
91 *
92 * @param[in] ip pointer to @p BaseBarometer interface.
93 *
94 * @return the number of axes.
95 */
96static size_t baro_get_axes_number(void *ip) {
97 (void)ip;
98
99 return LPS22HB_BARO_NUMBER_OF_AXES;
100}
101
102/**
103 * @brief Retrieves raw data from the BaseBarometer.
104 * @note This data is retrieved from MEMS register without any algebraical
105 * manipulation.
106 * @note The axes array must be at least the same size of the
107 * BaseBarometer axes number.
108 *
109 * @param[in] ip pointer to @p BaseBarometer interface.
110 * @param[out] axes a buffer which would be filled with raw data.
111 *
112 * @return The operation status.
113 * @retval MSG_OK if the function succeeded.
114 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
115 * be retrieved using @p i2cGetErrors().
116 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
117 */
118static msg_t baro_read_raw(void *ip, int32_t axes[]) {
119 LPS22HBDriver* devp;
120 uint8_t buff[3];
121 msg_t msg;
122
123 osalDbgCheck((ip != NULL) && (axes != NULL));
124
125 /* Getting parent instance pointer.*/
126 devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
127
128 osalDbgAssert((devp->state == LPS22HB_READY),
129 "baro_read_raw(), invalid state");
130
131 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
132 "baro_read_raw(), channel not ready");
133
134#if LPS22HB_SHARED_I2C
135 i2cAcquireBus(devp->config->i2cp);
136 i2cStart(devp->config->i2cp,
137 devp->config->i2ccfg);
138#endif /* LPS22HB_SHARED_I2C */
139
140 msg = lps22hbI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
141 LPS22HB_AD_PRESS_OUT_XL, buff, 3);
142
143#if LPS22HB_SHARED_I2C
144 i2cReleaseBus(devp->config->i2cp);
145#endif /* LPS22HB_SHARED_I2C */
146
147 if(msg == MSG_OK) {
148 *axes = buff[0] + (buff[1] << 8) + (buff[2] << 16);
149 }
150 return msg;
151}
152
153/**
154 * @brief Retrieves cooked data from the BaseBarometer.
155 * @note This data is manipulated according to the formula
156 * cooked = (raw * sensitivity) - bias.
157 * @note Final data is expressed as hPa.
158 * @note The axes array must be at least the same size of the
159 * BaseBarometer axes number.
160 *
161 * @param[in] ip pointer to @p BaseBarometer interface.
162 * @param[out] axes a buffer which would be filled with cooked data.
163 *
164 * @return The operation status.
165 * @retval MSG_OK if the function succeeded.
166 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
167 * be retrieved using @p i2cGetErrors().
168 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
169 */
170static msg_t baro_read_cooked(void *ip, float axes[]) {
171 LPS22HBDriver* devp;
172 int32_t raw;
173 msg_t msg;
174
175 osalDbgCheck((ip != NULL) && (axes != NULL));
176
177 /* Getting parent instance pointer.*/
178 devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
179
180 osalDbgAssert((devp->state == LPS22HB_READY),
181 "baro_read_cooked(), invalid state");
182
183 msg = baro_read_raw(ip, &raw);
184
185 *axes = (raw * devp->barosensitivity) - devp->barobias;
186
187 return msg;
188}
189
190/**
191 * @brief Set bias values for the BaseBarometer.
192 * @note Bias must be expressed as hPa.
193 * @note The bias buffer must be at least the same size of the
194 * BaseBarometer axes number.
195 *
196 * @param[in] ip pointer to @p BaseBarometer interface.
197 * @param[in] bp a buffer which contains biases.
198 *
199 * @return The operation status.
200 * @retval MSG_OK if the function succeeded.
201 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
202 * be retrieved using @p i2cGetErrors().
203 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
204 */
205static msg_t baro_set_bias(void *ip, float *bp) {
206 LPS22HBDriver* devp;
207 msg_t msg = MSG_OK;
208
209 osalDbgCheck((ip != NULL) && (bp != NULL));
210
211 /* Getting parent instance pointer.*/
212 devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
213
214 osalDbgAssert((devp->state == LPS22HB_READY),
215 "baro_set_bias(), invalid state");
216
217 devp->barobias = *bp;
218 return msg;
219}
220
221/**
222 * @brief Reset bias values for the BaseBarometer.
223 * @note Default biases value are obtained from device datasheet when
224 * available otherwise they are considered zero.
225 *
226 * @param[in] ip pointer to @p BaseBarometer interface.
227 *
228 * @return The operation status.
229 * @retval MSG_OK if the function succeeded.
230 */
231static msg_t baro_reset_bias(void *ip) {
232 LPS22HBDriver* devp;
233 msg_t msg = MSG_OK;
234
235 osalDbgCheck(ip != NULL);
236
237 /* Getting parent instance pointer.*/
238 devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
239
240 osalDbgAssert((devp->state == LPS22HB_READY),
241 "baro_reset_bias(), invalid state");
242
243 devp->barobias = LPS22HB_BARO_SENS;
244 return msg;
245}
246
247/**
248 * @brief Set sensitivity values for the BaseBarometer.
249 * @note Sensitivity must be expressed as hPa/LSB.
250 * @note The sensitivity buffer must be at least the same size of the
251 * BaseBarometer axes number.
252 *
253 * @param[in] ip pointer to @p BaseBarometer interface.
254 * @param[in] sp a buffer which contains sensitivities.
255 *
256 * @return The operation status.
257 * @retval MSG_OK if the function succeeded.
258 */
259static msg_t baro_set_sensitivity(void *ip, float *sp) {
260 LPS22HBDriver* devp;
261 msg_t msg = MSG_OK;
262
263 osalDbgCheck((ip != NULL) && (sp != NULL));
264
265 /* Getting parent instance pointer.*/
266 devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
267
268 osalDbgAssert((devp->state == LPS22HB_READY),
269 "baro_set_sensitivity(), invalid state");
270
271 devp->barosensitivity = *sp;
272 return msg;
273}
274
275/**
276 * @brief Reset sensitivity values for the BaseBarometer.
277 * @note Default sensitivities value are obtained from device datasheet.
278 *
279 * @param[in] ip pointer to @p BaseBarometer interface.
280 *
281 * @return The operation status.
282 * @retval MSG_OK if the function succeeded.
283 */
284static msg_t baro_reset_sensitivity(void *ip) {
285 LPS22HBDriver* devp;
286 msg_t msg = MSG_OK;
287
288 osalDbgCheck(ip != NULL);
289
290 /* Getting parent instance pointer.*/
291 devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
292
293 osalDbgAssert((devp->state == LPS22HB_READY),
294 "baro_reset_sensitivity(), invalid state");
295
296 devp->barosensitivity = LPS22HB_BARO_SENS;
297 return msg;
298}
299
300/**
301 * @brief Return the number of axes of the BaseThermometer.
302 *
303 * @param[in] ip pointer to @p BaseThermometer interface.
304 *
305 * @return the number of axes.
306 */
307static size_t thermo_get_axes_number(void *ip) {
308 (void)ip;
309
310 return LPS22HB_THERMO_NUMBER_OF_AXES;
311}
312
313/**
314 * @brief Retrieves raw data from the BaseThermometer.
315 * @note This data is retrieved from MEMS register without any algebraical
316 * manipulation.
317 * @note The axes array must be at least the same size of the
318 * BaseThermometer axes number.
319 *
320 * @param[in] ip pointer to @p BaseThermometer interface.
321 * @param[out] axes a buffer which would be filled with raw data.
322 *
323 * @return The operation status.
324 * @retval MSG_OK if the function succeeded.
325 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
326 * be retrieved using @p i2cGetErrors().
327 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
328 */
329static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
330 LPS22HBDriver* devp;
331 int16_t tmp;
332 uint8_t buff[2];
333 msg_t msg;
334
335 osalDbgCheck((ip != NULL) && (axes != NULL));
336
337 /* Getting parent instance pointer.*/
338 devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
339
340 osalDbgAssert((devp->state == LPS22HB_READY),
341 "thermo_read_raw(), invalid state");
342
343 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
344 "thermo_read_raw(), channel not ready");
345
346#if LPS22HB_SHARED_I2C
347 i2cAcquireBus(devp->config->i2cp);
348 i2cStart(devp->config->i2cp,
349 devp->config->i2ccfg);
350#endif /* LPS22HB_SHARED_I2C */
351
352 msg = lps22hbI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
353 LPS22HB_AD_TEMP_OUT_L, buff, 2);
354
355#if LPS22HB_SHARED_I2C
356 i2cReleaseBus(devp->config->i2cp);
357#endif /* LPS22HB_SHARED_I2C */
358
359 if (msg == MSG_OK) {
360 tmp = buff[0] + (buff[1] << 8);
361 *axes = (int32_t)tmp;
362 }
363 return msg;
364}
365
366/**
367 * @brief Retrieves cooked data from the BaseThermometer.
368 * @note This data is manipulated according to the formula
369 * cooked = (raw * sensitivity) - bias.
370 * @note Final data is expressed as °C.
371 * @note The axes array must be at least the same size of the
372 * BaseThermometer axes number.
373 *
374 * @param[in] ip pointer to @p BaseThermometer interface.
375 * @param[out] axis a buffer which would be filled with cooked data.
376 *
377 * @return The operation status.
378 * @retval MSG_OK if the function succeeded.
379 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
380 * be retrieved using @p i2cGetErrors().
381 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
382 */
383static msg_t thermo_read_cooked(void *ip, float* axis) {
384 LPS22HBDriver* devp;
385 int32_t raw;
386 msg_t msg;
387
388 osalDbgCheck((ip != NULL) && (axis != NULL));
389
390 /* Getting parent instance pointer.*/
391 devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
392
393 osalDbgAssert((devp->state == LPS22HB_READY),
394 "thermo_read_cooked(), invalid state");
395
396 msg = thermo_read_raw(devp, &raw);
397
398 *axis = (raw * devp->thermosensitivity) - devp->thermobias;
399
400 return msg;
401}
402
403/**
404 * @brief Set bias values for the BaseThermometer.
405 * @note Bias must be expressed as °C.
406 * @note The bias buffer must be at least the same size of the
407 * BaseThermometer axes number.
408 *
409 * @param[in] ip pointer to @p BaseThermometer interface.
410 * @param[in] bp a buffer which contains biases.
411 *
412 * @return The operation status.
413 * @retval MSG_OK if the function succeeded.
414 */
415static msg_t thermo_set_bias(void *ip, float *bp) {
416 LPS22HBDriver* devp;
417 msg_t msg = MSG_OK;
418
419 osalDbgCheck((ip != NULL) && (bp != NULL));
420
421 /* Getting parent instance pointer.*/
422 devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
423
424 osalDbgAssert((devp->state == LPS22HB_READY),
425 "thermo_set_bias(), invalid state");
426
427 devp->thermobias = *bp;
428
429 return msg;
430}
431
432/**
433 * @brief Reset bias values for the BaseThermometer.
434 * @note Default biases value are obtained from device datasheet when
435 * available otherwise they are considered zero.
436 *
437 * @param[in] ip pointer to @p BaseThermometer interface.
438 *
439 * @return The operation status.
440 * @retval MSG_OK if the function succeeded.
441 */
442static msg_t thermo_reset_bias(void *ip) {
443 LPS22HBDriver* devp;
444 msg_t msg = MSG_OK;
445
446 osalDbgCheck(ip != NULL);
447
448 /* Getting parent instance pointer.*/
449 devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
450
451 osalDbgAssert((devp->state == LPS22HB_READY),
452 "thermo_reset_bias(), invalid state");
453
454 devp->thermobias = LPS22HB_THERMO_BIAS;
455
456 return msg;
457}
458
459/**
460 * @brief Set sensitivity values for the BaseThermometer.
461 * @note Sensitivity must be expressed as °C/LSB.
462 * @note The sensitivity buffer must be at least the same size of the
463 * BaseThermometer axes number.
464 *
465 * @param[in] ip pointer to @p BaseThermometer interface.
466 * @param[in] sp a buffer which contains sensitivities.
467 *
468 * @return The operation status.
469 * @retval MSG_OK if the function succeeded.
470 */
471static msg_t thermo_set_sensitivity(void *ip, float *sp) {
472 LPS22HBDriver* devp;
473 msg_t msg = MSG_OK;
474
475 osalDbgCheck((ip != NULL) && (sp != NULL));
476
477 /* Getting parent instance pointer.*/
478 devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
479
480 osalDbgAssert((devp->state == LPS22HB_READY),
481 "thermo_set_sensitivity(), invalid state");
482
483 devp->thermosensitivity = *sp;
484
485 return msg;
486}
487
488/**
489 * @brief Reset sensitivity values for the BaseThermometer.
490 * @note Default sensitivities value are obtained from device datasheet.
491 *
492 * @param[in] ip pointer to @p BaseThermometer interface.
493 *
494 * @return The operation status.
495 * @retval MSG_OK if the function succeeded.
496 */
497static msg_t thermo_reset_sensitivity(void *ip) {
498 LPS22HBDriver* devp;
499 msg_t msg = MSG_OK;
500
501 osalDbgCheck(ip != NULL);
502
503 /* Getting parent instance pointer.*/
504 devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
505
506 osalDbgAssert((devp->state == LPS22HB_READY),
507 "thermo_reset_sensitivity(), invalid state");
508
509 devp->thermosensitivity = LPS22HB_THERMO_SENS;
510
511 return msg;
512}
513
514static const struct LPS22HBVMT vmt_device = {
515 (size_t)0
516};
517
518static const struct BaseBarometerVMT vmt_barometer = {
519 sizeof(struct LPS22HBVMT*),
520 baro_get_axes_number, baro_read_raw, baro_read_cooked,
521 baro_set_bias, baro_reset_bias, baro_set_sensitivity,
522 baro_reset_sensitivity
523};
524
525static const struct BaseThermometerVMT vmt_thermometer = {
526 sizeof(struct LPS22HBVMT*) + sizeof(BaseBarometer),
527 thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
528 thermo_set_bias, thermo_reset_bias, thermo_set_sensitivity,
529 thermo_reset_sensitivity
530};
531
532/*===========================================================================*/
533/* Driver exported functions. */
534/*===========================================================================*/
535
536/**
537 * @brief Initializes an instance.
538 *
539 * @param[out] devp pointer to the @p LPS22HBDriver object
540 *
541 * @init
542 */
543void lps22hbObjectInit(LPS22HBDriver *devp) {
544
545 devp->vmt = &vmt_device;
546 devp->baro_if.vmt = &vmt_barometer;
547 devp->thermo_if.vmt = &vmt_thermometer;
548
549 devp->config = NULL;
550
551 devp->baroaxes = LPS22HB_BARO_NUMBER_OF_AXES;
552 devp->thermoaxes = LPS22HB_THERMO_NUMBER_OF_AXES;
553
554 devp->state = LPS22HB_STOP;
555}
556
557/**
558 * @brief Configures and activates LPS22HB Complex Driver peripheral.
559 *
560 * @param[in] devp pointer to the @p LPS22HBDriver object
561 * @param[in] config pointer to the @p LPS22HBConfig object
562 *
563 * @api
564 */
565void lps22hbStart(LPS22HBDriver *devp, const LPS22HBConfig *config) {
566 uint8_t cr[2];
567 osalDbgCheck((devp != NULL) && (config != NULL));
568
569 osalDbgAssert((devp->state == LPS22HB_STOP) || (devp->state == LPS22HB_READY),
570 "lps22hbStart(), invalid state");
571
572 devp->config = config;
573
574 /* Enabling register auto-increment.*/
575 /* Control register 1 configuration block.*/
576 {
577 cr[0] = LPS22HB_AD_CTRL_REG2;
578 cr[1] = LPS22HB_CTRL_REG2_IF_ADD_INC;
579 }
580#if LPS22HB_SHARED_I2C
581 i2cAcquireBus(devp->config->i2cp);
582#endif /* LPS22HB_SHARED_I2C */
583
584 i2cStart(devp->config->i2cp, devp->config->i2ccfg);
585 lps22hbI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
586 cr, 1);
587
588#if LPS22HB_SHARED_I2C
589 i2cReleaseBus((devp)->config->i2cp);
590#endif /* LPS22HB_SHARED_I2C */
591
592 /* Control register 1 configuration block.*/
593 {
594 cr[0] = LPS22HB_AD_CTRL_REG1;
595 cr[1] = devp->config->outputdatarate;
596#if LPS22HB_USE_ADVANCED || defined(__DOXYGEN__)
597 cr[1] |= devp->config->blockdataupdate;
598 cr[1] |= devp->config->lowpass_filter;
599#endif
600 }
601
602#if LPS22HB_SHARED_I2C
603 i2cAcquireBus((devp)->config->i2cp);
604 i2cStart((devp)->config->i2cp,
605 (devp)->config->i2ccfg);
606#endif /* LPS22HB_SHARED_I2C */
607
608 lps22hbI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, cr, 1);
609
610#if LPS22HB_SHARED_I2C
611 i2cReleaseBus((devp)->config->i2cp);
612#endif /* LPS22HB_SHARED_I2C */
613
614 if(devp->config->barosensitivity == NULL) {
615 devp->barosensitivity = LPS22HB_BARO_SENS;
616 }
617 else{
618 /* Taking barometer sensitivity from user configurations */
619 devp->barosensitivity = *(devp->config->barosensitivity);
620 }
621
622 if(devp->config->barobias == NULL) {
623 devp->barobias = LPS22HB_BARO_BIAS;
624 }
625 else{
626 /* Taking barometer bias from user configurations */
627 devp->barobias = *(devp->config->barobias);
628 }
629
630 if(devp->config->thermosensitivity == NULL) {
631 devp->thermosensitivity = LPS22HB_THERMO_SENS;
632 }
633 else{
634 /* Taking thermometer sensitivity from user configurations */
635 devp->thermosensitivity = *(devp->config->thermosensitivity);
636 }
637
638 if(devp->config->thermobias == NULL) {
639 devp->thermobias = LPS22HB_THERMO_BIAS;
640 }
641 else{
642 /* Taking thermometer bias from user configurations */
643 devp->thermobias = *(devp->config->thermobias);
644 }
645
646 /* This is the Barometer transient recovery time */
647 osalThreadSleepMilliseconds(5);
648
649 devp->state = LPS22HB_READY;
650}
651
652/**
653 * @brief Deactivates the LPS22HB Complex Driver peripheral.
654 *
655 * @param[in] devp pointer to the @p LPS22HBDriver object
656 *
657 * @api
658 */
659void lps22hbStop(LPS22HBDriver *devp) {
660 uint8_t cr[2];
661
662 osalDbgCheck(devp != NULL);
663
664 osalDbgAssert((devp->state == LPS22HB_STOP) || (devp->state == LPS22HB_READY),
665 "lps22hbStop(), invalid state");
666
667 if (devp->state == LPS22HB_READY) {
668#if LPS22HB_SHARED_I2C
669 i2cAcquireBus((devp)->config->i2cp);
670 i2cStart((devp)->config->i2cp,
671 (devp)->config->i2ccfg);
672#endif /* LPS22HB_SHARED_I2C */
673
674 cr[0] = LPS22HB_AD_CTRL_REG1;
675 cr[1] = 0;
676 lps22hbI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
677 cr, 1);
678
679 i2cStop((devp)->config->i2cp);
680#if LPS22HB_SHARED_I2C
681 i2cReleaseBus((devp)->config->i2cp);
682#endif /* LPS22HB_SHARED_I2C */
683 }
684 devp->state = LPS22HB_STOP;
685}
686/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/lps22hb.h b/lib/chibios/os/ex/devices/ST/lps22hb.h
new file mode 100644
index 000000000..47cd5123b
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lps22hb.h
@@ -0,0 +1,724 @@
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 lps22hb.h
23 * @brief LPS22HB MEMS interface module header.
24 *
25 * @addtogroup LPS22HB
26 * @ingroup EX_ST
27 * @{
28 */
29#ifndef _LPS22HB_H_
30#define _LPS22HB_H_
31
32#include "ex_barometer.h"
33#include "ex_thermometer.h"
34
35/*===========================================================================*/
36/* Driver constants. */
37/*===========================================================================*/
38
39/**
40 * @name Version identification
41 * @{
42 */
43/**
44 * @brief LPS22HB driver version string.
45 */
46#define EX_LPS22HB_VERSION "1.0.2"
47
48/**
49 * @brief LPS22HB driver version major number.
50 */
51#define EX_LPS22HB_MAJOR 1
52
53/**
54 * @brief LPS22HB driver version minor number.
55 */
56#define EX_LPS22HB_MINOR 0
57
58/**
59 * @brief LPS22HB driver version patch number.
60 */
61#define EX_LPS22HB_PATCH 2
62/** @} */
63
64/**
65 * @brief LPS22HB barometer subsystem characteristics.
66 * @note Sensitivity is expressed as hPa/LSB whereas hPa stand for
67 * hectopascal.
68 * @note Bias is expressed as hPa.
69 *
70 * @{
71 */
72#define LPS22HB_BARO_NUMBER_OF_AXES 1U
73
74#define LPS22HB_BARO_SENS 0.00024414f
75#define LPS22HB_BARO_BIAS 0.0f
76/** @} */
77
78/**
79 * @brief LPS22HB thermometer subsystem characteristics.
80 * @note Sensitivity is expressed as �C/LSB.
81 * @note Bias is expressed as �C.
82 *
83 * @{
84 */
85#define LPS22HB_THERMO_NUMBER_OF_AXES 1U
86
87#define LPS22HB_THERMO_SENS 0.01f
88#define LPS22HB_THERMO_BIAS 0.0f
89/** @} */
90
91/**
92 * @name LPS22HB communication interfaces related bit masks
93 * @{
94 */
95#define LPS22HB_DI_MASK 0xFF
96#define LPS22HB_DI(n) (1 << n)
97#define LPS22HB_AD_MASK 0x3F
98#define LPS22HB_AD(n) (1 << n)
99#define LPS22HB_MS (1 << 6)
100#define LPS22HB_RW (1 << 7)
101
102#define LPS22HB_SUB_MS (1 << 7)
103/** @} */
104
105/**
106 * @name LPS22HB register addresses
107 * @{
108 */
109#define LPS22HB_AD_INT_CFG 0x0B
110#define LPS22HB_AD_THS_P_L 0x0C
111#define LPS22HB_AD_THS_P_H 0x0D
112#define LPS22HB_AD_WHO_AM_I 0x0F
113#define LPS22HB_AD_CTRL_REG1 0x10
114#define LPS22HB_AD_CTRL_REG2 0x11
115#define LPS22HB_AD_CTRL_REG3 0x12
116#define LPS22HB_AD_FIFO_CTRL 0x14
117#define LPS22HB_AD_REF_P_XL 0x15
118#define LPS22HB_AD_REF_P_L 0x16
119#define LPS22HB_AD_REF_P_H 0x17
120#define LPS22HB_AD_RPDS_L 0x18
121#define LPS22HB_AD_RPDS_H 0x19
122#define LPS22HB_AD_RES_CONF 0x1A
123#define LPS22HB_AD_INT_SRC 0x25
124#define LPS22HB_AD_FIFO_SRC 0x26
125#define LPS22HB_AD_STATUS_REG 0x27
126#define LPS22HB_AD_PRESS_OUT_XL 0x28
127#define LPS22HB_AD_PRESS_OUT_L 0x29
128#define LPS22HB_AD_PRESS_OUT_H 0x2A
129#define LPS22HB_AD_TEMP_OUT_L 0x2B
130#define LPS22HB_AD_TEMP_OUT_H 0x2C
131#define LPS22HB_AD_LPFP_RES 0x33
132/** @} */
133
134/**
135 * @name LPS22HB_INT_CFG register bits definitions
136 * @{
137 */
138#define LPS22HB_INT_CFG_MASK 0xFF
139#define LPS22HB_INT_CFG_PHE (1 << 0)
140#define LPS22HB_INT_CFG_PLE (1 << 1)
141#define LPS22HB_INT_CFG_LIR (1 << 2)
142#define LPS22HB_INT_CFG_DIFF_EN (1 << 3)
143#define LPS22HB_INT_CFG_RESET_AZ (1 << 4)
144#define LPS22HB_INT_CFG_AUTOZERO (1 << 5)
145#define LPS22HB_INT_CFG_RESET_ARP (1 << 6)
146#define LPS22HB_INT_CFG_AUTORIFP (1 << 7)
147/** @} */
148
149/**
150 * @name LPS22HB_CTRL_REG1 register bits definitions
151 * @{
152 */
153#define LPS22HB_CTRL_REG1_MASK 0x7F
154#define LPS22HB_CTRL_REG1_SIM (1 << 0)
155#define LPS22HB_CTRL_REG1_BDU (1 << 1)
156#define LPS22HB_CTRL_REG1_LPFP_CFG (1 << 2)
157#define LPS22HB_CTRL_REG1_LPFP_EN (1 << 3)
158#define LPS22HB_CTRL_REG1_ODR0 (1 << 4)
159#define LPS22HB_CTRL_REG1_ODR1 (1 << 5)
160#define LPS22HB_CTRL_REG1_ODR2 (1 << 6)
161/** @} */
162
163/**
164 * @name LPS22HB_CTRL_REG2 register bits definitions
165 * @{
166 */
167#define LPS22HB_CTRL_REG2_MASK 0xFD
168#define LPS22HB_CTRL_REG2_ONE_SHOT (1 << 0)
169#define LPS22HB_CTRL_REG2_SWRESET (1 << 2)
170#define LPS22HB_CTRL_REG2_I2C_DIS (1 << 3)
171#define LPS22HB_CTRL_REG2_IF_ADD_INC (1 << 4)
172#define LPS22HB_CTRL_REG2_STOP_ON_FTH (1 << 5)
173#define LPS22HB_CTRL_REG2_FIFO_EN (1 << 6)
174#define LPS22HB_CTRL_REG2_BOOT (1 << 7)
175/** @} */
176
177/**
178 * @name LPS22HB_CTRL_REG3 register bits definitions
179 * @{
180 */
181#define LPS22HB_CTRL_REG3_MASK 0xFF
182#define LPS22HB_CTRL_REG3_INT_S1 (1 << 0)
183#define LPS22HB_CTRL_REG3_INT_S2 (1 << 1)
184#define LPS22HB_CTRL_REG3_DRDY (1 << 2)
185#define LPS22HB_CTRL_REG3_F_OVR (1 << 3)
186#define LPS22HB_CTRL_REG3_F_FTH (1 << 4)
187#define LPS22HB_CTRL_REG3_F_FSS5 (1 << 5)
188#define LPS22HB_CTRL_REG3_PP_OD (1 << 6)
189#define LPS22HB_CTRL_REG3_INT_H_L (1 << 7)
190/** @} */
191
192/**
193 * @name LPS22HB_INT_SRC register bits definitions
194 * @{
195 */
196#define LPS22HB_INT_SRC_MASK 0x87
197#define LPS22HB_INT_SRC_PH (1 << 0)
198#define LPS22HB_INT_SRC_PL (1 << 1)
199#define LPS22HB_INT_SRC_IA (1 << 2)
200#define LPS22HB_INT_SRC_BOOT_STATUS (1 << 8)
201/** @} */
202
203/*===========================================================================*/
204/* Driver pre-compile time settings. */
205/*===========================================================================*/
206
207/**
208 * @name Configuration options
209 * @{
210 */
211/**
212 * @brief LPS22HB SPI interface switch.
213 * @details If set to @p TRUE the support for SPI is included.
214 * @note The default is @p FALSE.
215 */
216#if !defined(LPS22HB_USE_SPI) || defined(__DOXYGEN__)
217#define LPS22HB_USE_SPI FALSE
218#endif
219
220/**
221 * @brief LPS22HB shared SPI switch.
222 * @details If set to @p TRUE the device acquires SPI bus ownership
223 * on each transaction.
224 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
225 */
226#if !defined(LPS22HB_SHARED_SPI) || defined(__DOXYGEN__)
227#define LPS22HB_SHARED_SPI FALSE
228#endif
229
230/**
231 * @brief LPS22HB I2C interface switch.
232 * @details If set to @p TRUE the support for I2C is included.
233 * @note The default is @p TRUE.
234 */
235#if !defined(LPS22HB_USE_I2C) || defined(__DOXYGEN__)
236#define LPS22HB_USE_I2C TRUE
237#endif
238
239/**
240 * @brief LPS22HB shared I2C switch.
241 * @details If set to @p TRUE the device acquires I2C bus ownership
242 * on each transaction.
243 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
244 */
245#if !defined(LPS22HB_SHARED_I2C) || defined(__DOXYGEN__)
246#define LPS22HB_SHARED_I2C FALSE
247#endif
248
249/**
250 * @brief LPS22HB advanced configurations switch.
251 * @details If set to @p TRUE more configurations are available.
252 * @note The default is @p FALSE.
253 */
254#if !defined(LPS22HB_USE_ADVANCED) || defined(__DOXYGEN__)
255#define LPS22HB_USE_ADVANCED FALSE
256#endif
257/** @} */
258
259/*===========================================================================*/
260/* Derived constants and error checks. */
261/*===========================================================================*/
262
263#if !(LPS22HB_USE_SPI ^ LPS22HB_USE_I2C)
264#error "LPS22HB_USE_SPI and LPS22HB_USE_I2C cannot be both true or both false"
265#endif
266
267#if LPS22HB_USE_SPI && !HAL_USE_SPI
268#error "LPS22HB_USE_SPI requires HAL_USE_SPI"
269#endif
270
271#if LPS22HB_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
272#error "LPS22HB_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
273#endif
274
275#if LPS22HB_USE_I2C && !HAL_USE_I2C
276#error "LPS22HB_USE_I2C requires HAL_USE_I2C"
277#endif
278
279#if LPS22HB_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
280#error "LPS22HB_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
281#endif
282
283/*
284 * CHTODO: Add support for LPS22HB over SPI.
285 */
286#if LPS22HB_USE_SPI
287#error "LPS22HB over SPI still not supported"
288#endif
289
290/*===========================================================================*/
291/* Driver data structures and types. */
292/*===========================================================================*/
293
294/**
295 * @name LPS22HB data structures and types.
296 * @{
297 */
298/**
299 * @brief Structure representing a LPS22HB driver.
300 */
301typedef struct LPS22HBDriver LPS22HBDriver;
302
303/**
304 * @brief LPS22HB slave address
305 */
306typedef enum {
307 LPS22HB_SAD_GND = 0x5C, /**< Slave Address when SA0 is to GND */
308 LPS22HB_SAD_VCC = 0x5D /**< Slave Address when SA0 is to VCC */
309}lps22hb_sad_t;
310
311/**
312 * @brief LPS22HB output data rate and bandwidth.
313 */
314typedef enum {
315 LPS22HB_ODR_PD = 0x00, /**< Power down. */
316 LPS22HB_ODR_1HZ = 0x10, /**< Output data rate 1 Hz. */
317 LPS22HB_ODR_10HZ = 0x20, /**< Output data rate 10 Hz. */
318 LPS22HB_ODR_25HZ = 0x30, /**< Output data rate 25 Hz. */
319 LPS22HB_ODR_50HZ = 0x40, /**< Output data rate 50 Hz. */
320 LPS22HB_ODR_75HZ = 0x50 /**< Output data rate 75 Hz. */
321}lps22hb_odr_t;
322
323/**
324 * @brief LPS22HB pressure resolution.
325 */
326typedef enum {
327 LPS22HB_LP_DISABLED = 0x00, /**< LP Filter disabled. */
328 LPS22HB_LP_ODR_9 = 0x08, /**< LP Filter enabled. Cut-off ORD/9. */
329 LPS22HB_LP_ODR_20 = 0x0C /**< LP Filter enabled. Cut-off ORD/20. */
330}lps22hb_lp_t;
331
332/**
333 * @brief LPS22HB block data update.
334 */
335typedef enum {
336 LPS22HB_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
337 LPS22HB_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
338}lps22hb_bdu_t;
339
340/**
341 * @brief Driver state machine possible states.
342 */
343typedef enum {
344 LPS22HB_UNINIT = 0, /**< Not initialized. */
345 LPS22HB_STOP = 1, /**< Stopped. */
346 LPS22HB_READY = 2, /**< Ready. */
347} lps22hb_state_t;
348
349/**
350 * @brief LPS22HB configuration structure.
351 */
352typedef struct {
353
354#if LPS22HB_USE_SPI || defined(__DOXYGEN__)
355 /**
356 * @brief SPI driver associated to this LPS22HB.
357 */
358 SPIDriver *spip;
359 /**
360 * @brief SPI configuration associated to this LPS22HB.
361 */
362 const SPIConfig *spicfg;
363#endif /* LPS22HB_USE_SPI */
364#if LPS22HB_USE_I2C || defined(__DOXYGEN__)
365 /**
366 * @brief I2C driver associated to this LPS22HB.
367 */
368 I2CDriver *i2cp;
369 /**
370 * @brief I2C configuration associated to this LPS22HB.
371 */
372 const I2CConfig *i2ccfg;
373 /**
374 * @brief LPS22HB slave address
375 */
376 lps22hb_sad_t slaveaddress;
377#endif /* LPS22HB_USE_I2C */
378 /**
379 * @brief LPS22HB barometer subsystem initial sensitivity.
380 */
381 float *barosensitivity;
382 /**
383 * @brief LPS22HB barometer subsystem initial bias.
384 */
385 float *barobias;
386 /**
387 * @brief LPS22HB thermometer subsystem initial sensitivity.
388 */
389 float *thermosensitivity;
390 /**
391 * @brief LPS22HB thermometer subsystem initial bias.
392 */
393 float *thermobias;
394 /**
395 * @brief LPS22HB output data rate selection.
396 */
397 lps22hb_odr_t outputdatarate;
398#if LPS22HB_USE_ADVANCED || defined(__DOXYGEN__)
399 /**
400 * @brief LPS22HB block data update.
401 */
402 lps22hb_bdu_t blockdataupdate;
403 /**
404 * @brief LPS22HB barometer subsystem resolution.
405 */
406 lps22hb_lp_t lowpass_filter;
407#endif
408} LPS22HBConfig;
409
410/**
411 * @brief @p LPS22HB specific methods.
412 * @note No methods so far, just a common ancestor interface.
413 */
414#define _lps22hb_methods_alone
415
416/**
417 * @brief @p LPS22HB specific methods with inherited ones.
418 */
419#define _lps22hb_methods \
420 _base_object_methods \
421 _lps22hb_methods_alone
422
423/**
424 * @extends BaseObjectVMT
425 *
426 * @brief @p LPS22HB virtual methods table.
427 */
428struct LPS22HBVMT {
429 _lps22hb_methods
430};
431
432/**
433 * @brief @p LPS22HBDriver specific data.
434 */
435#define _lps22hb_data \
436 /* Driver state.*/ \
437 lps22hb_state_t state; \
438 /* Current configuration data.*/ \
439 const LPS22HBConfig *config; \
440 /* Barometer subsystem axes number.*/ \
441 size_t baroaxes; \
442 /* Barometer subsystem current sensitivity.*/ \
443 float barosensitivity; \
444 /* Barometer subsystem current bias .*/ \
445 float barobias; \
446 /* Thermometer subsystem axes number.*/ \
447 size_t thermoaxes; \
448 /* Thermometer subsystem current sensitivity.*/ \
449 float thermosensitivity; \
450 /* Thermometer subsystem current bias.*/ \
451 float thermobias;
452
453/**
454 * @brief LPS22HB 2-axis barometer/thermometer class.
455 */
456struct LPS22HBDriver {
457 /** @brief Virtual Methods Table.*/
458 const struct LPS22HBVMT *vmt;
459 /** @brief Base barometer interface.*/
460 BaseBarometer baro_if;
461 /** @brief Base thermometer interface.*/
462 BaseThermometer thermo_if;
463 _lps22hb_data
464};
465/** @} */
466
467/*===========================================================================*/
468/* Driver macros. */
469/*===========================================================================*/
470
471/**
472 * @brief Return the number of axes of the BaseBarometer.
473 *
474 * @param[in] devp pointer to @p LPS22HBDriver.
475 *
476 * @return the number of axes.
477 *
478 * @api
479 */
480#define lps22hbBarometerGetAxesNumber(devp) \
481 barometerGetAxesNumber(&((devp)->baro_if))
482
483/**
484 * @brief Retrieves raw data from the BaseBarometer.
485 * @note This data is retrieved from MEMS register without any algebraical
486 * manipulation.
487 * @note The axes array must be at least the same size of the
488 * BaseBarometer axes number.
489 *
490 * @param[in] devp pointer to @p LPS22HBDriver.
491 * @param[out] axes a buffer which would be filled with raw data.
492 *
493 * @return The operation status.
494 * @retval MSG_OK if the function succeeded.
495 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
496 * be retrieved using @p i2cGetErrors().
497 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
498 *
499 * @api
500 */
501#define lps22hbBarometerReadRaw(devp, axes) \
502 barometerReadRaw(&((devp)->baro_if), axes)
503
504/**
505 * @brief Retrieves cooked data from the BaseBarometer.
506 * @note This data is manipulated according to the formula
507 * cooked = (raw * sensitivity) - bias.
508 * @note Final data is expressed as hPa.
509 * @note The axes array must be at least the same size of the
510 * BaseBarometer axes number.
511 *
512 * @param[in] devp pointer to @p LPS22HBDriver.
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 * @api
522 */
523#define lps22hbBarometerReadCooked(devp, axes) \
524 barometerReadCooked(&((devp)->baro_if), axes)
525
526/**
527 * @brief Set bias values for the BaseBarometer.
528 * @note Bias must be expressed as hPa.
529 * @note The bias buffer must be at least the same size of the
530 * BaseBarometer axes number.
531 *
532 * @param[in] devp pointer to @p LPS22HBDriver.
533 * @param[in] bp a buffer which contains biases.
534 *
535 * @return The operation status.
536 * @retval MSG_OK if the function succeeded.
537 *
538 * @api
539 */
540#define lps22hbBarometerSetBias(devp, bp) \
541 barometerSetBias(&((devp)->baro_if), bp)
542
543/**
544 * @brief Reset bias values for the BaseBarometer.
545 * @note Default biases value are obtained from device datasheet when
546 * available otherwise they are considered zero.
547 *
548 * @param[in] devp pointer to @p LPS22HBDriver.
549 *
550 * @return The operation status.
551 * @retval MSG_OK if the function succeeded.
552 *
553 * @api
554 */
555#define lps22hbBarometerResetBias(devp) \
556 barometerResetBias(&((devp)->baro_if))
557
558/**
559 * @brief Set sensitivity values for the BaseBarometer.
560 * @note Sensitivity must be expressed as hPa/LSB.
561 * @note The sensitivity buffer must be at least the same size of the
562 * BaseBarometer axes number.
563 *
564 * @param[in] devp pointer to @p LPS22HBDriver.
565 * @param[in] sp a buffer which contains sensitivities.
566 *
567 * @return The operation status.
568 * @retval MSG_OK if the function succeeded.
569 *
570 * @api
571 */
572#define lps22hbBarometerSetSensitivity(devp, sp) \
573 barometerSetSensitivity(&((devp)->baro_if), sp)
574
575/**
576 * @brief Reset sensitivity values for the BaseBarometer.
577 * @note Default sensitivities value are obtained from device datasheet.
578 *
579 * @param[in] devp pointer to @p LPS22HBDriver.
580 *
581 * @return The operation status.
582 * @retval MSG_OK if the function succeeded.
583 *
584 * @api
585 */
586#define lps22hbBarometerResetSensitivity(devp) \
587 barometerResetSensitivity(&((devp)->baro_if))
588
589/**
590 * @brief Return the number of axes of the BaseThermometer.
591 *
592 * @param[in] devp pointer to @p LPS22HBDriver.
593 *
594 * @return the number of axes.
595 *
596 * @api
597 */
598#define lps22hbThermometerGetAxesNumber(devp) \
599 thermometerGetAxesNumber(&((devp)->thermo_if))
600
601/**
602 * @brief Retrieves raw data from the BaseThermometer.
603 * @note This data is retrieved from MEMS register without any algebraical
604 * manipulation.
605 * @note The axes array must be at least the same size of the
606 * BaseThermometer axes number.
607 *
608 * @param[in] devp pointer to @p LPS22HBDriver.
609 * @param[out] axes a buffer which would be filled with raw data.
610 *
611 * @return The operation status.
612 * @retval MSG_OK if the function succeeded.
613 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
614 * be retrieved using @p i2cGetErrors().
615 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
616 *
617 * @api
618 */
619#define lps22hbThermometerReadRaw(devp, axes) \
620 thermometerReadRaw(&((devp)->thermo_if), axes)
621
622/**
623 * @brief Retrieves cooked data from the BaseThermometer.
624 * @note This data is manipulated according to the formula
625 * cooked = (raw * sensitivity) - bias.
626 * @note Final data is expressed as °C.
627 * @note The axes array must be at least the same size of the
628 * BaseThermometer axes number.
629 *
630 * @param[in] devp pointer to @p LPS22HBDriver.
631 * @param[out] axes a buffer which would be filled with cooked data.
632 *
633 * @return The operation status.
634 * @retval MSG_OK if the function succeeded.
635 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
636 * be retrieved using @p i2cGetErrors().
637 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
638 *
639 * @api
640 */
641#define lps22hbThermometerReadCooked(devp, axes) \
642 thermometerReadCooked(&((devp)->thermo_if), axes)
643
644/**
645 * @brief Set bias values for the BaseThermometer.
646 * @note Bias must be expressed as °C.
647 * @note The bias buffer must be at least the same size of the
648 * BaseThermometer axes number.
649 *
650 * @param[in] devp pointer to @p LPS22HBDriver.
651 * @param[in] bp a buffer which contains biases.
652 *
653 * @return The operation status.
654 * @retval MSG_OK if the function succeeded.
655 *
656 * @api
657 */
658#define lps22hbThermometerSetBias(devp, bp) \
659 thermometerSetBias(&((devp)->thermo_if), bp)
660
661/**
662 * @brief Reset bias values for the BaseThermometer.
663 * @note Default biases value are obtained from device datasheet when
664 * available otherwise they are considered zero.
665 *
666 * @param[in] devp pointer to @p LPS22HBDriver.
667 *
668 * @return The operation status.
669 * @retval MSG_OK if the function succeeded.
670 *
671 * @api
672 */
673#define lps22hbThermometerResetBias(devp) \
674 thermometerResetBias(&((devp)->thermo_if))
675
676/**
677 * @brief Set sensitivity values for the BaseThermometer.
678 * @note Sensitivity must be expressed as °C/LSB.
679 * @note The sensitivity buffer must be at least the same size of the
680 * BaseThermometer axes number.
681 *
682 * @param[in] devp pointer to @p LPS22HBDriver.
683 * @param[in] sp a buffer which contains sensitivities.
684 *
685 * @return The operation status.
686 * @retval MSG_OK if the function succeeded.
687 *
688 * @api
689 */
690#define lps22hbThermometerSetSensitivity(devp, sp) \
691 thermometerSetSensitivity(&((devp)->thermo_if), sp)
692
693/**
694 * @brief Reset sensitivity values for the BaseThermometer.
695 * @note Default sensitivities value are obtained from device datasheet.
696 *
697 * @param[in] devp pointer to @p LPS22HBDriver.
698 *
699 * @return The operation status.
700 * @retval MSG_OK if the function succeeded.
701 *
702 * @api
703 */
704#define lps22hbThermometerResetSensitivity(devp) \
705 thermometerResetSensitivity(&((devp)->thermo_if))
706
707/*===========================================================================*/
708/* External declarations. */
709/*===========================================================================*/
710
711#ifdef __cplusplus
712extern "C" {
713#endif
714 void lps22hbObjectInit(LPS22HBDriver *devp);
715 void lps22hbStart(LPS22HBDriver *devp, const LPS22HBConfig *config);
716 void lps22hbStop(LPS22HBDriver *devp);
717#ifdef __cplusplus
718}
719#endif
720
721#endif /* _LPS22HB_H_ */
722
723/** @} */
724
diff --git a/lib/chibios/os/ex/devices/ST/lps22hb.mk b/lib/chibios/os/ex/devices/ST/lps22hb.mk
new file mode 100644
index 000000000..7dde418d0
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lps22hb.mk
@@ -0,0 +1,10 @@
1# List of all the LPS22HB device files.
2LPS22HBSRC := $(CHIBIOS)/os/ex/devices/ST/lps22hb.c
3
4# Required include directories
5LPS22HBINC := $(CHIBIOS)/os/ex/include \
6 $(CHIBIOS)/os/ex/devices/ST
7
8# Shared variables
9ALLCSRC += $(LPS22HBSRC)
10ALLINC += $(LPS22HBINC) \ No newline at end of file
diff --git a/lib/chibios/os/ex/devices/ST/lps25h.c b/lib/chibios/os/ex/devices/ST/lps25h.c
new file mode 100644
index 000000000..80dbe241c
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lps25h.c
@@ -0,0 +1,696 @@
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 lps25h.c
23 * @brief LPS25H MEMS interface module code.
24 *
25 * @addtogroup LPS25H
26 * @ingroup EX_ST
27 * @{
28 */
29
30#include "hal.h"
31#include "lps25h.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 (LPS25H_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 *
54 * @param[in] i2cp pointer to the I2C interface
55 * @param[in] sad slave address without R bit
56 * @param[in] reg first sub-register address
57 * @param[out] rxbuf pointer to an output buffer
58 * @param[in] n number of consecutive register to read
59 * @return the operation status.
60 *
61 * @notapi
62 */
63static msg_t lps25hI2CReadRegister(I2CDriver *i2cp, lps25h_sad_t sad,
64 uint8_t reg, uint8_t* rxbuf, size_t n) {
65 uint8_t txbuf = reg;
66 if(n > 1)
67 txbuf |= LPS25H_SUB_MS;
68
69 return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
70 TIME_INFINITE);
71}
72
73/**
74 * @brief Writes a value into a register using I2C.
75 * @pre The I2C interface must be initialized and the driver started.
76 *
77 * @param[in] i2cp pointer to the I2C interface
78 * @param[in] sad slave address without R bit
79 * @param[in] txbuf buffer containing sub-address value in first position
80 * and values to write
81 * @param[in] n size of txbuf less one (not considering the first
82 * element)
83 * @return the operation status.
84 *
85 * @notapi
86 */
87static msg_t lps25hI2CWriteRegister(I2CDriver *i2cp, lps25h_sad_t sad,
88 uint8_t* txbuf, size_t n) {
89 if (n > 1)
90 (*txbuf) |= LPS25H_SUB_MS;
91 return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
92 TIME_INFINITE);
93}
94#endif /* LPS25H_USE_I2C */
95
96/**
97 * @brief Return the number of axes of the BaseBarometer.
98 *
99 * @param[in] ip pointer to @p BaseBarometer interface.
100 *
101 * @return the number of axes.
102 */
103static size_t baro_get_axes_number(void *ip) {
104 (void)ip;
105
106 return LPS25H_BARO_NUMBER_OF_AXES;
107}
108
109/**
110 * @brief Retrieves raw data from the BaseBarometer.
111 * @note This data is retrieved from MEMS register without any algebraical
112 * manipulation.
113 * @note The axes array must be at least the same size of the
114 * BaseBarometer axes number.
115 *
116 * @param[in] ip pointer to @p BaseBarometer interface.
117 * @param[out] axes a buffer which would be filled with raw data.
118 *
119 * @return The operation status.
120 * @retval MSG_OK if the function succeeded.
121 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
122 * be retrieved using @p i2cGetErrors().
123 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
124 */
125static msg_t baro_read_raw(void *ip, int32_t axes[]) {
126 LPS25HDriver* devp;
127 uint8_t buff[3];
128 msg_t msg;
129
130 osalDbgCheck((ip != NULL) && (axes != NULL));
131
132 /* Getting parent instance pointer.*/
133 devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
134
135 osalDbgAssert((devp->state == LPS25H_READY),
136 "baro_read_raw(), invalid state");
137
138 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
139 "baro_read_raw(), channel not ready");
140
141#if LPS25H_SHARED_I2C
142 i2cAcquireBus(devp->config->i2cp);
143 i2cStart(devp->config->i2cp,
144 devp->config->i2ccfg);
145#endif /* LPS25H_SHARED_I2C */
146
147 msg = lps25hI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
148 LPS25H_AD_PRESS_OUT_XL, buff, 3);
149
150#if LPS25H_SHARED_I2C
151 i2cReleaseBus(devp->config->i2cp);
152#endif /* LPS25H_SHARED_I2C */
153
154 if(msg == MSG_OK) {
155 *axes = buff[0] + (buff[1] << 8) + (buff[2] << 16);
156 }
157 return msg;
158}
159
160/**
161 * @brief Retrieves cooked data from the BaseBarometer.
162 * @note This data is manipulated according to the formula
163 * cooked = (raw * sensitivity) - bias.
164 * @note Final data is expressed as hPa.
165 * @note The axes array must be at least the same size of the
166 * BaseBarometer axes number.
167 *
168 * @param[in] ip pointer to @p BaseBarometer interface.
169 * @param[out] axes a buffer which would be filled with cooked data.
170 *
171 * @return The operation status.
172 * @retval MSG_OK if the function succeeded.
173 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
174 * be retrieved using @p i2cGetErrors().
175 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
176 */
177static msg_t baro_read_cooked(void *ip, float axes[]) {
178 LPS25HDriver* devp;
179 int32_t raw;
180 msg_t msg;
181
182 osalDbgCheck((ip != NULL) && (axes != NULL));
183
184 /* Getting parent instance pointer.*/
185 devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
186
187 osalDbgAssert((devp->state == LPS25H_READY),
188 "baro_read_cooked(), invalid state");
189
190 msg = baro_read_raw(ip, &raw);
191
192 *axes = (raw * devp->barosensitivity) - devp->barobias;
193
194 return msg;
195}
196
197/**
198 * @brief Set bias values for the BaseBarometer.
199 * @note Bias must be expressed as hPa.
200 * @note The bias buffer must be at least the same size of the
201 * BaseBarometer axes number.
202 *
203 * @param[in] ip pointer to @p BaseBarometer interface.
204 * @param[in] bp a buffer which contains biases.
205 *
206 * @return The operation status.
207 * @retval MSG_OK if the function succeeded.
208 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
209 * be retrieved using @p i2cGetErrors().
210 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
211 */
212static msg_t baro_set_bias(void *ip, float *bp) {
213 LPS25HDriver* devp;
214 msg_t msg = MSG_OK;
215
216 osalDbgCheck((ip != NULL) && (bp != NULL));
217
218 /* Getting parent instance pointer.*/
219 devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
220
221 osalDbgAssert((devp->state == LPS25H_READY),
222 "baro_set_bias(), invalid state");
223
224 devp->barobias = *bp;
225 return msg;
226}
227
228/**
229 * @brief Reset bias values for the BaseBarometer.
230 * @note Default biases value are obtained from device datasheet when
231 * available otherwise they are considered zero.
232 *
233 * @param[in] ip pointer to @p BaseBarometer interface.
234 *
235 * @return The operation status.
236 * @retval MSG_OK if the function succeeded.
237 */
238static msg_t baro_reset_bias(void *ip) {
239 LPS25HDriver* devp;
240 msg_t msg = MSG_OK;
241
242 osalDbgCheck(ip != NULL);
243
244 /* Getting parent instance pointer.*/
245 devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
246
247 osalDbgAssert((devp->state == LPS25H_READY),
248 "baro_reset_bias(), invalid state");
249
250 devp->barobias = LPS25H_BARO_SENS;
251 return msg;
252}
253
254/**
255 * @brief Set sensitivity values for the BaseBarometer.
256 * @note Sensitivity must be expressed as hPa/LSB.
257 * @note The sensitivity buffer must be at least the same size of the
258 * BaseBarometer axes number.
259 *
260 * @param[in] ip pointer to @p BaseBarometer interface.
261 * @param[in] sp a buffer which contains sensitivities.
262 *
263 * @return The operation status.
264 * @retval MSG_OK if the function succeeded.
265 */
266static msg_t baro_set_sensitivity(void *ip, float *sp) {
267 LPS25HDriver* devp;
268 msg_t msg = MSG_OK;
269
270 osalDbgCheck((ip != NULL) && (sp != NULL));
271
272 /* Getting parent instance pointer.*/
273 devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
274
275 osalDbgAssert((devp->state == LPS25H_READY),
276 "baro_set_sensitivity(), invalid state");
277
278 devp->barosensitivity = *sp;
279 return msg;
280}
281
282/**
283 * @brief Reset sensitivity values for the BaseBarometer.
284 * @note Default sensitivities value are obtained from device datasheet.
285 *
286 * @param[in] ip pointer to @p BaseBarometer interface.
287 *
288 * @return The operation status.
289 * @retval MSG_OK if the function succeeded.
290 */
291static msg_t baro_reset_sensitivity(void *ip) {
292 LPS25HDriver* devp;
293 msg_t msg = MSG_OK;
294
295 osalDbgCheck(ip != NULL);
296
297 /* Getting parent instance pointer.*/
298 devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
299
300 osalDbgAssert((devp->state == LPS25H_READY),
301 "baro_reset_sensitivity(), invalid state");
302
303 devp->barosensitivity = LPS25H_BARO_SENS;
304 return msg;
305}
306
307/**
308 * @brief Return the number of axes of the BaseThermometer.
309 *
310 * @param[in] ip pointer to @p BaseThermometer interface.
311 *
312 * @return the number of axes.
313 */
314static size_t thermo_get_axes_number(void *ip) {
315 (void)ip;
316
317 return LPS25H_THERMO_NUMBER_OF_AXES;
318}
319
320/**
321 * @brief Retrieves raw data from the BaseThermometer.
322 * @note This data is retrieved from MEMS register without any algebraical
323 * manipulation.
324 * @note The axes array must be at least the same size of the
325 * BaseThermometer axes number.
326 *
327 * @param[in] ip pointer to @p BaseThermometer interface.
328 * @param[out] axes a buffer which would be filled with raw data.
329 *
330 * @return The operation status.
331 * @retval MSG_OK if the function succeeded.
332 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
333 * be retrieved using @p i2cGetErrors().
334 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
335 */
336static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
337 LPS25HDriver* devp;
338 int16_t tmp;
339 uint8_t buff[2];
340 msg_t msg;
341
342 osalDbgCheck((ip != NULL) && (axes != NULL));
343
344 /* Getting parent instance pointer.*/
345 devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
346
347 osalDbgAssert((devp->state == LPS25H_READY),
348 "thermo_read_raw(), invalid state");
349
350 osalDbgAssert((devp->config->i2cp->state == I2C_READY),
351 "thermo_read_raw(), channel not ready");
352
353#if LPS25H_SHARED_I2C
354 i2cAcquireBus(devp->config->i2cp);
355 i2cStart(devp->config->i2cp,
356 devp->config->i2ccfg);
357#endif /* LPS25H_SHARED_I2C */
358
359 msg = lps25hI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
360 LPS25H_AD_TEMP_OUT_L, buff, 2);
361
362#if LPS25H_SHARED_I2C
363 i2cReleaseBus(devp->config->i2cp);
364#endif /* LPS25H_SHARED_I2C */
365
366 if (msg == MSG_OK) {
367 tmp = buff[0] + (buff[1] << 8);
368 *axes = (int32_t)tmp;
369 }
370 return msg;
371}
372
373/**
374 * @brief Retrieves cooked data from the BaseThermometer.
375 * @note This data is manipulated according to the formula
376 * cooked = (raw * sensitivity) - bias.
377 * @note Final data is expressed as °C.
378 * @note The axes array must be at least the same size of the
379 * BaseThermometer axes number.
380 *
381 * @param[in] ip pointer to @p BaseThermometer interface.
382 * @param[out] axis a buffer which would be filled with cooked data.
383 *
384 * @return The operation status.
385 * @retval MSG_OK if the function succeeded.
386 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
387 * be retrieved using @p i2cGetErrors().
388 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
389 */
390static msg_t thermo_read_cooked(void *ip, float* axis) {
391 LPS25HDriver* devp;
392 int32_t raw;
393 msg_t msg;
394
395 osalDbgCheck((ip != NULL) && (axis != NULL));
396
397 /* Getting parent instance pointer.*/
398 devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
399
400 osalDbgAssert((devp->state == LPS25H_READY),
401 "thermo_read_cooked(), invalid state");
402
403 msg = thermo_read_raw(devp, &raw);
404
405 *axis = (raw * devp->thermosensitivity) - devp->thermobias;
406
407 return msg;
408}
409
410/**
411 * @brief Set bias values for the BaseThermometer.
412 * @note Bias must be expressed as °C.
413 * @note The bias buffer must be at least the same size of the
414 * BaseThermometer axes number.
415 *
416 * @param[in] ip pointer to @p BaseThermometer interface.
417 * @param[in] bp a buffer which contains biases.
418 *
419 * @return The operation status.
420 * @retval MSG_OK if the function succeeded.
421 */
422static msg_t thermo_set_bias(void *ip, float *bp) {
423 LPS25HDriver* devp;
424 msg_t msg = MSG_OK;
425
426 osalDbgCheck((ip != NULL) && (bp != NULL));
427
428 /* Getting parent instance pointer.*/
429 devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
430
431 osalDbgAssert((devp->state == LPS25H_READY),
432 "thermo_set_bias(), invalid state");
433
434 devp->thermobias = *bp;
435
436 return msg;
437}
438
439/**
440 * @brief Reset bias values for the BaseThermometer.
441 * @note Default biases value are obtained from device datasheet when
442 * available otherwise they are considered zero.
443 *
444 * @param[in] ip pointer to @p BaseThermometer interface.
445 *
446 * @return The operation status.
447 * @retval MSG_OK if the function succeeded.
448 */
449static msg_t thermo_reset_bias(void *ip) {
450 LPS25HDriver* devp;
451 msg_t msg = MSG_OK;
452
453 osalDbgCheck(ip != NULL);
454
455 /* Getting parent instance pointer.*/
456 devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
457
458 osalDbgAssert((devp->state == LPS25H_READY),
459 "thermo_reset_bias(), invalid state");
460
461 devp->thermobias = LPS25H_THERMO_BIAS;
462
463 return msg;
464}
465
466/**
467 * @brief Set sensitivity values for the BaseThermometer.
468 * @note Sensitivity must be expressed as °C/LSB.
469 * @note The sensitivity buffer must be at least the same size of the
470 * BaseThermometer axes number.
471 *
472 * @param[in] ip pointer to @p BaseThermometer interface.
473 * @param[in] sp a buffer which contains sensitivities.
474 *
475 * @return The operation status.
476 * @retval MSG_OK if the function succeeded.
477 */
478static msg_t thermo_set_sensitivity(void *ip, float *sp) {
479 LPS25HDriver* devp;
480 msg_t msg = MSG_OK;
481
482 osalDbgCheck((ip != NULL) && (sp != NULL));
483
484 /* Getting parent instance pointer.*/
485 devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
486
487 osalDbgAssert((devp->state == LPS25H_READY),
488 "thermo_set_sensitivity(), invalid state");
489
490 devp->thermosensitivity = *sp;
491
492 return msg;
493}
494
495/**
496 * @brief Reset sensitivity values for the BaseThermometer.
497 * @note Default sensitivities value are obtained from device datasheet.
498 *
499 * @param[in] ip pointer to @p BaseThermometer interface.
500 *
501 * @return The operation status.
502 * @retval MSG_OK if the function succeeded.
503 */
504static msg_t thermo_reset_sensitivity(void *ip) {
505 LPS25HDriver* devp;
506 msg_t msg = MSG_OK;
507
508 osalDbgCheck(ip != NULL);
509
510 /* Getting parent instance pointer.*/
511 devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
512
513 osalDbgAssert((devp->state == LPS25H_READY),
514 "thermo_reset_sensitivity(), invalid state");
515
516 devp->thermosensitivity = LPS25H_THERMO_SENS;
517
518 return msg;
519}
520
521static const struct LPS25HVMT vmt_device = {
522 (size_t)0
523};
524
525static const struct BaseBarometerVMT vmt_barometer = {
526 sizeof(struct LPS25HVMT*),
527 baro_get_axes_number, baro_read_raw, baro_read_cooked,
528 baro_set_bias, baro_reset_bias, baro_set_sensitivity,
529 baro_reset_sensitivity
530};
531
532static const struct BaseThermometerVMT vmt_thermometer = {
533 sizeof(struct LPS25HVMT*) + sizeof(BaseBarometer),
534 thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
535 thermo_set_bias, thermo_reset_bias, thermo_set_sensitivity,
536 thermo_reset_sensitivity
537};
538
539/*===========================================================================*/
540/* Driver exported functions. */
541/*===========================================================================*/
542
543/**
544 * @brief Initializes an instance.
545 *
546 * @param[out] devp pointer to the @p LPS25HDriver object
547 *
548 * @init
549 */
550void lps25hObjectInit(LPS25HDriver *devp) {
551
552 devp->vmt = &vmt_device;
553 devp->baro_if.vmt = &vmt_barometer;
554 devp->thermo_if.vmt = &vmt_thermometer;
555
556 devp->config = NULL;
557
558 devp->baroaxes = LPS25H_BARO_NUMBER_OF_AXES;
559 devp->thermoaxes = LPS25H_THERMO_NUMBER_OF_AXES;
560
561 devp->state = LPS25H_STOP;
562}
563
564/**
565 * @brief Configures and activates LPS25H Complex Driver peripheral.
566 *
567 * @param[in] devp pointer to the @p LPS25HDriver object
568 * @param[in] config pointer to the @p LPS25HConfig object
569 *
570 * @api
571 */
572void lps25hStart(LPS25HDriver *devp, const LPS25HConfig *config) {
573 uint8_t cr[2];
574 osalDbgCheck((devp != NULL) && (config != NULL));
575
576 osalDbgAssert((devp->state == LPS25H_STOP) || (devp->state == LPS25H_READY),
577 "lps25hStart(), invalid state");
578
579 devp->config = config;
580
581 /* Control register 1 configuration block.*/
582 {
583 cr[0] = LPS25H_AD_CTRL_REG1;
584 cr[1] = devp->config->outputdatarate | LPS25H_CTRL_REG1_PD;
585#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__)
586 cr[1] |= devp->config->blockdataupdate;
587#endif
588 }
589
590#if LPS25H_SHARED_I2C
591 i2cAcquireBus((devp)->config->i2cp);
592#endif /* LPS25H_SHARED_I2C */
593 i2cStart((devp)->config->i2cp,
594 (devp)->config->i2ccfg);
595
596 lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, cr, 1);
597
598#if LPS25H_SHARED_I2C
599 i2cReleaseBus((devp)->config->i2cp);
600#endif /* LPS25H_SHARED_I2C */
601
602 /* Resolution configuration block.*/
603 {
604 cr[0] = LPS25H_AD_RES_CONF;
605 cr[1] = 0x05;
606#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__)
607 cr[1] = devp->config->baroresolution | devp->config->thermoresolution;
608#endif
609
610 }
611#if LPS25H_SHARED_I2C
612 i2cAcquireBus((devp)->config->i2cp);
613 i2cStart((devp)->config->i2cp,
614 (devp)->config->i2ccfg);
615#endif /* LPS25H_SHARED_I2C */
616
617 lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
618 cr, 1);
619
620#if LPS25H_SHARED_I2C
621 i2cReleaseBus((devp)->config->i2cp);
622#endif /* LPS25H_SHARED_I2C */
623
624 if(devp->config->barosensitivity == NULL) {
625 devp->barosensitivity = LPS25H_BARO_SENS;
626 }
627 else{
628 /* Taking barometer sensitivity from user configurations */
629 devp->barosensitivity = *(devp->config->barosensitivity);
630 }
631
632 if(devp->config->barobias == NULL) {
633 devp->barobias = LPS25H_BARO_BIAS;
634 }
635 else{
636 /* Taking barometer bias from user configurations */
637 devp->barobias = *(devp->config->barobias);
638 }
639
640 if(devp->config->thermosensitivity == NULL) {
641 devp->thermosensitivity = LPS25H_THERMO_SENS;
642 }
643 else{
644 /* Taking thermometer sensitivity from user configurations */
645 devp->thermosensitivity = *(devp->config->thermosensitivity);
646 }
647
648 if(devp->config->thermobias == NULL) {
649 devp->thermobias = LPS25H_THERMO_BIAS;
650 }
651 else{
652 /* Taking thermometer bias from user configurations */
653 devp->thermobias = *(devp->config->thermobias);
654 }
655
656 /* This is the Barometer transient recovery time */
657 osalThreadSleepMilliseconds(5);
658
659 devp->state = LPS25H_READY;
660}
661
662/**
663 * @brief Deactivates the LPS25H Complex Driver peripheral.
664 *
665 * @param[in] devp pointer to the @p LPS25HDriver object
666 *
667 * @api
668 */
669void lps25hStop(LPS25HDriver *devp) {
670 uint8_t cr[2];
671
672 osalDbgCheck(devp != NULL);
673
674 osalDbgAssert((devp->state == LPS25H_STOP) || (devp->state == LPS25H_READY),
675 "lps25hStop(), invalid state");
676
677 if (devp->state == LPS25H_READY) {
678#if LPS25H_SHARED_I2C
679 i2cAcquireBus((devp)->config->i2cp);
680 i2cStart((devp)->config->i2cp,
681 (devp)->config->i2ccfg);
682#endif /* LPS25H_SHARED_I2C */
683
684 cr[0] = LPS25H_AD_CTRL_REG1;
685 cr[1] = 0;
686 lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
687 cr, 1);
688
689 i2cStop((devp)->config->i2cp);
690#if LPS25H_SHARED_I2C
691 i2cReleaseBus((devp)->config->i2cp);
692#endif /* LPS25H_SHARED_I2C */
693 }
694 devp->state = LPS25H_STOP;
695}
696/** @} */
diff --git a/lib/chibios/os/ex/devices/ST/lps25h.h b/lib/chibios/os/ex/devices/ST/lps25h.h
new file mode 100644
index 000000000..333a97bc0
--- /dev/null
+++ b/lib/chibios/os/ex/devices/ST/lps25h.h
@@ -0,0 +1,740 @@
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 lps25h.h
23 * @brief LPS25H MEMS interface module header.
24 *
25 * @addtogroup LPS25H
26 * @ingroup EX_ST
27 * @{
28 */
29#ifndef _LPS25H_H_
30#define _LPS25H_H_
31
32#include "ex_barometer.h"
33#include "ex_thermometer.h"
34
35/*===========================================================================*/
36/* Driver constants. */
37/*===========================================================================*/
38
39/**
40 * @name Version identification
41 * @{
42 */
43/**
44 * @brief LPS25H driver version string.
45 */
46#define EX_LPS25H_VERSION "1.1.2"
47
48/**
49 * @brief LPS25H driver version major number.
50 */
51#define EX_LPS25H_MAJOR 1
52
53/**
54 * @brief LPS25H driver version minor number.
55 */
56#define EX_LPS25H_MINOR 1
57
58/**
59 * @brief LPS25H driver version patch number.
60 */
61#define EX_LPS25H_PATCH 2
62/** @} */
63
64/**
65 * @brief LPS25H barometer subsystem characteristics.
66 * @note Sensitivity is expressed as hPa/LSB whereas hPa stand for
67 * hectopascal.
68 * @note Bias is expressed as hPa.
69 *
70 * @{
71 */
72#define LPS25H_BARO_NUMBER_OF_AXES 1U
73
74#define LPS25H_BARO_SENS 0.00024414f
75#define LPS25H_BARO_BIAS 0.0f
76/** @} */
77
78/**
79 * @brief LPS25H thermometer subsystem characteristics.
80 * @note Sensitivity is expressed as �C/LSB.
81 * @note Bias is expressed as �C.
82 *
83 * @{
84 */
85#define LPS25H_THERMO_NUMBER_OF_AXES 1U
86
87#define LPS25H_THERMO_SENS 0.00208333f
88#define LPS25H_THERMO_BIAS -42.5f
89/** @} */
90
91/**
92 * @name LPS25H communication interfaces related bit masks
93 * @{
94 */
95#define LPS25H_DI_MASK 0xFF
96#define LPS25H_DI(n) (1 << n)
97#define LPS25H_AD_MASK 0x3F
98#define LPS25H_AD(n) (1 << n)
99#define LPS25H_MS (1 << 6)
100#define LPS25H_RW (1 << 7)
101
102#define LPS25H_SUB_MS (1 << 7)
103/** @} */
104
105/**
106 * @name LPS25H register addresses
107 * @{
108 */
109#define LPS25H_AD_REF_P_XL 0x08
110#define LPS25H_AD_REF_P_L 0x09
111#define LPS25H_AD_REF_P_H 0x0A
112#define LPS25H_AD_WHO_AM_I 0x0F
113#define LPS25H_AD_RES_CONF 0x10
114#define LPS25H_AD_CTRL_REG1 0x20
115#define LPS25H_AD_CTRL_REG2 0x21
116#define LPS25H_AD_CTRL_REG3 0x22
117#define LPS25H_AD_CTRL_REG4 0x23
118#define LPS25H_AD_INT_CFG 0x24
119#define LPS25H_AD_INT_SRC 0x25
120#define LPS25H_AD_STATUS_REG 0x27
121#define LPS25H_AD_PRESS_OUT_XL 0x28
122#define LPS25H_AD_PRESS_OUT_L 0x29
123#define LPS25H_AD_PRESS_OUT_H 0x2A
124#define LPS25H_AD_TEMP_OUT_L 0x2B
125#define LPS25H_AD_TEMP_OUT_H 0x2C
126#define LPS25H_AD_FIFO_CTRL 0x2E
127#define LPS25H_AD_FIFO_SRC 0x2F
128#define LPS25H_AD_THS_P_L 0x30
129#define LPS25H_AD_THS_P_H 0x31
130#define LPS25H_AD_RPDS_L 0x39
131#define LPS25H_AD_RPDS_H 0x3A
132/** @} */
133
134/**
135 * @name LPS25H_CTRL_REG1 register bits definitions
136 * @{
137 */
138#define LPS25H_CTRL_REG1_MASK 0xFF
139#define LPS25H_CTRL_REG1_SIM (1 << 0)
140#define LPS25H_CTRL_REG1_RESET_AZ (1 << 1)
141#define LPS25H_CTRL_REG1_BDU (1 << 2)
142#define LPS25H_CTRL_REG1_DIFF_EN (1 << 3)
143#define LPS25H_CTRL_REG1_ODR0 (1 << 4)
144#define LPS25H_CTRL_REG1_ODR1 (1 << 5)
145#define LPS25H_CTRL_REG1_ODR2 (1 << 6)
146#define LPS25H_CTRL_REG1_PD (1 << 7)
147/** @} */
148
149/**
150 * @name LPS25H_CTRL_REG2 register bits definitions
151 * @{
152 */
153#define LPS25H_CTRL_REG2_MASK 0xF3
154#define LPS25H_CTRL_REG2_ONE_SHOT (1 << 0)
155#define LPS25H_CTRL_REG2_AUTO_ZERO (1 << 1)
156#define LPS25H_CTRL_REG2_SWRESET (1 << 2)
157#define LPS25H_CTRL_REG2_FIFO_MEAN_DEC (1 << 4)
158#define LPS25H_CTRL_REG2_WTM_EN (1 << 5)
159#define LPS25H_CTRL_REG2_FIFO_EN (1 << 6)
160#define LPS25H_CTRL_REG2_BOOT (1 << 7)
161/** @} */
162
163/**
164 * @name LPS25H_CTRL_REG3 register bits definitions
165 * @{
166 */
167#define LPS25H_CTRL_REG3_MASK 0xC3
168#define LPS25H_CTRL_REG3_INT_S1 (1 << 0)
169#define LPS25H_CTRL_REG3_INT_S2 (1 << 1)
170#define LPS25H_CTRL_REG3_PP_OD (1 << 6)
171#define LPS25H_CTRL_REG3_INT_H_L (1 << 7)
172/** @} */
173
174/**
175 * @name LPS25H_CTRL_REG4 register bits definitions
176 * @{
177 */
178#define LPS25H_CTRL_REG4_MASK 0x0F
179#define LPS25H_CTRL_REG4_P1_DRDY (1 << 0)
180#define LPS25H_CTRL_REG4_P1_OVERRUN (1 << 1)
181#define LPS25H_CTRL_REG4_P1_WTM (1 << 2)
182#define LPS25H_CTRL_REG4_P1_EMPTY (1 << 3)
183/** @} */
184
185/**
186 * @name LPS25H_INT1_CFG register bits definitions
187 * @{
188 */
189#define LPS25H_INT1_CFG_MASK 0x07
190#define LPS25H_INT1_CFG_PH_E (1 << 0)
191#define LPS25H_INT1_CFG_PL_E (1 << 1)
192#define LPS25H_INT1_CFG_LIR (1 << 2)
193/** @} */
194
195/**
196 * @name LPS25H_INT1_SRC register bits definitions
197 * @{
198 */
199#define LPS25H_INT1_SRC_MASK 0x07
200#define LPS25H_INT1_SRC_PH (1 << 0)
201#define LPS25H_INT1_SRC_PL (1 << 1)
202#define LPS25H_INT1_SRC_IA (1 << 2)
203/** @} */
204
205/*===========================================================================*/
206/* Driver pre-compile time settings. */
207/*===========================================================================*/
208
209/**
210 * @name Configuration options
211 * @{
212 */
213/**
214 * @brief LPS25H SPI interface switch.
215 * @details If set to @p TRUE the support for SPI is included.
216 * @note The default is @p FALSE.
217 */
218#if !defined(LPS25H_USE_SPI) || defined(__DOXYGEN__)
219#define LPS25H_USE_SPI FALSE
220#endif
221
222/**
223 * @brief LPS25H shared SPI switch.
224 * @details If set to @p TRUE the device acquires SPI bus ownership
225 * on each transaction.
226 * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
227 */
228#if !defined(LPS25H_SHARED_SPI) || defined(__DOXYGEN__)
229#define LPS25H_SHARED_SPI FALSE
230#endif
231
232/**
233 * @brief LPS25H I2C interface switch.
234 * @details If set to @p TRUE the support for I2C is included.
235 * @note The default is @p TRUE.
236 */
237#if !defined(LPS25H_USE_I2C) || defined(__DOXYGEN__)
238#define LPS25H_USE_I2C TRUE
239#endif
240
241/**
242 * @brief LPS25H shared I2C switch.
243 * @details If set to @p TRUE the device acquires I2C bus ownership
244 * on each transaction.
245 * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
246 */
247#if !defined(LPS25H_SHARED_I2C) || defined(__DOXYGEN__)
248#define LPS25H_SHARED_I2C FALSE
249#endif
250
251/**
252 * @brief LPS25H advanced configurations switch.
253 * @details If set to @p TRUE more configurations are available.
254 * @note The default is @p FALSE.
255 */
256#if !defined(LPS25H_USE_ADVANCED) || defined(__DOXYGEN__)
257#define LPS25H_USE_ADVANCED FALSE
258#endif
259/** @} */
260
261/*===========================================================================*/
262/* Derived constants and error checks. */
263/*===========================================================================*/
264
265#if !(LPS25H_USE_SPI ^ LPS25H_USE_I2C)
266#error "LPS25H_USE_SPI and LPS25H_USE_I2C cannot be both true or both false"
267#endif
268
269#if LPS25H_USE_SPI && !HAL_USE_SPI
270#error "LPS25H_USE_SPI requires HAL_USE_SPI"
271#endif
272
273#if LPS25H_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
274#error "LPS25H_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
275#endif
276
277#if LPS25H_USE_I2C && !HAL_USE_I2C
278#error "LPS25H_USE_I2C requires HAL_USE_I2C"
279#endif
280
281#if LPS25H_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
282#error "LPS25H_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
283#endif
284
285/*
286 * CHTODO: Add support for LPS25H over SPI.
287 */
288#if LPS25H_USE_SPI
289#error "LPS25H over SPI still not supported"
290#endif
291
292/*===========================================================================*/
293/* Driver data structures and types. */
294/*===========================================================================*/
295
296/**
297 * @name LPS25H data structures and types.
298 * @{
299 */
300/**
301 * @brief Structure representing a LPS25H driver.
302 */
303typedef struct LPS25HDriver LPS25HDriver;
304
305/**
306 * @brief LPS25H slave address
307 */
308typedef enum {
309 LPS25H_SAD_GND = 0x5C, /**< Slave Address when SA0 is to GND */
310 LPS25H_SAD_VCC = 0x5D /**< Slave Address when SA0 is to VCC */
311}lps25h_sad_t;
312
313/**
314 * @brief LPS25H output data rate and bandwidth.
315 */
316typedef enum {
317 LPS25H_ODR_ONE_SHOT = 0x00, /**< One shot. */
318 LPS25H_ODR_1HZ = 0x10, /**< Output data rate 1 Hz. */
319 LPS25H_ODR_7HZ = 0x20, /**< Output data rate 7 Hz. */
320 LPS25H_ODR_12P5HZ = 0x30, /**< Output data rate 12.5 Hz. */
321 LPS25H_ODR_25HZ = 0x40 /**< Output data rate 25 Hz. */
322}lps25h_odr_t;
323
324/**
325 * @brief LPS25H pressure resolution.
326 */
327typedef enum {
328 LPS25H_AVGP_8 = 0x00, /**< Number of internal average is 8. */
329 LPS25H_AVGP_32 = 0x01, /**< Number of internal average is 32. */
330 LPS25H_AVGP_128 = 0x02, /**< Number of internal average is 128. */
331 LPS25H_AVGP_512 = 0x03, /**< Number of internal average is 512. */
332}lps25h_avgp_t;
333
334/**
335 * @brief LPS25H temperature resolution.
336 */
337typedef enum {
338 LPS25H_AVGT_8 = 0x00, /**< Number of internal average is 8. */
339 LPS25H_AVGT_32 = 0x04, /**< Number of internal average is 32. */
340 LPS25H_AVGT_128 = 0x08, /**< Number of internal average is 128. */
341 LPS25H_AVGT_512 = 0x0C, /**< Number of internal average is 512. */
342}lps25h_avgt_t;
343
344/**
345 * @brief LPS25H block data update.
346 */
347typedef enum {
348 LPS25H_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
349 LPS25H_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
350}lps25h_bdu_t;
351
352/**
353 * @brief Driver state machine possible states.
354 */
355typedef enum {
356 LPS25H_UNINIT = 0, /**< Not initialized. */
357 LPS25H_STOP = 1, /**< Stopped. */
358 LPS25H_READY = 2, /**< Ready. */
359} lps25h_state_t;
360
361/**
362 * @brief LPS25H configuration structure.
363 */
364typedef struct {
365
366#if LPS25H_USE_SPI || defined(__DOXYGEN__)
367 /**
368 * @brief SPI driver associated to this LPS25H.
369 */
370 SPIDriver *spip;
371 /**
372 * @brief SPI configuration associated to this LPS25H.
373 */
374 const SPIConfig *spicfg;
375#endif /* LPS25H_USE_SPI */
376#if LPS25H_USE_I2C || defined(__DOXYGEN__)
377 /**
378 * @brief I2C driver associated to this LPS25H.
379 */
380 I2CDriver *i2cp;
381 /**
382 * @brief I2C configuration associated to this LPS25H.
383 */
384 const I2CConfig *i2ccfg;
385 /**
386 * @brief LPS25H slave address
387 */
388 lps25h_sad_t slaveaddress;
389#endif /* LPS25H_USE_I2C */
390 /**
391 * @brief LPS25H barometer subsystem initial sensitivity.
392 */
393 float *barosensitivity;
394 /**
395 * @brief LPS25H barometer subsystem initial bias.
396 */
397 float *barobias;
398 /**
399 * @brief LPS25H thermometer subsystem initial sensitivity.
400 */
401 float *thermosensitivity;
402 /**
403 * @brief LPS25H thermometer subsystem initial bias.
404 */
405 float *thermobias;
406 /**
407 * @brief LPS25H output data rate selection.
408 */
409 lps25h_odr_t outputdatarate;
410#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__)
411 /**
412 * @brief LPS25H block data update.
413 */
414 lps25h_bdu_t blockdataupdate;
415 /**
416 * @brief LPS25H barometer subsystem resolution.
417 */
418 lps25h_avgp_t baroresolution;
419 /**
420 * @brief LPS25H thermometer subsystem resolution.
421 */
422 lps25h_avgt_t thermoresolution;
423#endif
424} LPS25HConfig;
425
426/**
427 * @brief @p LPS25H specific methods.
428 * @note No methods so far, just a common ancestor interface.
429 */
430#define _lps25h_methods_alone
431
432/**
433 * @brief @p LPS25H specific methods with inherited ones.
434 */
435#define _lps25h_methods \
436 _base_object_methods \
437 _lps25h_methods_alone
438
439/**
440 * @extends BaseObjectVMT
441 *
442 * @brief @p LPS25H virtual methods table.
443 */
444struct LPS25HVMT {
445 _lps25h_methods
446};
447
448/**
449 * @brief @p LPS25HDriver specific data.
450 */
451#define _lps25h_data \
452 /* Driver state.*/ \
453 lps25h_state_t state; \
454 /* Current configuration data.*/ \
455 const LPS25HConfig *config; \
456 /* Barometer subsystem axes number.*/ \
457 size_t baroaxes; \
458 /* Barometer subsystem current sensitivity.*/ \
459 float barosensitivity; \
460 /* Barometer subsystem current bias .*/ \
461 float barobias; \
462 /* Thermometer subsystem axes number.*/ \
463 size_t thermoaxes; \
464 /* Thermometer subsystem current sensitivity.*/ \
465 float thermosensitivity; \
466 /* Thermometer subsystem current bias.*/ \
467 float thermobias;
468
469/**
470 * @brief LPS25H 2-axis barometer/thermometer class.
471 */
472struct LPS25HDriver {
473 /** @brief Virtual Methods Table.*/
474 const struct LPS25HVMT *vmt;
475 /** @brief Base barometer interface.*/
476 BaseBarometer baro_if;
477 /** @brief Base thermometer interface.*/
478 BaseThermometer thermo_if;
479 _lps25h_data
480};
481/** @} */
482
483/*===========================================================================*/
484/* Driver macros. */
485/*===========================================================================*/
486
487/**
488 * @brief Return the number of axes of the BaseBarometer.
489 *
490 * @param[in] devp pointer to @p LPS25HDriver.
491 *
492 * @return the number of axes.
493 *
494 * @api
495 */
496#define lps25hBarometerGetAxesNumber(devp) \
497 barometerGetAxesNumber(&((devp)->baro_if))
498
499/**
500 * @brief Retrieves raw data from the BaseBarometer.
501 * @note This data is retrieved from MEMS register without any algebraical
502 * manipulation.
503 * @note The axes array must be at least the same size of the
504 * BaseBarometer axes number.
505 *
506 * @param[in] devp pointer to @p LPS25HDriver.
507 * @param[out] axes a buffer which would be filled with raw data.
508 *
509 * @return The operation status.
510 * @retval MSG_OK if the function succeeded.
511 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
512 * be retrieved using @p i2cGetErrors().
513 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
514 *
515 * @api
516 */
517#define lps25hBarometerReadRaw(devp, axes) \
518 barometerReadRaw(&((devp)->baro_if), axes)
519
520/**
521 * @brief Retrieves cooked data from the BaseBarometer.
522 * @note This data is manipulated according to the formula
523 * cooked = (raw * sensitivity) - bias.
524 * @note Final data is expressed as hPa.
525 * @note The axes array must be at least the same size of the
526 * BaseBarometer axes number.
527 *
528 * @param[in] devp pointer to @p LPS25HDriver.
529 * @param[out] axes a buffer which would be filled with cooked data.
530 *
531 * @return The operation status.
532 * @retval MSG_OK if the function succeeded.
533 * @retval MSG_RESET if one or more I2C errors occurred, the errors can
534 * be retrieved using @p i2cGetErrors().
535 * @retval MSG_TIMEOUT if a timeout occurred before operation end.
536 *
537 * @api
538 */
539#define lps25hBarometerReadCooked(devp, axes) \
540 barometerReadCooked(&((devp)->baro_if), axes)
541
542/**
543 * @brief Set bias values for the BaseBarometer.
544 * @note Bias must be expressed as hPa.
545 * @note The bias buffer must be at least the same size of the
546 * BaseBarometer axes number.
547 *
548 * @param[in] devp pointer to @p LPS25HDriver.
549 * @param[in] bp a buffer which contains biases.
550 *
551 * @return The operation status.
552 * @retval MSG_OK if the function succeeded.
553 *
554 * @api
555 */
556#define lps25hBarometerSetBias(devp, bp) \
557 barometerSetBias(&((devp)->baro_if), bp)
558
559/**
560 * @brief Reset bias values for the BaseBarometer.
561 * @note Default biases value are obtained from device datasheet when
562 * available otherwise they are considered zero.
563 *
564 * @param[in] devp pointer to @p LPS25HDriver.
565 *
566 * @return The operation status.
567 * @retval MSG_OK if the function succeeded.
568 *
569 * @api
570 */
571#define lps25hBarometerResetBias(devp) \
572 barometerResetBias(&((devp)->baro_if))
573
574/**
575 * @brief Set sensitivity values for the BaseBarometer.
576 * @note Sensitivity must be expressed as hPa/LSB.
577 * @note The sensitivity buffer must be at least the same size of the
578 * BaseBarometer axes number.
579 *
580 * @param[in] devp pointer to @p LPS25HDriver.
581 * @param[in] sp a buffer which contains sensitivities.
582 *
583 * @return The operation status.
584 * @retval MSG_OK if the function succeeded.