ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_interface_lis2dh12.c
Go to the documentation of this file.
2#if (RI_LIS2DH12_ENABLED || DOXYGEN)
9#include "lis2dh12_reg.h"
10
11#include <stdlib.h>
12#include <string.h>
13#include <stdio.h>
14
15#ifdef RUUVI_NRF5_SDK15_LIS2GH12_DEBUG
16#ifndef RUUVI_NRF5_SDK15_LIS2GH12_LOG_LEVEL
17#define RUUVI_NRF5_SDK15_LIS2GH12_LOG_LEVEL RI_LOG_LEVEL_DEBUG
18#endif
19
20#define LOGD(fmt, ...) \
21 do { \
22 char buff[1024] = {0}; \
23 snprintf(buff, sizeof(buff), ":%d:%s(): " fmt, \
24 __LINE__, __func__, ##__VA_ARGS__); \
25 ri_log(RUUVI_NRF5_SDK15_LIS2GH12_LOG_LEVEL, buff); \
26 } while (0)
27#else
28#define LOGD(fmt, ...)
29#endif
50#define NUM_AXIS (3U)
51#define NM_BIT_DIVEDER (64U)
52#define MOTION_THRESHOLD_MAX (0x7FU)
53#define PWRON_DELAY_MS (10U)
54
56#define VERIFY_SENSOR_SLEEPS() do { \
57 uint8_t MACRO_MODE = 0; \
58 ri_lis2dh12_mode_get(&MACRO_MODE); \
59 if(RD_SENSOR_CFG_SLEEP != MACRO_MODE) { return RD_ERROR_INVALID_STATE; } \
60 } while(0)
61
63typedef union
64{
65 int16_t i16bit[NUM_AXIS];
66 uint8_t u8bit[2 * NUM_AXIS];
67} axis3bit16_t;
68
70typedef union
71{
72 int16_t i16bit;
73 uint8_t u8bit[2];
74} axis1bit16_t;
75
79#ifndef CEEDLING
80static
81#endif
82ri_lis2dh12_dev dev = {0};
83
84static const char m_acc_name[] = "LIS2DH12";
85
86static void lis2dh12_get_samples_selftest (axis3bit16_t * p_data_raw_acceleration)
87{
88 axis3bit16_t data_raw_acceleration = {0};
89 int32_t axis_x = 0;
90 int32_t axis_y = 0;
91 int32_t axis_z = 0;
92 // Start delay
94 // Discard first sample
95 lis2dh12_acceleration_raw_get (&dev.ctx, data_raw_acceleration.u8bit);
96
97 // Obtain 5 no self test samples
98 for (uint8_t i = 0; i < SELF_TEST_SAMPLES_NUM; i++)
99 {
100 lis2dh12_acceleration_raw_get (&dev.ctx, data_raw_acceleration.u8bit);
101 axis_x += data_raw_acceleration.i16bit[0];
102 axis_y += data_raw_acceleration.i16bit[1];
103 axis_z += data_raw_acceleration.i16bit[2];
104 }
105
106 p_data_raw_acceleration->i16bit[0] = (int16_t) (axis_x / SELF_TEST_SAMPLES_NUM);
107 p_data_raw_acceleration->i16bit[1] = (int16_t) (axis_y / SELF_TEST_SAMPLES_NUM);
108 p_data_raw_acceleration->i16bit[2] = (int16_t) (axis_z / SELF_TEST_SAMPLES_NUM);
109}
110
111// Check that self-test values differ enough
112static rd_status_t lis2dh12_verify_selftest (const axis3bit16_t * const new,
113 const axis3bit16_t * const old)
114{
115 rd_status_t err_code = RD_SUCCESS;
116
117 if (LIS2DH12_2g != dev.scale || LIS2DH12_NM_10bit != dev.resolution)
118 {
119 err_code |= RD_ERROR_INVALID_STATE;
120 }
121 else
122 {
123 // Calculate positive diffs of each axes and compare to expected change
124 for (size_t ii = 0; ii < NUM_AXIS; ii++)
125 {
126 int16_t diff = new->i16bit[ii] - old->i16bit[ii];
127 //Compensate justification, check absolute difference
128 diff /= NM_BIT_DIVEDER;
129
130 if (0 > diff) { diff = 0 - diff; }
131
133 {
134 LOGD ("diff < min = %d\r\n", diff);
135 err_code |= RD_ERROR_SELFTEST;
136 }
137
139 {
140 LOGD ("diff > max = %d\r\n", diff);
141 err_code |= RD_ERROR_SELFTEST;
142 }
143 }
144 }
145
146 return err_code;
147}
148
149static rd_status_t dev_ctx_init (const rd_bus_t bus,
150 const uint8_t handle)
151{
152 rd_status_t err_code = RD_SUCCESS;
153
154 switch (bus)
155 {
156 case RD_BUS_SPI:
157 dev.ctx.write_reg = &ri_spi_lis2dh12_write;
158 dev.ctx.read_reg = &ri_spi_lis2dh12_read;
159 break;
160
161 case RD_BUS_I2C:
162 err_code |= RD_ERROR_NOT_IMPLEMENTED;
163 break;
164
165 default:
166 err_code |= RD_ERROR_NOT_SUPPORTED;
167 break;
168 }
169
170 dev.handle = handle;
171 dev.ctx.handle = &dev.handle;
173 return err_code;
174}
175
176static rd_status_t check_whoami (void)
177{
178 rd_status_t err_code = RD_SUCCESS;
179 uint8_t whoamI = 0;
180 lis2dh12_device_id_get (&dev.ctx, &whoamI);
181
182 if (whoamI != LIS2DH12_ID)
183 {
184 err_code |= RD_ERROR_NOT_FOUND;
185 }
186
187 return err_code;
188}
189
190static rd_status_t clear_sensor_state (void)
191{
192 rd_status_t err_code = RD_SUCCESS;
193 int32_t lis_ret_code = LIS_SUCCESS;
194 float ths = 0;
195 // Disable FIFO, activity
196 err_code |= ri_lis2dh12_fifo_use (false);
197 err_code |= ri_lis2dh12_fifo_interrupt_use (false);
198 err_code |= ri_lis2dh12_activity_interrupt_use (false, &ths);
199 // Enable temperature sensor
200 lis_ret_code |= lis2dh12_temperature_meas_set (&dev.ctx, LIS2DH12_TEMP_ENABLE);
201 // Disable Block Data Update, allow values to update even if old is not read
202 lis_ret_code |= lis2dh12_block_data_update_set (&dev.ctx, PROPERTY_ENABLE);
203 // Disable filtering
204 lis_ret_code |= lis2dh12_high_pass_on_outputs_set (&dev.ctx, PROPERTY_DISABLE);
205
206 if (LIS_SUCCESS != lis_ret_code)
207 {
208 err_code |= RD_ERROR_INTERNAL;
209 }
210
211 return err_code;
212}
213
214static rd_status_t selftest (void)
215{
216 LOGD ("begin\r\n");
217 axis3bit16_t data_raw_acceleration_old = {0};
218 axis3bit16_t data_raw_acceleration_new = {0};
219 int32_t lis_ret_code = LIS_SUCCESS;
220 rd_status_t err_code = RD_SUCCESS;
221 // Set Output Data Rate for self-test
222 dev.samplerate = LIS2DH12_ODR_400Hz;
223 lis2dh12_data_rate_set (&dev.ctx, dev.samplerate);
224 // Set full scale to 2G for self-test
225 dev.scale = LIS2DH12_2g;
226 lis2dh12_full_scale_set (&dev.ctx, dev.scale);
227 // Set device in 10 bit mode
228 dev.resolution = LIS2DH12_NM_10bit;
229 lis2dh12_operating_mode_set (&dev.ctx, dev.resolution);
230 // Run self-test
231 // turn self-test off.
232 dev.selftest = LIS2DH12_ST_DISABLE;
233 lis_ret_code = lis2dh12_self_test_set (&dev.ctx, dev.selftest);
234 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
235 lis2dh12_get_samples_selftest (&data_raw_acceleration_old);
236 dev.selftest = LIS2DH12_ST_POSITIVE;
237 lis2dh12_self_test_set (&dev.ctx, dev.selftest);
238 lis2dh12_get_samples_selftest (&data_raw_acceleration_new);
239 lis_ret_code = lis2dh12_verify_selftest (&data_raw_acceleration_new,
240 &data_raw_acceleration_old);
241 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_SELFTEST;
242 LOGD ("selftest = LIS2DH12_ST_POSITIVE.Error = %08x\r\n", err_code);
243 dev.selftest = LIS2DH12_ST_NEGATIVE;
244 lis2dh12_self_test_set (&dev.ctx, dev.selftest);
245 lis2dh12_get_samples_selftest (&data_raw_acceleration_new);
246 lis_ret_code = lis2dh12_verify_selftest (&data_raw_acceleration_new,
247 &data_raw_acceleration_old);
248 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_SELFTEST;
249 LOGD ("selftest = LIS2DH12_ST_NEGATIVE.Error = %08x\r\n", err_code);
250 // turn self-test off, keep error code in case we "lose" sensor after self-test
251 dev.selftest = LIS2DH12_ST_DISABLE;
252 lis_ret_code = lis2dh12_self_test_set (&dev.ctx, dev.selftest);
253 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
254 // Turn accelerometer off
255 dev.samplerate = LIS2DH12_POWER_DOWN;
256 lis_ret_code = lis2dh12_data_rate_set (&dev.ctx, dev.samplerate);
257 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
258 LOGD ("end. Error = %08x\r\n", err_code);
259 return err_code;
260}
261
262rd_status_t ri_lis2dh12_init (rd_sensor_t * p_sensor, rd_bus_t bus, uint8_t handle)
263{
264 rd_status_t err_code = RD_SUCCESS;
265 LOGD ("begin\r\n");
266
267 if (NULL == p_sensor)
268 {
269 err_code |= RD_ERROR_NULL;
270 LOGD ("p_sensor. Error = %08x\r\n", err_code);
271 }
272 else if (rd_sensor_is_init (p_sensor))
273 {
274 err_code |= RD_ERROR_INVALID_STATE;
275 LOGD ("write_reg. Error = %08x\r\n", err_code);
276 }
277 else
278 {
279 err_code |= dev_ctx_init (bus, handle);
280 LOGD ("dev_ctx_init. Error = %08x\r\n", err_code);
281 rd_sensor_initialize (p_sensor);
282 p_sensor->name = m_acc_name;
283
284 if (RD_SUCCESS == err_code)
285 {
286 err_code |= ri_delay_ms (PWRON_DELAY_MS);
287 }
288
289 if (RD_SUCCESS == err_code)
290 {
291 err_code |= check_whoami();
292 LOGD ("check_whoami. Error = %08x\r\n", err_code);
293 }
294
295 if (RD_SUCCESS == err_code)
296 {
297 err_code |= clear_sensor_state();
298 LOGD ("clear_sensor_state. Error = %08x\r\n", err_code);
299 }
300
301 if (RD_SUCCESS == err_code)
302 {
303 err_code |= selftest();
304 LOGD ("selftest. Error = %08x\r\n", err_code);
305 }
306
307 if (RD_SUCCESS == err_code)
308 {
309 p_sensor->init = ri_lis2dh12_init;
310 p_sensor->uninit = ri_lis2dh12_uninit;
317 p_sensor->dsp_set = ri_lis2dh12_dsp_set;
318 p_sensor->dsp_get = ri_lis2dh12_dsp_get;
319 p_sensor->mode_set = ri_lis2dh12_mode_set;
320 p_sensor->mode_get = ri_lis2dh12_mode_get;
321 p_sensor->data_get = ri_lis2dh12_data_get;
328 p_sensor->provides.datas.acceleration_x_g = 1;
329 p_sensor->provides.datas.acceleration_y_g = 1;
330 p_sensor->provides.datas.acceleration_z_g = 1;
331 p_sensor->provides.datas.temperature_c = 1;
333 }
334 else
335 {
336 rd_sensor_uninitialize (p_sensor);
337 memset (&dev, 0, sizeof (dev));
338 }
339 }
340
341 LOGD ("end. Error = %08x\r\n", err_code);
342 return err_code;
343}
344
345/*
346 * Lis2dh12 does not have a proper softreset (boot does not reset all registers)
347 * Therefore just stop sampling
348 */
350 rd_bus_t bus, uint8_t handle)
351{
352 rd_status_t err_code = RD_SUCCESS;
353
354 if (NULL == p_sensor)
355 {
356 err_code |= RD_ERROR_NULL;
357 }
358 else
359 {
360 rd_sensor_uninitialize (p_sensor);
361 dev.samplerate = LIS2DH12_POWER_DOWN;
362 //LIS2DH12 function returns SPI write result which is rd_status_t
363 int32_t lis_ret_code = lis2dh12_data_rate_set (& (dev.ctx), dev.samplerate);
364 memset (&dev, 0, sizeof (dev));
365
366 if (LIS_SUCCESS != lis_ret_code)
367 {
368 err_code |= RD_ERROR_INTERNAL;
369 }
370 }
371
372 return err_code;
373}
374
382{
383 if (NULL == samplerate) { return RD_ERROR_NULL; }
384
386 rd_status_t err_code = RD_SUCCESS;
387 int32_t lis_ret_code;
388
389 if (RD_SENSOR_CFG_NO_CHANGE == *samplerate) {}
390 else if (RD_SENSOR_CFG_MIN == *samplerate) { dev.samplerate = LIS2DH12_ODR_1Hz; }
391 else if (RD_SENSOR_CFG_MAX == *samplerate) { dev.samplerate = LIS2DH12_ODR_5kHz376_LP_1kHz344_NM_HP; }
392 else if (RD_SENSOR_CFG_DEFAULT == *samplerate) { dev.samplerate = LIS2DH12_ODR_1Hz; }
393 else if (1 == *samplerate) { dev.samplerate = LIS2DH12_ODR_1Hz; }
394 else if (10 >= *samplerate) { dev.samplerate = LIS2DH12_ODR_10Hz; }
395 else if (25 >= *samplerate) { dev.samplerate = LIS2DH12_ODR_25Hz; }
396 else if (50 >= *samplerate) { dev.samplerate = LIS2DH12_ODR_50Hz; }
397 else if (100 >= *samplerate) { dev.samplerate = LIS2DH12_ODR_100Hz; }
398 else if (200 >= *samplerate) { dev.samplerate = LIS2DH12_ODR_200Hz; }
399 else if (RD_SENSOR_CFG_CUSTOM_1 == *samplerate) { dev.samplerate = LIS2DH12_ODR_400Hz; }
400 else if (RD_SENSOR_CFG_CUSTOM_2 == *samplerate) { dev.samplerate = LIS2DH12_ODR_1kHz620_LP; }
401 // This is equal to LIS2DH12_ODR_5kHz376_LP
402 else if (RD_SENSOR_CFG_CUSTOM_3 == *samplerate) { dev.samplerate = LIS2DH12_ODR_5kHz376_LP_1kHz344_NM_HP; }
403 else { *samplerate = RD_SENSOR_ERR_NOT_SUPPORTED; err_code |= RD_ERROR_NOT_SUPPORTED; }
404
405 if (RD_SUCCESS == err_code)
406 {
407 lis_ret_code = lis2dh12_data_rate_set (& (dev.ctx), dev.samplerate);
408 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
409 err_code |= ri_lis2dh12_samplerate_get (samplerate);
410 }
411
412 return err_code;
413}
414
415/*
416 *. Read sample rate to pointer
417 */
419{
420 if (NULL == samplerate) { return RD_ERROR_NULL; }
421
422 rd_status_t err_code = RD_SUCCESS;
423 int32_t lis_ret_code;
424 lis_ret_code = lis2dh12_data_rate_get (& (dev.ctx), &dev.samplerate);
425 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
426
427 switch (dev.samplerate)
428 {
429 case LIS2DH12_ODR_1Hz:
430 *samplerate = 1;
431 break;
432
433 case LIS2DH12_ODR_10Hz:
434 *samplerate = 10;
435 break;
436
437 case LIS2DH12_ODR_25Hz:
438 *samplerate = 25;
439 break;
440
441 case LIS2DH12_ODR_50Hz:
442 *samplerate = 50;
443 break;
444
445 case LIS2DH12_ODR_100Hz:
446 *samplerate = 100;
447 break;
448
449 case LIS2DH12_ODR_200Hz:
450 *samplerate = 200;
451 break;
452
453 case LIS2DH12_ODR_400Hz:
454 *samplerate = RD_SENSOR_CFG_CUSTOM_1;
455 break;
456
457 case LIS2DH12_ODR_5kHz376_LP_1kHz344_NM_HP:
458 *samplerate = RD_SENSOR_CFG_MAX;
459 break;
460
461 case LIS2DH12_ODR_1kHz620_LP:
462 *samplerate = RD_SENSOR_CFG_CUSTOM_2;
463 break;
464
465 default:
466 *samplerate = RD_SENSOR_ERR_NOT_SUPPORTED;
467 err_code |= RD_ERROR_INTERNAL;
468 }
469
470 return err_code;
471}
472
477{
478 if (NULL == resolution) { return RD_ERROR_NULL; }
479
481 rd_status_t err_code = RD_SUCCESS;
482 int32_t lis_ret_code;
483
484 if (RD_SENSOR_CFG_NO_CHANGE == *resolution) { }
485 else if (RD_SENSOR_CFG_MIN == *resolution) { dev.resolution = LIS2DH12_LP_8bit; }
486 else if (RD_SENSOR_CFG_MAX == *resolution) { dev.resolution = LIS2DH12_HR_12bit; }
487 else if (RD_SENSOR_CFG_DEFAULT == *resolution) { dev.resolution = LIS2DH12_NM_10bit; }
488 else if (8 >= *resolution) { dev.resolution = LIS2DH12_LP_8bit; }
489 else if (10 >= *resolution) { dev.resolution = LIS2DH12_NM_10bit; }
490 else if (12 >= *resolution) { dev.resolution = LIS2DH12_HR_12bit; }
491 else { *resolution = RD_SENSOR_ERR_NOT_SUPPORTED; err_code |= RD_ERROR_NOT_SUPPORTED; }
492
493 if (RD_SUCCESS == err_code)
494 {
495 lis_ret_code = lis2dh12_operating_mode_set (& (dev.ctx), dev.resolution);
496 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
497 err_code |= ri_lis2dh12_resolution_get (resolution);
498 }
499
500 return err_code;
501}
502
504{
505 if (NULL == resolution) { return RD_ERROR_NULL; }
506
507 rd_status_t err_code = RD_SUCCESS;
508 int32_t lis_ret_code;
509 lis_ret_code = lis2dh12_operating_mode_get (& (dev.ctx), &dev.resolution);
510 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
511
512 switch (dev.resolution)
513 {
514 case LIS2DH12_LP_8bit:
515 *resolution = 8;
516 break;
517
518 case LIS2DH12_NM_10bit:
519 *resolution = 10;
520 break;
521
522 case LIS2DH12_HR_12bit:
523 *resolution = 12;
524 break;
525
526 default:
527 *resolution = RD_SENSOR_ERR_INVALID;
528 err_code |= RD_ERROR_INTERNAL;
529 break;
530 }
531
532 return err_code;
533}
534
539{
540 if (NULL == scale) { return RD_ERROR_NULL; }
541
543 rd_status_t err_code = RD_SUCCESS;
544 int32_t lis_ret_code;
545
546 if (RD_SENSOR_CFG_NO_CHANGE == *scale) { }
547 else if (RD_SENSOR_CFG_MIN == *scale) { dev.scale = LIS2DH12_2g; }
548 else if (RD_SENSOR_CFG_MAX == *scale) { dev.scale = LIS2DH12_16g; }
549 else if (RD_SENSOR_CFG_DEFAULT == *scale) { dev.scale = LIS2DH12_2g; }
550 else if (2 >= *scale) { dev.scale = LIS2DH12_2g; }
551 else if (4 >= *scale) { dev.scale = LIS2DH12_4g; }
552 else if (8 >= *scale) { dev.scale = LIS2DH12_8g; }
553 else if (16 >= *scale) { dev.scale = LIS2DH12_16g; }
554 else
555 {
557 err_code |= RD_ERROR_NOT_SUPPORTED;
558 }
559
560 if (RD_SUCCESS == err_code)
561 {
562 lis_ret_code = lis2dh12_full_scale_set (& (dev.ctx), dev.scale);
563 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
564 err_code |= ri_lis2dh12_scale_get (scale);
565 }
566
567 return err_code;
568}
569
571{
572 if (NULL == scale) { return RD_ERROR_NULL; }
573
574 rd_status_t err_code = RD_SUCCESS;
575 int32_t lis_ret_code;
576 lis_ret_code = lis2dh12_full_scale_get (& (dev.ctx), &dev.scale);
577 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
578
579 switch (dev.scale)
580 {
581 case LIS2DH12_2g:
582 *scale = 2;
583 break;
584
585 case LIS2DH12_4g:
586 *scale = 4;
587 break;
588
589 case LIS2DH12_8g:
590 *scale = 8;
591 break;
592
593 case LIS2DH12_16g:
594 *scale = 16;
595 break;
596
597 default:
599 err_code |= RD_ERROR_INTERNAL;
600 }
601
602 return err_code;
603}
604
605/*
606 http://www.st.com/content/ccc/resource/technical/document/application_note/60/52/bd/69/28/f4/48/2b/DM00165265.pdf/files/DM00165265.pdf/jcr:content/translations/en.DM00165265.pdf
607 CTRL2 DCF [1:0] HP cutoff frequency [Hz]
608 00 ODR/50
609 01 ODR/100
610 10 ODR/9
611 11 ODR/400
612*/
613rd_status_t ri_lis2dh12_dsp_set (uint8_t * dsp, uint8_t * parameter)
614{
615 if (NULL == dsp || NULL == parameter) { return RD_ERROR_NULL; }
616
618 rd_status_t err_code = RD_SUCCESS;
619 int32_t lis_ret_code;
620 // Read original values in case one is NO_CHANGE and other should be adjusted.
621 uint8_t orig_dsp, orig_param;
622 err_code |= ri_lis2dh12_dsp_get (&orig_dsp, &orig_param);
623
624 if (RD_SENSOR_CFG_NO_CHANGE == *dsp) { *dsp = orig_dsp; }
625
626 if (RD_SENSOR_CFG_NO_CHANGE == *parameter) { *parameter = orig_param; }
627
628 if (RD_SENSOR_DSP_HIGH_PASS == *dsp)
629 {
630 lis2dh12_hpcf_t hpcf;
631
632 // Set default here to avoid duplicate value error in switch-case
633 if (RD_SENSOR_CFG_DEFAULT == *parameter) { *parameter = 0; }
634
635 switch (*parameter)
636 {
638 case 0:
639 hpcf = LIS2DH12_LIGHT;
640 *parameter = 0;
641 break;
642
643 case 1:
644 hpcf = LIS2DH12_MEDIUM;
645 break;
646
647 case 2:
648 hpcf = LIS2DH12_STRONG;
649 break;
650
652 case 3:
653 hpcf = LIS2DH12_AGGRESSIVE;
654 *parameter = 3;
655 break;
656
657 default :
658 *parameter = RD_ERROR_NOT_SUPPORTED;
660 }
661
662 lis_ret_code = lis2dh12_high_pass_bandwidth_set (& (dev.ctx), hpcf);
663 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
664 lis_ret_code = lis2dh12_high_pass_mode_set (& (dev.ctx), LIS2DH12_NORMAL);
665 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
666 lis_ret_code = lis2dh12_high_pass_on_outputs_set (& (dev.ctx), PROPERTY_ENABLE);
667 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
668 return err_code;
669 }
670
671 // Has no effect, but kept for future-proofness.
672 if (RD_SENSOR_CFG_DEFAULT == *dsp)
673 {
674 *dsp = RD_SENSOR_DSP_LAST;
675 }
676
677 if (RD_SENSOR_DSP_LAST == *dsp)
678 {
679 lis_ret_code = lis2dh12_high_pass_on_outputs_set (& (dev.ctx), PROPERTY_DISABLE);
680 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
681 *dsp = RD_SENSOR_DSP_LAST;
682 return err_code;
683 }
684
686}
687
688rd_status_t ri_lis2dh12_dsp_get (uint8_t * dsp, uint8_t * parameter)
689{
690 rd_status_t err_code = RD_SUCCESS;
691 int32_t lis_ret_code;
692 uint8_t mode;
693 lis2dh12_hpcf_t hpcf;
694 lis_ret_code = lis2dh12_high_pass_bandwidth_get (& (dev.ctx), &hpcf);
695 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
696 lis_ret_code = lis2dh12_high_pass_on_outputs_get (& (dev.ctx), &mode);
697 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
698
699 if (mode) { *dsp = RD_SENSOR_DSP_HIGH_PASS; }
700 else { *dsp = RD_SENSOR_DSP_LAST; }
701
702 switch (hpcf)
703 {
704 case LIS2DH12_LIGHT:
705 *parameter = 0;
706 break;
707
708 case LIS2DH12_MEDIUM:
709 *parameter = 1;
710 break;
711
712 case LIS2DH12_STRONG:
713 *parameter = 2;
714 break;
715
716 case LIS2DH12_AGGRESSIVE:
717 *parameter = 3;
718 break;
719
720 default:
721 *parameter = RD_SENSOR_ERR_NOT_SUPPORTED;
722 return RD_ERROR_INTERNAL;
723 }
724
725 return err_code;
726}
727
729{
730 if (NULL == mode) { return RD_ERROR_NULL; }
731
732 int32_t lis_ret_code;
733 rd_status_t err_code = RD_SUCCESS;
734
735 if (RD_SENSOR_CFG_SINGLE == *mode)
736 {
737 // Do nothing if sensor is in continuous mode
738 uint8_t current_mode;
739 ri_lis2dh12_mode_get (&current_mode);
740
741 if (RD_SENSOR_CFG_CONTINUOUS == current_mode)
742 {
745 }
746
747 // Start sensor at 400 Hz (highest common samplerate)
748 // and wait for 7/ODR ms for turn-on (?) NOTE: 7 s / 400 just to be on safe side.
749 // Refer to LIS2DH12 datasheet p.16.
750 dev.samplerate = LIS2DH12_ODR_400Hz;
751 lis_ret_code = lis2dh12_data_rate_set (& (dev.ctx), dev.samplerate);
752 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
753 ri_delay_ms ( (7000 / 400) + 1);
755 dev.samplerate = LIS2DH12_POWER_DOWN;
756 lis_ret_code = lis2dh12_data_rate_set (& (dev.ctx), dev.samplerate);
757 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
758 *mode = RD_SENSOR_CFG_SLEEP;
759 return err_code;
760 }
761
762 // Do not store power down mode to dev structure, so we can continue at previous data rate
763 // when mode is set to continous.
764 if (RD_SENSOR_CFG_SLEEP == *mode)
765 {
766 dev.mode = *mode;
767 lis_ret_code = lis2dh12_data_rate_set (& (dev.ctx), LIS2DH12_POWER_DOWN);
768 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
769 }
770 else if (RD_SENSOR_CFG_CONTINUOUS == *mode)
771 {
772 dev.mode = *mode;
773 lis_ret_code = lis2dh12_data_rate_set (& (dev.ctx), dev.samplerate);
774 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
775 }
776 else { err_code |= RD_ERROR_INVALID_PARAM; }
777
778 return err_code;
779}
780
782{
783 if (NULL == mode) { return RD_ERROR_NULL; }
784
785 switch (dev.mode)
786 {
788 *mode = RD_SENSOR_CFG_SLEEP;
789 break;
790
793 break;
794
795 default:
797 return RD_ERROR_INTERNAL;
798 }
799
800 return RD_SUCCESS;
801}
802
810static rd_status_t rawToC (const uint8_t * const raw_temperature,
811 float * temperature)
812{
813 rd_status_t err_code = RD_SUCCESS;
814 int16_t value = (raw_temperature[1] * 256) + raw_temperature[0];
815
816 switch (dev.resolution)
817 {
818 case LIS2DH12_LP_8bit:
819 *temperature = lis2dh12_from_lsb_lp_to_celsius (value);
820 break;
821
822 case LIS2DH12_NM_10bit:
823 *temperature = lis2dh12_from_lsb_nm_to_celsius (value);
824 break;
825
826 case LIS2DH12_HR_12bit:
827 *temperature = lis2dh12_from_lsb_hr_to_celsius (value);
828 break;
829
830 default:
831 *temperature = RD_FLOAT_INVALID;
832 err_code |= RD_ERROR_INTERNAL;
833 break;
834 }
835
836 return err_code;
837}
838
846static rd_status_t rawToMg (const axis3bit16_t * raw_acceleration,
847 float * acceleration)
848{
849 rd_status_t err_code = RD_SUCCESS;
850
851 for (size_t ii = 0; ii < 3; ii++)
852 {
853 switch (dev.scale)
854 {
855 case LIS2DH12_2g:
856 switch (dev.resolution)
857 {
858 case LIS2DH12_LP_8bit:
859 acceleration[ii] = lis2dh12_from_fs2_lp_to_mg (raw_acceleration->i16bit[ii]);
860 break;
861
862 case LIS2DH12_NM_10bit:
863 acceleration[ii] = lis2dh12_from_fs2_nm_to_mg (raw_acceleration->i16bit[ii]);
864 break;
865
866 case LIS2DH12_HR_12bit:
867 acceleration[ii] = lis2dh12_from_fs2_hr_to_mg (raw_acceleration->i16bit[ii]);
868 break;
869
870 default:
871 acceleration[ii] = RD_FLOAT_INVALID;
872 err_code |= RD_ERROR_INTERNAL;
873 break;
874 }
875
876 break;
877
878 case LIS2DH12_4g:
879 switch (dev.resolution)
880 {
881 case LIS2DH12_LP_8bit:
882 acceleration[ii] = lis2dh12_from_fs4_lp_to_mg (raw_acceleration->i16bit[ii]);
883 break;
884
885 case LIS2DH12_NM_10bit:
886 acceleration[ii] = lis2dh12_from_fs4_nm_to_mg (raw_acceleration->i16bit[ii]);
887 break;
888
889 case LIS2DH12_HR_12bit:
890 acceleration[ii] = lis2dh12_from_fs4_hr_to_mg (raw_acceleration->i16bit[ii]);
891 break;
892
893 default:
894 acceleration[ii] = RD_FLOAT_INVALID;
895 err_code |= RD_ERROR_INTERNAL;
896 break;
897 }
898
899 break;
900
901 case LIS2DH12_8g:
902 switch (dev.resolution)
903 {
904 case LIS2DH12_LP_8bit:
905 acceleration[ii] = lis2dh12_from_fs8_lp_to_mg (raw_acceleration->i16bit[ii]);
906 break;
907
908 case LIS2DH12_NM_10bit:
909 acceleration[ii] = lis2dh12_from_fs8_nm_to_mg (raw_acceleration->i16bit[ii]);
910 break;
911
912 case LIS2DH12_HR_12bit:
913 acceleration[ii] = lis2dh12_from_fs8_hr_to_mg (raw_acceleration->i16bit[ii]);
914 break;
915
916 default:
917 acceleration[ii] = RD_FLOAT_INVALID;
918 err_code |= RD_ERROR_INTERNAL;
919 break;
920 }
921
922 break;
923
924 case LIS2DH12_16g:
925 switch (dev.resolution)
926 {
927 case LIS2DH12_LP_8bit:
928 acceleration[ii] = lis2dh12_from_fs16_lp_to_mg (raw_acceleration->i16bit[ii]);
929 break;
930
931 case LIS2DH12_NM_10bit:
932 acceleration[ii] = lis2dh12_from_fs16_nm_to_mg (raw_acceleration->i16bit[ii]);
933 break;
934
935 case LIS2DH12_HR_12bit:
936 acceleration[ii] = lis2dh12_from_fs16_hr_to_mg (raw_acceleration->i16bit[ii]);
937 break;
938
939 default:
940 acceleration[ii] = RD_FLOAT_INVALID;
941 err_code |= RD_ERROR_INTERNAL;
942 break;
943 }
944
945 break;
946
947 default:
948 acceleration[ii] = RD_FLOAT_INVALID;
949 err_code |= RD_ERROR_INTERNAL;
950 break;
951 }
952 }
953
954 return err_code;
955}
956
958 data)
959{
960 if (NULL == data) { return RD_ERROR_NULL; }
961
962 rd_status_t err_code = RD_SUCCESS;
963 int32_t lis_ret_code;
964 axis3bit16_t raw_acceleration;
965 uint8_t raw_temperature[2];
966 memset (raw_acceleration.u8bit, 0x00, 3 * sizeof (int16_t));
967 lis_ret_code = lis2dh12_acceleration_raw_get (& (dev.ctx), raw_acceleration.u8bit);
968 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
969 lis_ret_code = lis2dh12_temperature_raw_get (& (dev.ctx), raw_temperature);
970 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
971 // Compensate data with resolution, scale
972 float acceleration[3];
973 float temperature;
974 err_code |= rawToMg (&raw_acceleration, acceleration);
975 err_code |= rawToC (raw_temperature, &temperature);
976 uint8_t mode;
977 err_code |= ri_lis2dh12_mode_get (&mode);
978
979 if (RD_SENSOR_CFG_SLEEP == mode) { data->timestamp_ms = dev.tsample; }
980 else if (RD_SENSOR_CFG_CONTINUOUS == mode)
981 {
983 }
985
986 // If we have valid data, return it.
988 && RD_SUCCESS == err_code)
989 {
990 rd_sensor_data_t d_acceleration;
991 float values[4];
992 rd_sensor_data_fields_t acc_fields = {.bitfield = 0};
993 d_acceleration.data = values;
994 acc_fields.datas.acceleration_x_g = 1;
995 acc_fields.datas.acceleration_y_g = 1;
996 acc_fields.datas.acceleration_z_g = 1;
997 acc_fields.datas.temperature_c = 1;
998 //Convert mG to G.
999 values[0] = acceleration[0] / 1000.0;
1000 values[1] = acceleration[1] / 1000.0;
1001 values[2] = acceleration[2] / 1000.0;
1002 values[3] = temperature;
1003 d_acceleration.valid = acc_fields;
1004 d_acceleration.fields = acc_fields;
1006 &d_acceleration,
1007 data->fields);
1008 }
1009
1010 return err_code;
1011}
1012
1013// TODO: State checks
1015{
1016 lis2dh12_fm_t mode;
1017 int32_t lis_ret_code;
1018 rd_status_t err_code = RD_SUCCESS;
1019
1020 if (enable) { mode = LIS2DH12_DYNAMIC_STREAM_MODE; }
1021 else { mode = LIS2DH12_BYPASS_MODE; }
1022
1023 lis_ret_code = lis2dh12_fifo_set (& (dev.ctx), enable);
1024 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1025 lis_ret_code = lis2dh12_fifo_mode_set (& (dev.ctx), mode);
1026 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1027 return err_code;
1028}
1029
1030//TODO * return: RD_INVALID_STATE if FIFO is not in use
1031rd_status_t ri_lis2dh12_fifo_read (size_t * num_elements,
1032 rd_sensor_data_t * p_data)
1033{
1034 if (NULL == num_elements || NULL == p_data) { return RD_ERROR_NULL; }
1035
1036 uint8_t elements = 0;
1037 rd_status_t err_code = RD_SUCCESS;
1038 int32_t lis_ret_code;
1039 lis_ret_code = lis2dh12_fifo_data_level_get (& (dev.ctx), &elements);
1040 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1041
1042 if (!elements)
1043 {
1044 *num_elements = 0;
1045 return RD_SUCCESS;
1046 }
1047
1048 // 31 FIFO + latest
1049 elements++;
1050
1051 // Do not read more than buffer size
1052 if (elements > *num_elements) { elements = *num_elements; }
1053
1054 // get current time
1056 // Read all elements
1057 axis3bit16_t raw_acceleration;
1058 float acceleration[3];
1059
1060 for (size_t ii = 0; ii < elements; ii++)
1061 {
1062 lis_ret_code = lis2dh12_acceleration_raw_get (& (dev.ctx), raw_acceleration.u8bit);
1063 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1064 // Compensate data with resolution, scale
1065 err_code |= rawToMg (&raw_acceleration, acceleration);
1066 rd_sensor_data_t d_acceleration;
1067 rd_sensor_data_fields_t acc_fields = {.bitfield = 0};
1068 acc_fields.datas.acceleration_x_g = 1;
1069 acc_fields.datas.acceleration_y_g = 1;
1070 acc_fields.datas.acceleration_z_g = 1;
1071 //Convert mG to G
1072 acceleration[0] = acceleration[0] / 1000.0;
1073 acceleration[1] = acceleration[1] / 1000.0;
1074 acceleration[2] = acceleration[2] / 1000.0;
1075 d_acceleration.data = acceleration;
1076 d_acceleration.valid = acc_fields;
1077 d_acceleration.fields = acc_fields;
1078 rd_sensor_data_populate (& (p_data[ii]),
1079 &d_acceleration,
1080 p_data[ii].fields);
1081 }
1082
1083 *num_elements = elements;
1084 return err_code;
1085}
1086
1087
1089{
1090 rd_status_t err_code = RD_SUCCESS;
1091 int32_t lis_ret_code;
1092 lis2dh12_ctrl_reg3_t ctrl = { 0 };
1093
1094 if (true == enable)
1095 {
1096 // Setting the FTH [4:0] bit in the FIFO_CTRL_REG (2Eh) register to an N value,
1097 // the number of X, Y and Z data samples that should be read at the rise of the watermark interrupt is up to (N+1).
1098 lis_ret_code = lis2dh12_fifo_watermark_set (& (dev.ctx), 31);
1099 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1100 ctrl.i1_wtm = PROPERTY_ENABLE;
1101 }
1102
1103 lis_ret_code = lis2dh12_pin_int1_config_set (& (dev.ctx), &ctrl);
1104 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1105 return err_code;
1106}
1107
1123rd_status_t ri_lis2dh12_activity_interrupt_use (const bool enable, float * const limit_g)
1124{
1125 rd_status_t err_code = RD_SUCCESS;
1126 int32_t lis_ret_code;
1127 lis2dh12_hp_t high_pass = LIS2DH12_ON_INT1_GEN;
1128 lis2dh12_ctrl_reg6_t ctrl6 = { 0 };
1129 lis2dh12_int1_cfg_t cfg = { 0 };
1130
1131 if (NULL == limit_g)
1132 {
1133 err_code |= RD_ERROR_NULL;
1134 }
1135 else if ( (0 > *limit_g) && enable)
1136 {
1137 err_code |= RD_ERROR_INVALID_PARAM;
1138 }
1139 else if (enable)
1140 {
1141 cfg.xhie = PROPERTY_ENABLE;
1142 cfg.yhie = PROPERTY_ENABLE;
1143 cfg.zhie = PROPERTY_ENABLE;
1144 ctrl6.i2_ia1 = PROPERTY_ENABLE;
1145 /*
1146 Do not enable lower threshold on activity detection, as it would
1147 turn logic into not-active detection.
1148 cfg.xlie = PROPERTY_ENABLE;
1149 cfg.ylie = PROPERTY_ENABLE;
1150 cfg.zlie = PROPERTY_ENABLE;
1151 */
1152 // Adjust for scale
1153 // 1 LSb = 16 mg @ FS = 2 g
1154 // 1 LSb = 32 mg @ FS = 4 g
1155 // 1 LSb = 62 mg @ FS = 8 g
1156 // 1 LSb = 186 mg @ FS = 16 g
1157 uint8_t scale;
1158 uint32_t threshold;
1159 float divisor;
1160 lis_ret_code = ri_lis2dh12_scale_get (&scale);
1161 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1162
1163 switch (scale)
1164 {
1165 case 2:
1166 divisor = 0.016f;
1167 break;
1168
1169 case 4:
1170 divisor = 0.032f;
1171 break;
1172
1173 case 8:
1174 divisor = 0.062f;
1175 break;
1176
1177 case 16:
1178 divisor = 0.186f;
1179 break;
1180
1181 default:
1182 divisor = 0.016f;
1183 break;
1184 }
1185
1186 threshold = (uint32_t) (*limit_g / divisor) + 1;
1187
1188 if (threshold > MOTION_THRESHOLD_MAX)
1189 {
1190 err_code |= RD_ERROR_INVALID_PARAM;
1191 }
1192 else
1193 {
1194 *limit_g = ( (float) threshold) * divisor;
1195 // Configure INTERRUPT 1 Threshold
1196 lis_ret_code = lis2dh12_int1_gen_threshold_set (& (dev.ctx), threshold);
1197 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1198 }
1199 }
1200 else
1201 {
1202 high_pass = LIS2DH12_DISC_FROM_INT_GENERATOR;
1203 }
1204
1205 if (RD_SUCCESS == err_code)
1206 {
1207 // Configure highpass on INTERRUPT 1
1208 lis_ret_code = lis2dh12_high_pass_int_conf_set (& (dev.ctx), high_pass);
1209 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1210 // Configure INTERRUPT 1.
1211 lis_ret_code = lis2dh12_int1_gen_conf_set (& (dev.ctx), &cfg);
1212 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1213 // Route INTERRUPT 1 to PIN 2.
1214 lis_ret_code = lis2dh12_pin_int2_config_set (& (dev.ctx), &ctrl6);
1215 err_code |= (LIS_SUCCESS == lis_ret_code) ? RD_SUCCESS : RD_ERROR_INTERNAL;
1216 }
1217
1218 return err_code;
1219}
1221#endif
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_FATAL
Program should always reset after this.
uint32_t rd_status_t
bitfield for representing errors
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_ERROR_NOT_IMPLEMENTED
Not implemented yet.
#define RD_FLOAT_INVALID
Signal that value should not be used.
#define RD_ERROR_NOT_SUPPORTED
Not supported.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_SELFTEST
Self-test fail.
#define RD_ERROR_NOT_FOUND
Not found.
#define RD_UINT64_INVALID
Signal that value should not be used.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_ERROR_INTERNAL
Internal Error.
#define RI_LIS2DH12_SELFTEST_DIFF_MIN
Minimum counts of self-test change in 10 bit resolution 2 G scale, ref datasheet.
rd_status_t ri_lis2dh12_resolution_set(uint8_t *resolution)
rd_sensor_setup_fp
#define SELF_TEST_SAMPLES_NUM
5 samples
rd_status_t ri_lis2dh12_mode_get(uint8_t *mode)
rd_sensor_setup_fp
#define LIS_SUCCESS
No error in LIS driver.
#define SELF_TEST_DELAY_MS
At least 3 samples at 400 Hz, but recommended value 100.
rd_status_t ri_lis2dh12_samplerate_get(uint8_t *samplerate)
rd_sensor_setup_fp
rd_status_t ri_lis2dh12_dsp_get(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
rd_status_t ri_lis2dh12_fifo_use(const bool enable)
Enable 32-level FIFO in LIS2DH12 If FIFO is enabled, values are stored on LIS2DH12 FIFO and oldest el...
rd_status_t ri_lis2dh12_scale_set(uint8_t *scale)
rd_sensor_setup_fp
rd_status_t ri_lis2dh12_mode_set(uint8_t *mode)
rd_sensor_setup_fp
rd_status_t ri_lis2dh12_dsp_set(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
rd_status_t ri_lis2dh12_samplerate_set(uint8_t *samplerate)
rd_sensor_setup_fp
rd_status_t ri_lis2dh12_fifo_interrupt_use(const bool enable)
Enable FIFO full interrupt on LIS2DH12. Triggers as ACTIVE HIGH interrupt once FIFO has 32 elements.
rd_status_t ri_lis2dh12_uninit(rd_sensor_t *p_sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
rd_status_t ri_lis2dh12_data_get(rd_sensor_data_t *const data)
rd_sensor_data_fp
#define RI_LIS2DH12_SELFTEST_DIFF_MAX
Maximum counts of self-test change in 10 bit resolution 2 G scale, ref datasheet.
rd_status_t ri_lis2dh12_fifo_read(size_t *num_elements, rd_sensor_data_t *p_data)
Read FIFO Reads up to num_elements data points from FIFO and populates pointer data with them.
rd_status_t ri_lis2dh12_init(rd_sensor_t *p_sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
rd_status_t ri_lis2dh12_resolution_get(uint8_t *resolution)
rd_sensor_setup_fp
rd_status_t ri_lis2dh12_activity_interrupt_use(const bool enable, float *const limit_g)
Enable activity interrupt on LIS2DH12.
rd_status_t ri_lis2dh12_scale_get(uint8_t *scale)
rd_sensor_setup_fp
#define RD_SENSOR_DSP_LAST
Return last value from sensor. Parameter: No effect. Use default.
#define RD_SENSOR_ERR_NOT_SUPPORTED
Error code, given parameter is not supported by sensor.
bool rd_sensor_is_init(const rd_sensor_t *const sensor)
Check if given sensor structure is already initialized.
#define RD_SENSOR_CFG_SLEEP
Sensor should go to sleep immediately.
#define RD_SENSOR_CFG_MAX
Configure largest supported and implemented value.
#define RD_SENSOR_CFG_DEFAULT
Default value, always valid for the sensor.
void rd_sensor_uninitialize(rd_sensor_t *const p_sensor)
Mark sensor as uninitialized by calling the generic initialization. Will not clear the name of the se...
rd_status_t rd_sensor_configuration_get(const rd_sensor_t *sensor, rd_sensor_configuration_t *config)
Implementation of ref rd_configuration_fp.
void rd_sensor_initialize(rd_sensor_t *const p_sensor)
Initialize sensor struct with non-null pointers which return RD_ERROR_NOT_INITIALIZED.
#define RD_SENSOR_ERR_INVALID
Error code, given parameter is invalid.
#define RD_SENSOR_CFG_CUSTOM_3
Configuration range is 0...200, i.e. 0 ... 0xC8. Use C9 ... CF as sensor-specific values.
#define RD_SENSOR_CFG_CUSTOM_1
Configuration range is 0...200, i.e. 0 ... 0xC8. Use C9 ... CF as sensor-specific values.
void rd_sensor_data_populate(rd_sensor_data_t *const target, const rd_sensor_data_t *const provided, const rd_sensor_data_fields_t requested)
Populate given target data with data provided by sensor as requested.
rd_status_t rd_sensor_configuration_set(const rd_sensor_t *sensor, rd_sensor_configuration_t *config)
Implementation of ref rd_configuration_fp.
#define RD_SENSOR_CFG_MIN
Configure smallest supported and implemented value.
#define RD_SENSOR_CFG_CONTINUOUS
Sensor will keep sampling at defined sample rate.
#define RD_SENSOR_DSP_HIGH_PASS
High pass sensor values Parameter: coefficient.
#define RD_SENSOR_CFG_NO_CHANGE
Do not change configured value.
rd_bus_t
Type of bus sensor uses.
#define RD_SENSOR_CFG_CUSTOM_2
Configuration range is 0...200, i.e. 0 ... 0xC8. Use C9 ... CF as sensor-specific values.
uint64_t rd_sensor_timestamp_get(void)
Calls the timestamp function and returns its value.
#define RD_SENSOR_CFG_SINGLE
Sensor should go to sleep after single measurement.
@ RD_BUS_SPI
SPI bus.
@ RD_BUS_I2C
I2C bus.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Ruuvi sensor interface Lifecycle: Beta
#define PWRON_DELAY_MS
Milliseconds from poweron to sensor rdy. 5ms typ.
#define LOGD(fmt,...)
#define NM_BIT_DIVEDER
Normal mode uses 10 bits in 16 bit field, leading to 2^6 factor in results.
#define VERIFY_SENSOR_SLEEPS()
Macro for checking that sensor is in sleep mode before configuration.
#define MOTION_THRESHOLD_MAX
Highest threshold value allowed.
#define NUM_AXIS
X, Y, Z.
int32_t ri_spi_lis2dh12_write(void *dev_ptr, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
int32_t ri_spi_lis2dh12_read(void *dev_ptr, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
rd_status_t ri_delay_ms(uint32_t time)
Delay a given number of milliseconds.
unsigned int acceleration_x_g
Acceleration along X-axis, gravities.
unsigned int temperature_c
Temperature, celcius.
unsigned int acceleration_z_g
Acceleration along Z-axis, gravities.
unsigned int acceleration_y_g
Acceleration along Y-axis, gravities.
Generic sensor data struct.
float * data
Data of sensor. Must contain as many elements as fields has bits set.
uint64_t timestamp_ms
Timestamp of the event, rd_sensor_timestamp_get.
rd_sensor_data_fields_t valid
Listing of valid data in this sample.
rd_sensor_data_fields_t fields
Description of datafields which may be contained in this sample.
Interface to sensor. Some sensors can implement additional functions. The additional functions are de...
rd_sensor_data_fp data_get
rd_sensor_data_fp
rd_configuration_fp configuration_set
rd_configuration_fp
rd_sensor_setup_fp samplerate_get
rd_sensor_setup_fp
rd_sensor_setup_fp resolution_get
rd_sensor_setup_fp
rd_sensor_init_fp uninit
rd_sensor_init_fp
rd_configuration_fp configuration_get
rd_configuration_fp
rd_sensor_dsp_fp dsp_get
rd_sensor_dsp_fp
rd_sensor_data_fields_t provides
Description of data fields the sensor is able to provide.
rd_sensor_dsp_fp dsp_set
rd_sensor_dsp_fp
rd_sensor_setup_fp mode_set
rd_sensor_setup_fp
const char * name
Sensor human-readable name. Should be at most 8 bytes long.
rd_sensor_fifo_read_fp fifo_read
rd_sensor_level_interrupt_use_fp
rd_sensor_fifo_enable_fp fifo_interrupt_enable
rd_sensor_level_interrupt_use_fp
rd_sensor_level_interrupt_use_fp level_interrupt_set
rd_sensor_level_interrupt_use_fp
rd_sensor_setup_fp mode_get
rd_sensor_setup_fp
rd_sensor_setup_fp samplerate_set
rd_sensor_setup_fp
rd_sensor_fifo_enable_fp fifo_enable
rd_sensor_fifo_enable_fp
rd_sensor_init_fp init
rd_sensor_init_fp
rd_sensor_setup_fp scale_set
rd_sensor_setup_fp
rd_sensor_setup_fp resolution_set
rd_sensor_setup_fp
rd_sensor_setup_fp scale_get
rd_sensor_setup_fp
context for LIS2DH12
uint64_t tsample
Time of sample, rd_sensor_timestamp_get.
uint8_t handle
Device handle, SPI GPIO pin or I2C address.
lis2dh12_op_md_t resolution
Resolution, bits. 8, 10, or 12.
uint8_t mode
Operating mode. Sleep, single or continuous.
lis2dh12_st_t selftest
Self-test enabled, positive, negative or disabled.
stmdev_ctx_t ctx
Driver control structure.
lis2dh12_odr_t samplerate
Sample rate, 1 ... 200, or custom values for higher.
lis2dh12_fs_t scale
Scale, gravities. 2, 4, 8 or 16.
Union to access sensor data.
uint32_t bitfield
Bitfield used to access sensor data.
rd_sensor_data_bitfield_t datas
Structured data field.