ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_driver_sensor_test.c
Go to the documentation of this file.
1 
11 #include "ruuvi_driver_error.h"
12 #include "ruuvi_driver_sensor.h"
13 #include "ruuvi_interface_gpio.h"
16 #include "ruuvi_interface_log.h"
17 #include "ruuvi_interface_rtc.h"
18 #include "ruuvi_interface_yield.h"
20 
21 #include <float.h>
22 #include <stdbool.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <stdio.h>
26 
27 #if RUUVI_RUN_TESTS
28 
29 #define RETURN_ON_ERROR(status) if(status) \
30 { \
31 RD_ERROR_CHECK(RD_ERROR_SELFTEST, ~RD_ERROR_FATAL); \
32 return status; \
33 }
34 #define BITFIELD_MASK (1U)
35 #define MAX_LOG_BUFFER_SIZE (128U)
36 #define MAX_SENSOR_NAME_LEN (20U)
37 #define MAX_BITS_PER_BYTE (8U)
38 #define MAX_SENSORS (sizeof(rd_sensor_data_fields_t)* MAX_BITS_PER_BYTE)
39 #define MAX_RETRIES (50U)
40 #define MAX_FIFO_DEPTH (32U)
41 #define MAX_SENSOR_PROVIDED_FIELDS (4U)
42 
43 #define LOG_PRINT_DELAY_MS (10U)
44 
45 
46 static inline void LOG (const char * const msg)
47 {
49  ri_delay_ms (LOG_PRINT_DELAY_MS); // Avoid overflowing log buffer.
50 }
51 
52 static volatile bool fifo_int = false;
53 static volatile bool level_int = false;
54 
55 static bool initialize_sensor_once (rd_sensor_t * DUT,
56  const rd_sensor_init_fp init,
57  const rd_bus_t bus, const uint8_t handle)
58 {
59  rd_status_t err_code = RD_SUCCESS;
60  err_code = init (DUT, bus, handle);
61 
62  if (RD_SUCCESS != err_code)
63  {
64  return true;
65  }
66 
67  return false;
68 }
69 
70 static bool uninitialize_sensor (rd_sensor_t * DUT,
71  const rd_sensor_init_fp init,
72  const rd_bus_t bus, const uint8_t handle)
73 {
74  rd_status_t err_code = RD_SUCCESS;
75  err_code = DUT->uninit (DUT, bus, handle);
76 
77  if (RD_SUCCESS != err_code)
78  {
79  return true;
80  }
81 
82  return false;
83 }
84 
85 static bool initialize_sensor_twice (rd_sensor_t * DUT,
86  const rd_sensor_init_fp init,
87  const rd_bus_t bus, const uint8_t handle)
88 {
89  rd_status_t err_code = RD_SUCCESS;
90  err_code = init (DUT, bus, handle);
91  err_code = init (DUT, bus, handle);
92 
93  if (RD_SUCCESS == err_code)
94  {
95  RD_ERROR_CHECK (err_code, ~RD_ERROR_FATAL);
96  return true;
97  }
98 
99  return false;
100 }
101 
102 static bool validate_sensor_setup (rd_sensor_t * DUT)
103 {
104  // - None of the sensor function pointers may be NULL after init
105  if (DUT->init == NULL ||
106  DUT->uninit == NULL ||
107  DUT->configuration_get == NULL ||
108  DUT->configuration_set == NULL ||
109  DUT->data_get == NULL ||
110  DUT->dsp_get == NULL ||
111  DUT->dsp_set == NULL ||
112  DUT->fifo_enable == NULL ||
113  DUT->fifo_interrupt_enable == NULL ||
114  DUT->fifo_read == NULL ||
115  DUT->level_interrupt_set == NULL ||
116  DUT->mode_get == NULL ||
117  DUT->mode_set == NULL ||
118  DUT->resolution_get == NULL ||
119  DUT->resolution_set == NULL ||
120  DUT->samplerate_get == NULL ||
121  DUT->samplerate_set == NULL ||
122  DUT->scale_get == NULL ||
123  DUT->scale_set == NULL ||
124  DUT->name == NULL ||
125  DUT->provides.bitfield == 0)
126  {
127  return true;
128  }
129 
130  return false;
131 }
132 
133 static bool validate_sensor_teardown (rd_sensor_t * DUT)
134 {
135  bool failed = false;
136  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->init (NULL, 0, 0)) ? true : false;
137  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->uninit (NULL, 0, 0)) ? true : false;
138  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->configuration_get (NULL,
139  NULL)) ? true : false;
140  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->configuration_set (NULL,
141  NULL)) ? true : false;
142  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->data_get (NULL)) ? true : false;
143  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->dsp_get (NULL, NULL)) ? true : false;
144  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->dsp_set (NULL, NULL)) ? true : false;
145  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->fifo_enable (false)) ? true : false;
147  false)) ? true : false;
148  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->fifo_read (NULL,
149  NULL)) ? true : false;
150  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->level_interrupt_set (false,
151  NULL)) ? true : false;
152  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->mode_get (NULL)) ? true : false;
153  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->mode_set (NULL)) ? true : false;
154  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->resolution_get (NULL)) ? true : false;
155  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->resolution_set (NULL)) ? true : false;
156  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->samplerate_get (NULL)) ? true : false;
157  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->samplerate_set (NULL)) ? true : false;
158  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->scale_get (NULL)) ? true : false;
159  failed |= (RD_ERROR_NOT_INITIALIZED != DUT->scale_set (NULL)) ? true : false;
160  failed |= (0 != DUT->provides.bitfield) ? true : false;
161  return failed;
162 }
163 
164 static bool validate_sensor_mode_after_init (rd_sensor_t * DUT)
165 {
166  uint8_t mode;
167  rd_status_t err_code = DUT->mode_get (&mode);
168 
169  if (RD_SUCCESS != err_code || RD_SENSOR_CFG_SLEEP != mode)
170  {
172  return true;
173  }
174 
175  return false;
176 }
177 
178 static bool test_sensor_init_on_null (rd_sensor_t * DUT,
179  const rd_sensor_init_fp init,
180  const rd_bus_t bus, const uint8_t handle)
181 {
182  rd_status_t err_init = DUT->init (NULL, bus, handle);
183  rd_status_t err_uninit = DUT->uninit (NULL, bus, handle);
184 
185  if (RD_ERROR_NULL != err_init || RD_ERROR_NULL != err_uninit)
186  {
187  return true;
188  }
189 
190  return false;
191 }
192 
217 static bool test_sensor_init (const rd_sensor_init_fp init,
218  const rd_bus_t bus, const uint8_t handle)
219 {
220  rd_sensor_t DUT = {0};
221  bool failed = false;
222  // - Sensor must return RD_SUCCESS on first init.
223  failed |= initialize_sensor_once (&DUT, init, bus, handle);
224  RETURN_ON_ERROR (failed);
225  // - None of the sensor function pointers may be NULL after init
226  failed |= validate_sensor_setup (&DUT);
227  // - Sensor must return RD_SUCCESS on first uninit
228  failed |= uninitialize_sensor (&DUT, init, bus, handle);
229  // - All of sensor function pointers must return RD_ERROR_NOT_INITIALIZED after uninit
230  failed |= validate_sensor_teardown (&DUT);
231  // - Sensor must return RD_ERROR_INVALID_STATE when initializing sensor which is already init
232  failed |= initialize_sensor_twice (&DUT, init, bus, handle);
233  // - Sensor must return RD_SUCCESS after uninit
234  failed |= uninitialize_sensor (&DUT, init, bus, handle);
235  // - Sensor initialization must be successful after uninit.
236  failed |= initialize_sensor_once (&DUT, init, bus, handle);
237  // - Sensor mode_get must return RD_SENSOR_CFG_SLEEP after init.
238  failed |= validate_sensor_mode_after_init (&DUT);
239  // - Init and Uninit must return RD_ERROR_NULL if pointer to sensor struct is NULL
240  failed |= test_sensor_init_on_null (&DUT, init, bus, handle);
241  // Uninitialise sensor after test
242  DUT.uninit (&DUT, bus, handle);
243  return failed;
244 }
245 
246 static bool test_sensor_setup_set_get (const rd_sensor_t * DUT,
247  const rd_sensor_setup_fp set, const rd_sensor_setup_fp get)
248 {
249  rd_status_t err_code = RD_SUCCESS;
250  bool failed = false;
251  uint8_t config = 0;
252  uint8_t original = 0;
253  // Test constant values
255 
256  for (size_t ii = 0; ii < sizeof (cfg_constants); ii++)
257  {
258  config = cfg_constants[ii];
259  err_code = set (&config);
260  original = config;
261  err_code |= get (&config);
262 
263  if (config != original ||
264  RD_SUCCESS != err_code)
265  {
266  failed = true;
267  }
268  }
269 
270  if (RD_SUCCESS != err_code)
271  {
272  failed = true;
273  }
274 
275  // Sensor must return RD_ERROR_INVALID_STATE if sensor is not in SLEEP mode while being configured.
276  uint8_t mode = RD_SENSOR_CFG_CONTINUOUS;
277  config = RD_SENSOR_CFG_DEFAULT;
278  err_code = DUT->mode_set (&mode);
279  err_code |= set (&config);
280 
281  if (RD_ERROR_INVALID_STATE != err_code)
282  {
283  failed = true;
284  }
285 
286  mode = RD_SENSOR_CFG_SLEEP;
287  err_code = DUT->mode_set (&mode);
288 
289  // Test values 1 ... 200
290  for (uint8_t ii = 1; ii < 200; ii++)
291  {
292  config = ii;
293  original = config;
294  err_code = set (&config);
295 
296  // Set value must be at least requested value
297  if (RD_SUCCESS == err_code &&
298  original > config)
299  {
300  failed = true;
301  }
302 
303  // Get must be as what was returned in set
304  original = config;
305  err_code |= get (&config);
306 
307  if (config != original &&
308  RD_SUCCESS == err_code)
309  {
310  failed = true;
311  break;
312  }
313 
314  // Break on not supported
315  if (RD_ERROR_NOT_SUPPORTED == err_code)
316  {
317  break;
318  }
319 
320  // Return error on any other error code
321  if (RD_SUCCESS != err_code)
322  {
323  return true;
324  }
325  }
326 
327  // Check NULL check
328  err_code = set (NULL);
329 
330  if (RD_ERROR_NULL != err_code)
331  {
332  failed = true;
333  }
334 
335  err_code = get (NULL);
336 
337  if (RD_ERROR_NULL != err_code)
338  {
339  failed = true;
340  }
341 
342  return failed;
343 }
344 
361 static bool test_sensor_setup (const rd_sensor_init_fp init,
362  const rd_bus_t bus, const uint8_t handle)
363 {
364  // - Sensor must return RD_SUCCESS on first init.
365  rd_sensor_t DUT;
366  memset (&DUT, 0, sizeof (DUT));
367  bool failed = false;
368  failed |= init (&DUT, bus, handle);
369 
370  if (failed)
371  {
372  // Return to avoid calling NULL function pointers
373  return failed;
374  }
375 
376  // Test scale
377  failed |= test_sensor_setup_set_get (&DUT, DUT.scale_set, DUT.scale_get);
378  // Test samplerate
379  failed |= test_sensor_setup_set_get (&DUT, DUT.samplerate_set, DUT.samplerate_get);
380  // Test resolution
381  failed |= test_sensor_setup_set_get (&DUT, DUT.resolution_set, DUT.resolution_get);
382  // Uninitialise sensor after test
383  DUT.uninit (&DUT, bus, handle);
384  return failed;
385 }
386 
388 static inline bool value_has_changed (rd_sensor_data_t * old,
389  const rd_sensor_data_t * const new_d)
390 {
391  bool change = false;
392 
393  for (uint8_t ii = 0; ii < rd_sensor_data_fieldcount (old); ii++)
394  {
395  if (old->data[ii] != new_d->data[ii]) { change = true; }
396 
397  old->data[ii] = new_d->data[ii];
398  }
399 
400  return change;
401 }
402 
403 static bool sensor_sleeps_after_init (const rd_sensor_t * const DUT)
404 {
405  rd_status_t err_code = RD_SUCCESS;
406  uint8_t mode;
407  err_code = DUT->mode_get (&mode);
408 
409  if (RD_SUCCESS != err_code || RD_SENSOR_CFG_SLEEP != mode)
410  {
411  return true;
412  }
413 
414  return false;
415 }
416 
417 static bool sensor_returns_invalid_before_sampling (const rd_sensor_t * const DUT)
418 {
419  rd_status_t err_code = RD_SUCCESS;
420  float values_new[MAX_SENSOR_PROVIDED_FIELDS];
421  rd_sensor_data_t new_data =
422  {
423  .fields = DUT->provides,
424  .data = values_new
425  };
426  err_code = DUT->data_get (&new_data);
427 
428  if (RD_SUCCESS != err_code || new_data.valid.bitfield)
429  {
431  return true;
432  }
433 
434  return false;
435 }
436 
437 static bool sensor_returns_to_sleep (const rd_sensor_t * const DUT)
438 {
439  rd_status_t err_code = RD_SUCCESS;
440  uint8_t mode;
441  mode = RD_SENSOR_CFG_SINGLE;
442  err_code = DUT->mode_set (&mode);
443 
444  if (RD_SUCCESS != err_code || RD_SENSOR_CFG_SLEEP != mode)
445  {
447  return true;
448  }
449 
450  return false;
451 }
452 
453 static bool sensor_returns_valid_data (const rd_sensor_t * const DUT)
454 {
455  rd_status_t err_code = RD_SUCCESS;
456  uint8_t mode;
457  rd_sensor_data_t data = {0};
458  float values [MAX_SENSOR_PROVIDED_FIELDS];
459  data.fields = DUT->provides;
460  data.data = values;
461  mode = RD_SENSOR_CFG_SINGLE;
462  err_code = DUT->mode_set (&mode);
463  err_code |= DUT->data_get (&data);
464 
465  if (RD_SUCCESS != err_code ||
466  (DUT->provides.bitfield != data.valid.bitfield) ||
468  {
470  return true;
471  }
472 
473  return false;
474 }
475 
476 static bool single_sample_stays_valid (const rd_sensor_t * const DUT)
477 {
478  rd_status_t err_code = RD_SUCCESS;
479  uint8_t mode = RD_SENSOR_CFG_SINGLE;
480  float old_values[MAX_SENSOR_PROVIDED_FIELDS] = {0};
481  float new_values[MAX_SENSOR_PROVIDED_FIELDS] = {0};
482  rd_sensor_data_t old_data = {.fields = DUT->provides,
483  .data = old_values
484  };
485  rd_sensor_data_t new_data = {.fields = DUT->provides,
486  .data = new_values
487  };
488  err_code = DUT->mode_set (&mode);
489  err_code |= DUT->data_get (&old_data);
490  ri_delay_ms (2); // wait 2 ms to ensure timestamp is not changed.
491  err_code |= DUT->data_get (&new_data);
492 
493  if (RD_SUCCESS != err_code ||
494  old_data.timestamp_ms != new_data.timestamp_ms ||
495  0 != memcmp (old_values, new_values, sizeof (old_values)))
496  {
498  return true;
499  }
500 
501  return false;
502 }
503 
504 static bool sensor_remains_continuous (const rd_sensor_t * const DUT)
505 {
506  rd_status_t err_code = RD_SUCCESS;
507  uint8_t mode = RD_SENSOR_CFG_SINGLE;
509  err_code = DUT->mode_set (&mode);
510  ri_delay_ms (20);
511  err_code |= DUT->mode_get (&mode);
512 
513  if (RD_SUCCESS != err_code || RD_SENSOR_CFG_CONTINUOUS != mode)
514  {
515  return true;
516  }
517 
518  return false;
519 }
520 
521 static bool sensor_rejects_single_on_continuous (const rd_sensor_t * const DUT)
522 {
523  rd_status_t err_code = RD_SUCCESS;
524  uint8_t mode = RD_SENSOR_CFG_SINGLE;
525  err_code = DUT->mode_set (&mode);
526 
527  if (RD_ERROR_INVALID_STATE != err_code
528  || RD_SENSOR_CFG_CONTINUOUS != mode)
529  {
530  return true;
531  }
532 
533  return false;
534 }
535 
536 static bool sensor_mode_cannot_be_null (const rd_sensor_t * const DUT)
537 {
538  rd_status_t err_code = RD_SUCCESS;
539  err_code = DUT->mode_set (NULL);
540 
541  if (RD_ERROR_NULL != err_code)
542  {
543  return true;
544  }
545 
546  err_code = DUT->mode_get (NULL);
547 
548  if (RD_ERROR_NULL != err_code)
549  {
550  return true;
551  }
552 
553  return false;
554 }
555 
556 static bool sensor_returns_continuous_data (const rd_sensor_t * const DUT)
557 {
558  rd_status_t err_code = RD_SUCCESS;
559  uint8_t mode = RD_SENSOR_CFG_SLEEP;
560  float old_values[MAX_SENSOR_PROVIDED_FIELDS];
561  float new_values[MAX_SENSOR_PROVIDED_FIELDS];
562  rd_sensor_data_t old_data = {.fields = DUT->provides,
563  .data = old_values
564  };
565  rd_sensor_data_t new_data = {.fields = DUT->provides,
566  .data = new_values
567  };
568  err_code = DUT->mode_set (&mode);
569  err_code |= DUT->data_get (&old_data);
570  ri_delay_ms (2); // wait 2 ms to ensure timestamp is not changed.
571  err_code |= DUT->data_get (&new_data);
572  err_code = DUT->mode_set (&mode);
573  uint8_t samplerate = RD_SENSOR_CFG_MAX;
574  err_code |= DUT->samplerate_set (&samplerate);
576  err_code |= DUT->mode_set (&mode);
577  uint32_t interval = (1000 / (samplerate + 1));
578  ri_delay_ms (2 * interval);
579  err_code |= DUT->data_get (&old_data);
580  int retries = 0;
581 
582  for (; retries < MAX_RETRIES; retries++)
583  {
584  ri_delay_ms (2 * interval);
585  new_data.valid.bitfield = 0;
587  err_code |= DUT->data_get (&new_data);
588 
589  if (old_data.timestamp_ms == new_data.timestamp_ms || RD_SUCCESS != err_code)
590  {
591  if (RD_STATUS_MORE_AVAILABLE == err_code)
592  {
593  do
594  {
595  err_code |= DUT->data_get (&new_data);
596  } while (RD_STATUS_MORE_AVAILABLE == err_code);
597 
598  continue;
599  }
600  else
601  {
602  return true;
603  }
604  }
605 
606  if (value_has_changed (&old_data, &new_data)) { break; }
607  }
608 
609  if (MAX_RETRIES == retries)
610  {
611  return true;
612  }
613 
614  return false;
615 }
616 
638 static bool test_sensor_modes (const rd_sensor_init_fp init,
639  const rd_bus_t bus, const uint8_t handle)
640 {
641  bool failed = false;
642  rd_sensor_t DUT;
643  memset (&DUT, 0, sizeof (DUT));
644  initialize_sensor_once (&DUT, init, bus, handle);
645  // - Sensor must be in SLEEP mode after init
646  failed |= sensor_sleeps_after_init (&DUT);
647  // - Sensor must return all values as INVALID if sensor is read before first sample
648  failed |= sensor_returns_invalid_before_sampling (&DUT);
649  // - Sensor must be in SLEEP mode after mode has been set to SINGLE
650  failed |= sensor_returns_to_sleep (&DUT);
651  // - Sensor must have new data after setting mode to SINGLE returns
652  failed |= sensor_returns_valid_data (&DUT);
653  // - Sensor must have same values, including timestamp, on successive calls to DATA_GET after SINGLE sample
654  failed |= single_sample_stays_valid (&DUT);
655  // - Sensor must stay in CONTINUOUS mode after being set to continuous.
656  failed |= sensor_remains_continuous (&DUT);
657  // - Sensor must return RD_ERROR_INVALID_STATE if set to SINGLE while in continuous mode and remain in continuous mode
658  failed |= sensor_rejects_single_on_continuous (&DUT);
659  // - Sensor must return RD_ERROR_NULL if null mode is passed as a parameter
660  failed |= sensor_mode_cannot_be_null (&DUT);
661  // Sensor must return updated data in CONTINUOUS mode, at least timestamp has to be updated after two ms wait.
662  failed |= sensor_returns_continuous_data (&DUT);
663  // Uninitialise sensor after test
664  failed |= DUT.uninit (&DUT, bus, handle);
665  return failed;
666 }
667 
668 static void on_fifo (const ri_gpio_evt_t evt)
669 {
670  fifo_int = true;
671 }
672 
673 static void on_level (const ri_gpio_evt_t evt)
674 {
675  level_int = true;
676 }
677 
689 static bool test_sensor_interrupts_setup (rd_sensor_t * DUT,
690  rd_sensor_init_fp const init,
691  const rd_bus_t bus, const uint8_t handle,
692  ri_gpio_interrupt_fp_t * const interrupt_table,
693  const ri_gpio_id_t fifo_pin,
694  const ri_gpio_id_t level_pin)
695 {
696  rd_status_t err_code = RD_SUCCESS;
697 
699  {
700  err_code |= ri_gpio_interrupt_uninit();
701  }
702 
703  err_code |= ri_gpio_interrupt_init (interrupt_table,
705  err_code |= ri_gpio_interrupt_enable (fifo_pin, RI_GPIO_SLOPE_LOTOHI,
706  RI_GPIO_MODE_INPUT_PULLUP, on_fifo);
707  err_code |= ri_gpio_interrupt_enable (level_pin, RI_GPIO_SLOPE_LOTOHI,
708  RI_GPIO_MODE_INPUT_PULLUP, on_level);
709  // - Sensor must return RD_SUCCESS on first init.
710  memset (DUT, 0, sizeof (rd_sensor_t));
711  err_code |= init (DUT, bus, handle);
712  err_code |= DUT->fifo_interrupt_enable (true);
713  return (RD_SUCCESS != err_code);
714 }
715 
719 static void test_sensor_interrupts_teardown (rd_sensor_t * const DUT,
720  rd_sensor_init_fp const init,
721  const rd_bus_t bus, const uint8_t handle,
722  const ri_gpio_id_t fifo_pin,
723  const ri_gpio_id_t level_pin)
724 {
725  DUT->fifo_interrupt_enable (false);
726  ri_gpio_interrupt_disable (fifo_pin);
727  ri_gpio_interrupt_disable (level_pin);
728  DUT->uninit (DUT, bus, handle);
730 }
731 
733 static rd_status_t test_sensor_level_enable (const rd_sensor_t * DUT)
734 {
735  float threshold_g = APP_MOTION_THRESHOLD;
736  DUT->level_interrupt_set (true, &threshold_g);
737  rd_sensor_configuration_t config = {0};
738  config.samplerate = 10;
740  DUT->configuration_set (DUT, &config);
741  level_int = false;
742  // Wait for LEVEL interrupt
743  uint32_t timeout = 0;
744  uint32_t max_time = 5U * 1000U * 1000U;
745 
746  while ( (!level_int) && (timeout < max_time))
747  {
748  timeout += 10;
749  ri_delay_us (10);
750  }
751 
752  if (timeout >= max_time)
753  {
754  return RD_ERROR_TIMEOUT;
755  }
756 
757  return (level_int) ? false : true;
758 }
759 
761 static rd_status_t test_sensor_fifo_enable (const rd_sensor_t * DUT)
762 {
763  DUT->fifo_enable (true);
764  rd_sensor_configuration_t config = {0};
765  config.samplerate = 10;
767  DUT->configuration_set (DUT, &config);
768  fifo_int = false;
769  ri_delay_ms (100);
770  rd_sensor_data_t old;
771  float old_values[MAX_SENSOR_PROVIDED_FIELDS];
772  old.data = old_values;
773  old.fields.bitfield = DUT->provides.bitfield;
774  size_t num_samples = MAX_FIFO_DEPTH;
775  rd_sensor_data_t data[MAX_FIFO_DEPTH] = { 0 };
776  float values[num_samples][MAX_SENSOR_PROVIDED_FIELDS];
777  uint32_t max_time = 4U * 1000U * 1000U;
778 
779  for (size_t ii = 0; ii < num_samples; ii++)
780  {
781  data[ii].data = values[ii];
782  data[ii].fields.bitfield = DUT->provides.bitfield;
783  }
784 
785  bool valid_data = false;
786  // Wait for FIFO interrupt
787  uint32_t timeout = 0;
788 
789  while ( (!fifo_int) && (timeout < max_time))
790  {
791  timeout += 10;
792  ri_delay_us (10);
793  }
794 
795  if (timeout >= max_time)
796  {
797  return RD_ERROR_TIMEOUT;
798  }
799 
800  DUT->fifo_read (&num_samples, data);
801 
802  if (10U > num_samples)
803  {
804  return RD_ERROR_SELFTEST;
805  }
806 
807  // Check that FIFO has new values
808  value_has_changed (&old, & (data[0]));
809 
810  for (size_t iii = 1; iii < num_samples; iii++)
811  {
812  if (value_has_changed (&old, & (data[iii])))
813  {
814  valid_data = true;
815  break;
816  }
817  }
818 
819  return (valid_data) ? false : true;
820 }
821 
822 
843 static bool test_sensor_interrupts (const rd_sensor_init_fp init,
844  const rd_bus_t bus, const uint8_t handle,
845  const bool interactive,
846  const ri_gpio_id_t fifo_pin,
847  const ri_gpio_id_t level_pin,
848  const rd_test_print_fp printfp)
849 {
851  interrupt_table[RI_GPIO_INTERRUPT_TEST_TABLE_SIZE];
852  rd_sensor_t DUT;
853  rd_status_t status;
854  status = test_sensor_interrupts_setup (&DUT, init, bus, handle, interrupt_table, fifo_pin,
855  level_pin);
856 
857  if (RD_SUCCESS == status)
858  {
859  printfp ("{\r\n\"level\":");
860  status |= test_sensor_level_enable (&DUT);
861 
862  if (status)
863  {
864  printfp ("\"fail\",\r\n");
865  }
866  else
867  {
868  printfp ("\"pass\",\r\n");
869  }
870 
871  test_sensor_interrupts_teardown (&DUT, init, bus, handle, fifo_pin,
872  level_pin);
873  status = test_sensor_interrupts_setup (&DUT, init, bus, handle, interrupt_table, fifo_pin,
874  level_pin);
875  printfp ("\"fifo\":");
876  status |= test_sensor_fifo_enable (&DUT);
877 
878  if (status)
879  {
880  printfp ("\"fail\"\r\n");
881  }
882  else
883  {
884  printfp ("\"pass\"\r\n");
885  }
886 
887  printfp ("},");
888  }
889 
890  test_sensor_interrupts_teardown (&DUT, init, bus, handle, fifo_pin,
891  level_pin);
892  return status;
893 }
894 
895 static bool sensor_returns_valid_data_print (const rd_sensor_t * const DUT,
896  const rd_test_print_fp printfp)
897 {
898  rd_status_t err_code = RD_SUCCESS;
899  uint8_t mode;
900  rd_sensor_data_t data = {0};
901  float values [MAX_SENSOR_PROVIDED_FIELDS];
902  data.fields = DUT->provides;
903  data.data = values;
904  mode = RD_SENSOR_CFG_SINGLE;
905  err_code = DUT->mode_set (&mode);
906  err_code |= DUT->data_get (&data);
907 
908  if (RD_SUCCESS != err_code)
909  {
911  return true;
912  }
913 
914  rd_sensor_data_print (&data, printfp);
915  return false;
916 }
917 
918 static bool test_sensor_data_print (const rd_sensor_init_fp init,
919  const rd_bus_t bus, const uint8_t handle,
920  const rd_test_print_fp printfp)
921 {
922  // - Sensor must return RD_SUCCESS on first init.
923  rd_sensor_t DUT;
924  memset (&DUT, 0, sizeof (DUT));
925  bool failed = false;
926  failed |= init (&DUT, bus, handle);
927 
928  if (failed)
929  {
930  // Return to avoid calling NULL function pointers
931  printfp ("\"data\":\"fail\",\r\n");
932  return failed;
933  }
934 
935  failed |= sensor_returns_valid_data_print (&DUT, printfp);
936  DUT.uninit (&DUT, bus, handle);
937  return failed;
938 }
939 
941  rt_sensor_ctx_t * p_sensor_ctx)
942 {
943  bool status = false;
944  rd_status_t err_code = RD_SUCCESS;
945  printfp ("\"");
946  printfp (p_sensor_ctx->sensor.name);
947  printfp ("\": {\r\n");
948  printfp ("\"init\":");
949 
950  if (RD_HANDLE_UNUSED == p_sensor_ctx->handle)
951  {
952  err_code |= RD_ERROR_NOT_FOUND;
953  }
954  else
955  {
956  err_code |= p_sensor_ctx->init (&p_sensor_ctx->sensor,
957  p_sensor_ctx->bus,
958  p_sensor_ctx->handle);
959  }
960 
961  if (RD_ERROR_NOT_FOUND == err_code)
962  {
963  printfp ("\"skip\"\r\n");
964  p_sensor_ctx->sensor.uninit (&p_sensor_ctx->sensor, p_sensor_ctx->bus,
965  p_sensor_ctx->handle);
966  }
967  else
968  {
969  p_sensor_ctx->sensor.uninit (&p_sensor_ctx->sensor, p_sensor_ctx->bus,
970  p_sensor_ctx->handle);
971  status = test_sensor_init (p_sensor_ctx->init, p_sensor_ctx->bus, p_sensor_ctx->handle);
972 
973  if (status)
974  {
975  printfp ("\"fail\",\r\n");
976  }
977  else
978  {
979  printfp ("\"pass\",\r\n");
980  }
981 
982  printfp ("\"modes\":");
983 
984  if (!status)
985  {
986  status = test_sensor_modes (p_sensor_ctx->init, p_sensor_ctx->bus, p_sensor_ctx->handle);
987  }
988 
989  if (status)
990  {
991  printfp ("\"fail\",\r\n");
992  }
993  else
994  {
995  printfp ("\"pass\",\r\n");
996  }
997 
998  printfp ("\"configuration\":");
999 
1000  if (!status)
1001  {
1002  status = test_sensor_setup (p_sensor_ctx->init, p_sensor_ctx->bus, p_sensor_ctx->handle);
1003  }
1004 
1005  if (status)
1006  {
1007  printfp ("\"fail\",\r\n");
1008  }
1009  else
1010  {
1011  printfp ("\"pass\",\r\n");
1012  }
1013 
1014  printfp ("\"interrupts\":");
1015 
1016  if ( (RI_GPIO_ID_UNUSED != p_sensor_ctx->fifo_pin)
1017  && (RI_GPIO_ID_UNUSED != p_sensor_ctx->level_pin)
1018  && (!status))
1019  {
1020  status = test_sensor_interrupts (p_sensor_ctx->init, p_sensor_ctx->bus,
1021  p_sensor_ctx->handle, false,
1022  p_sensor_ctx->fifo_pin,
1023  p_sensor_ctx->level_pin,
1024  printfp);
1025  }
1026  else
1027  {
1028  printfp ("\"skipped\",\r\n");
1029  }
1030 
1031  status = test_sensor_data_print (p_sensor_ctx->init, p_sensor_ctx->bus,
1032  p_sensor_ctx->handle, printfp);
1033  }
1034 
1035  printfp ("}");
1036  return status;
1037 }
1038 
1039 void rd_sensor_data_print (const rd_sensor_data_t * const p_data,
1040  const rd_test_print_fp printfp)
1041 {
1042  uint8_t data_counter = 0;
1043  uint8_t data_available = 0;
1044  uint32_t data_check = p_data->fields.bitfield;
1045  char sensors_name[MAX_SENSORS][MAX_SENSOR_NAME_LEN] =
1046  {
1047  "acceleration_x_g",
1048  "acceleration_y_g",
1049  "acceleration_z_g",
1050  "co2_ppm",
1051  "gyro_x_dps",
1052  "gyro_y_dps",
1053  "gyro_z_dps",
1054  "humidity_rh",
1055  "luminosity",
1056  "magnetometer_x_g",
1057  "magnetometer_y_g",
1058  "magnetometer_z_g",
1059  "pm_1_ugm3",
1060  "pm_2_ugm3",
1061  "pm_4_ugm3",
1062  "pm_10_ugm3",
1063  "pressure_pa",
1064  "spl_dbz",
1065  "temperature_c",
1066  "voc_ppm",
1067  "voltage_v",
1068  "voltage_ratio",
1069  };
1070 
1071  /* Count enabled sensors */
1072  for (int i = 0; i < MAX_SENSORS; i++)
1073  {
1074  if (data_check & BITFIELD_MASK)
1075  { data_available++; }
1076 
1077  data_check = data_check >> 1;
1078  }
1079 
1080  if (NULL != p_data)
1081  {
1082  printfp ("\"data\":{\r\n");
1083  char msg[MAX_LOG_BUFFER_SIZE];
1084 
1085  if (RD_UINT64_INVALID == p_data->timestamp_ms)
1086  {
1087  snprintf (msg, sizeof (msg), "\"timestamp_ms\": \"RD_UINT64_INVALID\",\n");
1088  }
1089  else
1090  {
1091  // Cast to 32 bits, tests are run at boot so there is no danger of overflow.
1092  snprintf (msg, sizeof (msg), "\"timestamp_ms\": \"%ld\",\n",
1093  (uint32_t) p_data->timestamp_ms);
1094  }
1095 
1096  printfp (msg);
1097 
1098  for (uint8_t i = 0; i < MAX_SENSORS; i++)
1099  {
1100  if ( (p_data->fields.bitfield >> i) &
1101  BITFIELD_MASK)
1102  {
1103  char msg[MAX_LOG_BUFFER_SIZE];
1104 
1105  if ( (p_data->valid.bitfield >> i) &
1106  BITFIELD_MASK)
1107  {
1108  if (0 == isnan (* ( (float *) (&p_data->data[data_counter]))))
1109  {
1110  snprintf (msg, sizeof (msg),
1111  "\"%s\": \"%.2f\"",
1112  (char *) &sensors_name[i][0],
1113  * ( (float *) (&p_data->data[data_counter])));
1114  }
1115  else
1116  {
1117  snprintf (msg, sizeof (msg),
1118  "\"%s\": \"NAN\"",
1119  (char *) &sensors_name[i][0]);
1120  }
1121 
1122  data_counter++;
1123  }
1124  else
1125  {
1126  snprintf (msg, sizeof (msg),
1127  "\"%s\": \"NAN\"",
1128  (char *) &sensors_name[i][0]);
1129  }
1130 
1131  if (data_counter == data_available)
1132  {
1133  char * str = "\r\n";
1134  strncat (msg, str, sizeof (str));
1135  }
1136  else
1137  {
1138  char * str = ",\r\n";
1139  strncat (msg, str, sizeof (str));
1140  }
1141 
1142  printfp (msg);
1143  }
1144  }
1145 
1146  printfp ("}\r\n");
1147  }
1148 }
1149 
1150 #else //RUUVI_RUN_TESTS
1151 
1152 // Dummy implementation
1153 rd_status_t test_sensor_status (size_t * total, size_t * passed)
1154 {
1155  return RD_SUCCESS;
1156 }
1157 
1158 // Dummy implementation
1159 void test_sensor_run (void)
1160 {}
1161 #endif
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_NOT_INITIALIZED
Driver is not initialized.
#define RD_ERROR_FATAL
Program should always reset after this.
uint32_t rd_status_t
bitfield for representing errors
#define RD_STATUS_MORE_AVAILABLE
Driver has more data queued.
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_ERROR_NOT_SUPPORTED
Not supported.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_TIMEOUT
Operation timed out.
#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.
rd_status_t ri_gpio_interrupt_enable(const ri_gpio_id_t pin, const ri_gpio_slope_t slope, const ri_gpio_mode_t mode, const ri_gpio_interrupt_fp_t handler)
Enable interrupt on a pin.
#define RI_GPIO_INTERRUPT_TEST_TABLE_SIZE
Fixed 64 interrupt table size, adjust this if some device has more than 2 ports with 32 gpios each.
rd_status_t ri_gpio_interrupt_init(ri_gpio_interrupt_fp_t *const interrupt_table, const uint16_t max_interrupts)
Initialize interrupt functionality to GPIO. Takes address of interrupt table as a pointer to avoid ty...
void(* ri_gpio_interrupt_fp_t)(const ri_gpio_evt_t)
rd_status_t ri_gpio_interrupt_uninit(void)
Uninitialize interrupt functionality of GPIO.
rd_status_t ri_gpio_interrupt_disable(const ri_gpio_id_t pin)
Disable interrupt on a pin.
bool ri_gpio_interrupt_is_init(void)
Check if interrupt module is initialized.
void ri_log(const ri_log_severity_t severity, const char *const message)
Queues messages into log.
@ RI_LOG_LEVEL_INFO
rd_status_t(* rd_sensor_init_fp)(rd_sensor_t *const p_sensor, const rd_bus_t bus, const uint8_t handle)
Initialize and uninitialize sensor. Init and uninit will setup sensor with function pointers....
#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.
uint8_t rd_sensor_data_fieldcount(const rd_sensor_data_t *const target)
Count number of floats required for this data structure.
#define RD_SENSOR_INVALID_TIMSTAMP
Signal this timestamp value is erroneous.
rd_status_t(* rd_sensor_setup_fp)(uint8_t *parameter)
Setup a parameter of a sensor. The function will modify the pointed data to the actual value which wa...
#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_CFG_NO_CHANGE
Do not change configured value.
rd_bus_t
Type of bus sensor uses.
#define RD_SENSOR_CFG_SINGLE
Sensor should go to sleep after single measurement.
#define RD_HANDLE_UNUSED
Mark sensor as unused with this handle.
void rd_sensor_data_print(const rd_sensor_data_t *const p_data, const rd_test_print_fp printfp)
Print Ruuvi Sensor data in human readable JSON.
bool rd_sensor_run_integration_test(const rd_test_print_fp printfp, rt_sensor_ctx_t *p_sensor_ctx)
void(* rd_test_print_fp)(const char *const msg)
function pointer to print test information
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Ruuvi sensor interface Lifecycle: Beta
rd_status_t test_sensor_status(size_t *total, size_t *passed)
void test_sensor_run(void)
Run sensor integration tests.
uint16_t ri_gpio_id_t
port<<8 + pin
#define RI_GPIO_ID_UNUSED
Enable implementation selected by application.
@ RI_GPIO_MODE_INPUT_PULLUP
Input, can be read. Pulled up by internal resistor, value depends on IC.
rd_status_t ri_delay_us(uint32_t time)
Delay a given number of microseconds.
rd_status_t ri_delay_ms(uint32_t time)
Delay a given number of milliseconds.
All sensors must implement configuration functions which accept this struct.
uint8_t mode
Mode, RD_SENSOR_SLEEP, _SINGLE, _CONTINOUS.
uint8_t samplerate
Samplerate, in Hz.
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
rd_sensor_t sensor
Control structure for sensor.
uint8_t handle
Handle of sensor.
ri_gpio_id_t level_pin
Level interrupt.
ri_gpio_id_t fifo_pin
FIFO full interrupt.
rd_sensor_init_fp init
Initialization function.
rd_bus_t bus
Bus of sensor.
uint32_t bitfield
Bitfield used to access sensor data.