ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_driver_sensor.c
Go to the documentation of this file.
3#include <stddef.h>
4#include <string.h>
5
6#define BITS_PER_BYTE (8U)
7
8static 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
46static 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
57{
58 if (NULL == millis)
59 {
60 return 0;
61 }
62
63 return millis();
64}
65
66static rd_status_t rd_fifo_enable_ni (const bool enable)
67{
69}
70
71static rd_status_t rd_fifo_interrupt_enable_ni (const bool enable)
72{
74}
75
76static rd_status_t rd_fifo_read_ni (size_t * num_elements, rd_sensor_data_t * data)
77{
79}
80
81static rd_status_t rd_data_get_ni (rd_sensor_data_t * const data)
82{
84}
85
86static 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
92static rd_status_t rd_setup_ni (uint8_t * const value)
93{
95}
96
97static rd_status_t rd_level_interrupt_use_ni (const bool enable,
98 float * limit_g)
99{
101}
102
103static rd_status_t rd_dsp_ni (uint8_t * const dsp, uint8_t * const parameter)
104{
106}
107
108static rd_status_t rd_sensor_configuration_ni (const rd_sensor_t *
109 sensor, rd_sensor_configuration_t * config)
110{
112}
113
114void 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
143void rd_sensor_uninitialize (rd_sensor_t * const p_sensor)
144{
145 // Reset sensor to initial values.
146 rd_sensor_initialize (p_sensor);
147}
148
149static 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
175float 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
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)
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
333inline uint8_t rd_sensor_data_fieldcount (const rd_sensor_data_t * const target)
334{
335 return __builtin_popcount (target->fields.bitfield);
336}
337
338rd_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
397bool 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.