ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_driver_sensor.c
Go to the documentation of this file.
1 #include "ruuvi_driver_error.h"
2 #include "ruuvi_driver_sensor.h"
3 #include <stddef.h>
4 #include <string.h>
5 
6 #define BITS_PER_BYTE (8U)
7 
8 static const char m_init_name[] = "NOTINIT";
9 
11  sensor, rd_sensor_configuration_t * config)
12 {
13  rd_status_t err_code = RD_SUCCESS;
14 
15  if (NULL == sensor || NULL == config) { return RD_ERROR_NULL; }
16 
17  if (NULL == sensor->samplerate_set) { return RD_ERROR_INVALID_STATE; }
18 
19  uint8_t sleep = RD_SENSOR_CFG_SLEEP;
20  err_code |= sensor->mode_set (&sleep);
21  err_code |= sensor->samplerate_set (& (config->samplerate));
22  err_code |= sensor->resolution_set (& (config->resolution));
23  err_code |= sensor->scale_set (& (config->scale));
24  err_code |= sensor->dsp_set (& (config->dsp_function), & (config->dsp_parameter));
25  err_code |= sensor->mode_set (& (config->mode));
26  return err_code;
27 }
28 
30  sensor, rd_sensor_configuration_t * config)
31 {
32  rd_status_t err_code = RD_SUCCESS;
33 
34  if (NULL == sensor || NULL == config) { return RD_ERROR_NULL; }
35 
36  if (NULL == sensor->samplerate_set) { return RD_ERROR_INVALID_STATE; }
37 
38  err_code |= sensor->samplerate_get (& (config->samplerate));
39  err_code |= sensor->resolution_get (& (config->resolution));
40  err_code |= sensor->scale_get (& (config->scale));
41  err_code |= sensor->dsp_get (& (config->dsp_function), & (config->dsp_parameter));
42  err_code |= sensor->mode_get (& (config->mode));
43  return err_code;
44 }
45 
46 static rd_sensor_timestamp_fp millis = NULL;
47 
49  rd_sensor_timestamp_fp timestamp_fp)
50 {
51  millis = timestamp_fp;
52  return RD_SUCCESS;
53 }
54 
55 // Calls the timestamp function and returns it's value. returns 0 if timestamp function is NULL
56 uint64_t rd_sensor_timestamp_get (void)
57 {
58  if (NULL == millis)
59  {
60  return 0;
61  }
62 
63  return millis();
64 }
65 
66 static rd_status_t rd_fifo_enable_ni (const bool enable)
67 {
69 }
70 
71 static rd_status_t rd_fifo_interrupt_enable_ni (const bool enable)
72 {
74 }
75 
76 static rd_status_t rd_fifo_read_ni (size_t * num_elements, rd_sensor_data_t * data)
77 {
79 }
80 
81 static rd_status_t rd_data_get_ni (rd_sensor_data_t * const data)
82 {
84 }
85 
86 static rd_status_t rd_init_ni (rd_sensor_t * const
87  p_sensor, const rd_bus_t bus, const uint8_t handle)
88 {
90 }
91 
92 static rd_status_t rd_setup_ni (uint8_t * const value)
93 {
95 }
96 
97 static rd_status_t rd_level_interrupt_use_ni (const bool enable,
98  float * limit_g)
99 {
101 }
102 
103 static rd_status_t rd_dsp_ni (uint8_t * const dsp, uint8_t * const parameter)
104 {
106 }
107 
108 static rd_status_t rd_sensor_configuration_ni (const rd_sensor_t *
109  sensor, rd_sensor_configuration_t * config)
110 {
112 }
113 
114 void rd_sensor_initialize (rd_sensor_t * const p_sensor)
115 {
116  if (NULL != p_sensor->name)
117  {
118  p_sensor->name = m_init_name;
119  }
120 
121  p_sensor->configuration_get = rd_sensor_configuration_ni;
122  p_sensor->configuration_set = rd_sensor_configuration_ni;
123  p_sensor->data_get = rd_data_get_ni;
124  p_sensor->dsp_get = rd_dsp_ni;
125  p_sensor->dsp_set = rd_dsp_ni;
126  p_sensor->fifo_enable = rd_fifo_enable_ni;
127  p_sensor->fifo_interrupt_enable = rd_fifo_interrupt_enable_ni;
128  p_sensor->fifo_read = rd_fifo_read_ni;
129  p_sensor->init = rd_init_ni;
130  p_sensor->uninit = rd_init_ni;
131  p_sensor->level_interrupt_set = rd_level_interrupt_use_ni;
132  p_sensor->mode_get = rd_setup_ni;
133  p_sensor->mode_set = rd_setup_ni;
134  p_sensor->resolution_get = rd_setup_ni;
135  p_sensor->resolution_set = rd_setup_ni;
136  p_sensor->samplerate_get = rd_setup_ni;
137  p_sensor->samplerate_set = rd_setup_ni;
138  p_sensor->scale_get = rd_setup_ni;
139  p_sensor->scale_set = rd_setup_ni;
140  memset (& (p_sensor->provides), 0, sizeof (p_sensor->provides));
141 }
142 
143 void rd_sensor_uninitialize (rd_sensor_t * const p_sensor)
144 {
145  // Reset sensor to initial values.
146  rd_sensor_initialize (p_sensor);
147 }
148 
149 static inline uint8_t get_index_of_field (const rd_sensor_data_t * const target,
150  const rd_sensor_data_fields_t field)
151 {
152  // Null bits higher than target
153  uint8_t leading_zeros = (uint8_t) __builtin_clz (field.bitfield);
154  uint32_t mask = UINT32_MAX;
155  uint8_t bitfield_size = sizeof (field.bitfield) * BITS_PER_BYTE;
156  uint8_t target_bit = (bitfield_size - leading_zeros);
157 
158  if (target_bit < bitfield_size)
159  {
160  mask = (1U << target_bit) - 1U;
161  }
162 
163  // Count set bits in nulled bitfield to find index.
164  uint8_t index = (uint8_t) (__builtin_popcount (target->fields.bitfield & mask) - 1);
165 
166  // return 0 if we don't have a valid result.
167  if (index > bitfield_size)
168  {
169  index = 0;
170  }
171 
172  return index;
173 }
174 
175 float rd_sensor_data_parse (const rd_sensor_data_t * const provided,
176  const rd_sensor_data_fields_t requested)
177 {
178  float rvalue = RD_FLOAT_INVALID;
179 
180  // If one value was requested and is available return value.
181  if ( (NULL != provided)
182  && (0 != (provided->valid.bitfield & requested.bitfield))
183  && (1 == __builtin_popcount (requested.bitfield)))
184  {
185  rvalue = provided->data[get_index_of_field (provided, requested)];
186  }
187 
188  return rvalue;
189 }
190 
192  const rd_sensor_data_fields_t field,
193  const float value)
194 {
195  // If there isn't valid requested data, return
196  if (NULL == target)
197  {
198  // No action needed
199  }
200  else if (! (target->fields.bitfield & field.bitfield))
201  {
202  // No action needed
203  }
204  // If trying to set more than one field, return.
205  else if (1 != __builtin_popcount (field.bitfield))
206  {
207  // No action needed
208  }
209  else
210  {
211  // Set value to appropriate index
212  target->data[get_index_of_field (target, field)] = value;
213  // Mark data as valid
214  target->valid.bitfield |= field.bitfield;
215  }
216 }
217 
218 bool rd_sensor_has_valid_data (const rd_sensor_data_t * const target,
219  const uint8_t index)
220 {
221  uint8_t fieldcount = 0;
222  rd_sensor_data_fields_t check = {0};
223  uint8_t target_index = 0U;
224  uint32_t mask = 0U;
225  bool valid = false;
226 
227  if (NULL != target)
228  {
229  fieldcount = rd_sensor_data_fieldcount (target);
230  check = target->fields;
231  }
232 
233  // Verify bounds
234  if (fieldcount > index)
235  {
236  // Find target field
237  for (uint8_t ii = 0U; ii < index; ii++)
238  {
239  // Null trailing fields
240  target_index = (uint8_t) __builtin_ctz (check.bitfield);
241  mask = 1U << target_index;
242  check.bitfield &= ~mask;
243  }
244 
245  target_index = (uint8_t) __builtin_ctz (check.bitfield);
246  mask = 1U << target_index;
247  // Check if field at given index is marked valid, convert to bool.
248  valid = !! (target->valid.bitfield & mask);
249  }
250 
251  return valid;
252 }
253 
255  const uint8_t index)
256 {
257  uint8_t fieldcount = 0;
258  rd_sensor_data_fields_t check = {0};
259  uint8_t target_index = 0U;
260  uint32_t mask = 0U;
261 
262  if (NULL != target)
263  {
264  fieldcount = rd_sensor_data_fieldcount (target);
265  }
266 
267  // Verify bounds
268  if (fieldcount > index)
269  {
270  check = target->fields;
271 
272  // Find target field
273  for (uint8_t ii = 0U; ii < index; ii++)
274  {
275  // Null trailing fields
276  target_index = (uint8_t) __builtin_ctz (check.bitfield);
277  mask = 1U << target_index;
278  check.bitfield &= ~mask;
279  }
280 
281  target_index = (uint8_t) __builtin_ctz (check.bitfield);
282  mask = 1U << target_index;
283  check.bitfield &= mask;
284  }
285 
286  // return given bitfield
287  return check.datas;
288 }
289 
291  const rd_sensor_data_t * const provided,
292  const rd_sensor_data_fields_t requested)
293 {
294  if ( (NULL != target) && (NULL != provided))
295  {
296  // Compare provided data to requested data not yet valid.
297  rd_sensor_data_fields_t available =
298  {
299  .bitfield = (provided->valid).bitfield
300  & (requested.bitfield & ~ (target->valid.bitfield))
301  };
302 
303  // Update timestamp if there is not already a valid timestamp
304  if ( (0 != available.bitfield)
305  && ( (0 == target->timestamp_ms)
306  || (RD_SENSOR_INVALID_TIMSTAMP == target->timestamp_ms)))
307  {
308  target->timestamp_ms = provided->timestamp_ms;
309  }
310 
311  // We have the available, requested fields. Fill the target struct with those
312  while (available.bitfield)
313  {
314  // read rightmost field
315  const uint8_t index = (uint8_t) __builtin_ctz (available.bitfield);
316 
317  if (index < sizeof (requested.bitfield) * BITS_PER_BYTE)
318  {
320  {
321  .bitfield = (1U << index)
322  };
323  float value = rd_sensor_data_parse (provided, next);
324  rd_sensor_data_set (target, next, value);
325  }
326 
327  // set rightmost bit of available to 0
328  available.bitfield &= (available.bitfield - 1U);
329  }
330  }
331 }
332 
333 inline uint8_t rd_sensor_data_fieldcount (const rd_sensor_data_t * const target)
334 {
335  return __builtin_popcount (target->fields.bitfield);
336 }
337 
338 rd_status_t validate_default_input_set (uint8_t * const input, const uint8_t mode)
339 {
340  rd_status_t err_code = RD_SUCCESS;
341 
342  if (NULL == input)
343  {
344  err_code = RD_ERROR_NULL;
345  }
346  else
347  {
348  if (RD_SENSOR_CFG_SLEEP != mode)
349  {
350  err_code = RD_ERROR_INVALID_STATE;
351  }
352  else
353  {
354  if (RD_SENSOR_CFG_DEFAULT == (*input))
355  {
356  (*input) = RD_SENSOR_CFG_DEFAULT;
357  }
358  else if (RD_SENSOR_CFG_NO_CHANGE == (*input))
359  {
360  (*input) = RD_SENSOR_CFG_DEFAULT;
361  }
362  else if (RD_SENSOR_CFG_MIN == (*input))
363  {
364  (*input) = RD_SENSOR_CFG_DEFAULT;
365  }
366  else if (RD_SENSOR_CFG_MAX == (*input))
367  {
368  (*input) = RD_SENSOR_CFG_DEFAULT;
369  }
370  else
371  {
372  (*input) = RD_SENSOR_CFG_DEFAULT;
373  err_code = RD_ERROR_NOT_SUPPORTED;
374  }
375  }
376  }
377 
378  return err_code;
379 }
380 
382 {
383  rd_status_t err_code = RD_SUCCESS;
384 
385  if (NULL == input)
386  {
387  err_code = RD_ERROR_NULL;
388  }
389  else
390  {
391  (*input) = RD_SENSOR_CFG_DEFAULT;
392  }
393 
394  return err_code;
395 }
396 
397 bool rd_sensor_is_init (const rd_sensor_t * const sensor)
398 {
399  bool init = false;
400 
401  if ( (NULL != sensor) && (NULL != sensor->uninit))
402  {
403  init = (sensor->uninit != &rd_init_ni);
404  }
405 
406  return init;
407 }
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_NOT_INITIALIZED
Driver is not initialized.
uint32_t rd_status_t
bitfield for representing errors
#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_INVALID_STATE
Invalid state, operation disallowed in this state.
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.
bool rd_sensor_has_valid_data(const rd_sensor_data_t *const target, const uint8_t index)
Check if sensor has valid data at given index.
#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.
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_sensor_data_bitfield_t rd_sensor_field_type(const rd_sensor_data_t *const target, const uint8_t index)
Check the type of data at given index.
rd_status_t rd_sensor_timestamp_function_set(rd_sensor_timestamp_fp timestamp_fp)
Setup timestamping. Set to NULL to disable timestamps.
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.
rd_status_t validate_default_input_set(uint8_t *const input, const uint8_t mode)
Validate that given setting can be set on a sensor which supports only default value.
#define RD_SENSOR_INVALID_TIMSTAMP
Signal this timestamp value is erroneous.
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_NO_CHANGE
Do not change configured value.
rd_bus_t
Type of bus sensor uses.
void rd_sensor_data_set(rd_sensor_data_t *const target, const rd_sensor_data_fields_t field, const float value)
Set a desired value to target data.
uint64_t rd_sensor_timestamp_get(void)
Calls the timestamp function and returns its value.
rd_status_t validate_default_input_get(uint8_t *const input)
Validate and get input when only allowed value is default.
float rd_sensor_data_parse(const rd_sensor_data_t *const provided, const rd_sensor_data_fields_t requested)
Parse data from provided struct.
uint64_t(* rd_sensor_timestamp_fp)(void)
Return number of milliseconds since the start of RTC.
Ruuvi error codes and error check function.
#define BITS_PER_BYTE
Number of bits in a byte.
Ruuvi sensor interface Lifecycle: Beta
All sensors must implement configuration functions which accept this struct.
uint8_t resolution
Resolution, in bits.
uint8_t mode
Mode, RD_SENSOR_SLEEP, _SINGLE, _CONTINOUS.
uint8_t samplerate
Samplerate, in Hz.
uint8_t scale
Scale, in relevant Si-unit.
uint8_t dsp_parameter
Parameter to DSP functions.
uint8_t dsp_function
DSP function, one of RD_SENSOR_DSP_*.
Bitfield to describe related sensor data.
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
Union to access sensor data.
uint32_t bitfield
Bitfield used to access sensor data.
rd_sensor_data_bitfield_t datas
Structured data field.