ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_interface_lis2dh12.c
Go to the documentation of this file.
2 #if (RI_LIS2DH12_ENABLED || DOXYGEN)
3 #include "ruuvi_driver_error.h"
4 #include "ruuvi_driver_sensor.h"
8 #include "ruuvi_interface_log.h"
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 
63 typedef union
64 {
65  int16_t i16bit[NUM_AXIS];
66  uint8_t u8bit[2 * NUM_AXIS];
67 } axis3bit16_t;
68 
70 typedef union
71 {
72  int16_t i16bit;
73  uint8_t u8bit[2];
74 } axis1bit16_t;
75 
79 #ifndef CEEDLING
80 static
81 #endif
82 ri_lis2dh12_dev dev = {0};
83 
84 static const char m_acc_name[] = "LIS2DH12";
85 
86 static 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
112 static 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 
149 static 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 
176 static 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 
190 static 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 
214 static 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 
262 rd_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;
315  p_sensor->scale_set = ri_lis2dh12_scale_set;
316  p_sensor->scale_get = ri_lis2dh12_scale_get;
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;
324  p_sensor->fifo_enable = ri_lis2dh12_fifo_use;
326  p_sensor->fifo_read = ri_lis2dh12_fifo_read;
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 */
613 rd_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  {
637  case RD_SENSOR_CFG_MIN:
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 
651  case RD_SENSOR_CFG_MAX:
652  case 3:
653  hpcf = LIS2DH12_AGGRESSIVE;
654  *parameter = 3;
655  break;
656 
657  default :
658  *parameter = RD_ERROR_NOT_SUPPORTED;
659  return 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 
685  return RD_ERROR_NOT_SUPPORTED;
686 }
687 
688 rd_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  {
743  *mode = RD_SENSOR_CFG_CONTINUOUS;
744  return RD_ERROR_INVALID_STATE;
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  {
787  case RD_SENSOR_CFG_SLEEP:
788  *mode = RD_SENSOR_CFG_SLEEP;
789  break;
790 
792  *mode = RD_SENSOR_CFG_CONTINUOUS;
793  break;
794 
795  default:
797  return RD_ERROR_INTERNAL;
798  }
799 
800  return RD_SUCCESS;
801 }
802 
810 static 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 
846 static 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.
987  if (RD_UINT64_INVALID != data->timestamp_ms
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
1031 rd_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 
1123 rd_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.