ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_nrf5_sdk15_environmental_mcu.c
Go to the documentation of this file.
1
48#if RUUVI_NRF5_SDK15_NRF52832_ENVIRONMENTAL_ENABLED
49#include "ruuvi_driver_error.h"
50#include "ruuvi_driver_sensor.h"
53
54#include "nrf_sdm.h"
55#include "nrf_temp.h"
56
57#include <string.h>
58
59#define NRF52_TEMP_SENSOR_RESOLUTION (10U)
60#define NRF52_TEMP_FIXED_SCALE (128U)
61
62// Function for checking "ignored" parameters NO_CHANGE, MIN, MAX, DEFAULT
63static inline __attribute__ ( (nonnull))
64rd_status_t success_on_valid (uint8_t param)
65{
67
68 if ( (RD_SENSOR_CFG_DEFAULT == param) ||
69 (RD_SENSOR_CFG_MIN == param) ||
70 (RD_SENSOR_CFG_MAX == param) ||
71 (RD_SENSOR_CFG_NO_CHANGE == param))
72 {
73 err_code = RD_SUCCESS;
74 }
75
76 return err_code;
77}
78
79// Function for checking that sensor is in sleep mode before configuration
80static inline __attribute__ ( (nonnull))
81rd_status_t environmental_mcu_sensor_sleep (void)
82{
83 rd_status_t err_code = RD_SUCCESS;
84 uint8_t mode = 0;
86
87 if (RD_SENSOR_CFG_SLEEP != mode)
88 {
89 err_code = RD_ERROR_INVALID_STATE;
90 }
91
92 return err_code;
93}
94
95// Flag to keep track if we should update the temperature register on data read.
96static bool autorefresh = false;
97static float temperature;
98static uint64_t tsample;
99static const char m_tmp_name[] = "nRF5TMP";
100
101static void nrf52832_temperature_sample (void)
102{
103 uint8_t sd_enabled = NRF_SDH_ENABLED;
104 int32_t raw_temp = 0;
105 // Check if softdevice is enabled
106 sd_softdevice_is_enabled (&sd_enabled);
107
108 // If Nordic softdevice is enabled, we cannot use temperature peripheral directly
109 if (NRF_SDH_ENABLED == sd_enabled)
110 {
111 sd_temp_get (&raw_temp);
112 }
113 // If SD is not enabled, call the peripheral directly.
114 else
115 {
116 NRF_TEMP->TASKS_START = 1;
118 /* Busy wait while temperature measurement is not finished, you can skip waiting if you enable interrupt for DATARDY event and read the result in the interrupt. */
119 /*lint -e{845} // A zero has been given as right argument to operator '|'" */
120 while (NRF_TEMP->EVENTS_DATARDY == 0)
121 {
122 // Do nothing.
123 }
124
125 NRF_TEMP->EVENTS_DATARDY = 0;
127 raw_temp = nrf_temp_read();
129 NRF_TEMP->TASKS_STOP = 1;
130 }
131
132 temperature = raw_temp / 4.0F;
133 tsample = rd_sensor_timestamp_get();
134}
135
137 rd_bus_t bus,
138 uint8_t handle)
139{
140 UNUSED_PARAMETER (bus);
141 UNUSED_PARAMETER (handle);
142 rd_status_t err_code = RD_SUCCESS;
143
144 if (NULL == sensor)
145 {
146 err_code = RD_ERROR_NULL;
147 }
148 else if (rd_sensor_is_init (sensor))
149 {
150 err_code = RD_ERROR_INVALID_STATE;
151 }
152 else
153 {
154 rd_sensor_initialize (sensor);
155 // Workaround for PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module
156 nrf_temp_init();
157 tsample = RD_UINT64_INVALID;
158 temperature = RD_FLOAT_INVALID;
159 // Setup function pointers
175 sensor->name = m_tmp_name;
176 sensor->provides.datas.temperature_c = 1;
177 }
178
179 return err_code;
180}
181
183 rd_bus_t bus,
184 uint8_t handle)
185{
186 rd_status_t err_code = RD_SUCCESS;
187 UNUSED_PARAMETER (bus);
188 UNUSED_PARAMETER (handle);
189
190 if (NULL == sensor)
191 {
192 err_code = RD_ERROR_NULL;
193 }
194 else
195 {
196 autorefresh = false;
197 rd_sensor_uninitialize (sensor);
198 tsample = RD_UINT64_INVALID;
199 }
200
201 return err_code;
202}
203
204// Continuous sampling is not supported, mark pointed value as default even if parameter is one of no-changes
206 uint8_t * samplerate)
207{
208 rd_status_t err_code = RD_SUCCESS;
209
210 if (NULL == samplerate)
211 {
212 err_code = RD_ERROR_NULL;
213 }
214 else if (RD_SUCCESS == environmental_mcu_sensor_sleep())
215 {
216 uint8_t original = *samplerate;
217 *samplerate = RD_SENSOR_CFG_DEFAULT;
218 err_code = success_on_valid (original);
219 }
220 else
221 {
222 err_code |= RD_ERROR_INVALID_STATE;
223 }
224
225 return err_code;
226}
227
229 uint8_t * samplerate)
230{
231 rd_status_t err_code = RD_SUCCESS;
232
233 if (NULL == samplerate)
234 {
235 err_code = RD_ERROR_NULL;
236 }
237 else
238 {
239 *samplerate = RD_SENSOR_CFG_DEFAULT;
240 err_code = RD_SUCCESS;
241 }
242
243 return err_code;
244}
245
246// Temperature resolution is fixed to 10 bits, including sign. Return error to driver, but mark used value to pointer.
248 uint8_t * resolution)
249{
250 rd_status_t err_code = RD_SUCCESS;
251 uint8_t original = *resolution;
252
253 if (NULL == resolution)
254 {
255 err_code |= RD_ERROR_NULL;
256 }
257 else if (RD_SUCCESS == environmental_mcu_sensor_sleep())
258 {
259 *resolution = NRF52_TEMP_SENSOR_RESOLUTION;
260 err_code = success_on_valid (original);
261 }
262 else
263 {
264 err_code |= RD_ERROR_INVALID_STATE;
265 }
266
267 return err_code;
268}
269
271 uint8_t * resolution)
272{
273 rd_status_t err_code = RD_SUCCESS;
274
275 if (NULL == resolution)
276 {
277 err_code = RD_ERROR_NULL;
278 }
279 else
280 {
281 *resolution = NRF52_TEMP_SENSOR_RESOLUTION;
282 }
283
284 return err_code;
285}
286
287// Scale cannot be set. Our scale is fixed at (2^9) / 4 = 128 (or -127).
289{
290 rd_status_t err_code = RD_SUCCESS;
291 uint8_t original = *scale;
292
293 if (NULL == scale)
294 {
295 err_code |= RD_ERROR_NULL;
296 }
297 else if (RD_SUCCESS == environmental_mcu_sensor_sleep())
298 {
299 *scale = NRF52_TEMP_FIXED_SCALE;
300 err_code = success_on_valid (original);
301 }
302 else
303 {
304 err_code |= RD_ERROR_INVALID_STATE;
305 }
306
307 return err_code;
308}
309
311{
312 rd_status_t err_code = RD_SUCCESS;
313
314 if (NULL == scale)
315 {
316 err_code = RD_ERROR_NULL;
317 }
318 else
319 {
320 *scale = NRF52_TEMP_FIXED_SCALE;
321 }
322
323 return err_code;
324}
325
326// Return success on DSP_LAST and acceptable defaults, not supported otherwise
328 uint8_t * parameter)
329{
331 uint8_t original = *dsp;
332
333 if ( (NULL == dsp) || (NULL == parameter))
334 {
335 err_code |= RD_ERROR_NULL;
336 }
337 else if (RD_SUCCESS == environmental_mcu_sensor_sleep())
338 {
340 *parameter = RD_SENSOR_ERR_NOT_SUPPORTED;
341 err_code = success_on_valid (original);
342 }
343 else
344 {
345 err_code |= RD_ERROR_INVALID_STATE;
346 }
347
348 return err_code;
349}
350
352 uint8_t * parameter)
353{
354 *dsp = RD_SENSOR_DSP_LAST;
355 *parameter = 1;
356 return RD_SUCCESS;
357}
358
359// Start single on command, mark autorefresh with continuous
361{
363
364 if (NULL == mode)
365 {
366 err_code = RD_ERROR_NULL;
367 }
368 // Enter sleep by default and by explicit sleep commmand
369 else if ( (RD_SENSOR_CFG_SLEEP == *mode) || (RD_SENSOR_CFG_DEFAULT == *mode))
370 {
371 autorefresh = false;
372 *mode = RD_SENSOR_CFG_SLEEP;
373 err_code = RD_SUCCESS;
374 }
375 else if (RD_SENSOR_CFG_SINGLE == *mode)
376 {
377 // Do nothing if sensor is in continuous mode
378 uint8_t current_mode;
379 ri_environmental_mcu_mode_get (&current_mode);
380
381 if (RD_SENSOR_CFG_CONTINUOUS == current_mode)
382 {
384 err_code = RD_ERROR_INVALID_STATE;
385 }
386 else
387 {
388 // Enter sleep after measurement
389 autorefresh = false;
390 *mode = RD_SENSOR_CFG_SLEEP;
391 // Global float is updated by sample
392 nrf52832_temperature_sample();
393 err_code = RD_SUCCESS;
394 }
395 }
396 else if (RD_SENSOR_CFG_CONTINUOUS == *mode)
397 {
398 autorefresh = true;
399 err_code = RD_SUCCESS;
400 }
401 else
402 {
404 }
405
406 return err_code;
407}
408
410{
411 rd_status_t err_code = RD_SUCCESS;
412
413 if (NULL == mode)
414 {
415 err_code = RD_ERROR_NULL;
416 }
417 else if (autorefresh)
418 {
420 }
421 else if (!autorefresh)
422 {
423 *mode = RD_SENSOR_CFG_SLEEP;
424 }
425 else
426 {
427 *mode = RD_SENSOR_ERR_INVALID;
428 }
429
430 return err_code;
431}
432
434 rd_sensor_data_t * const p_data)
435{
436 rd_status_t err_code = RD_SUCCESS;
437
438 if (NULL == p_data)
439 {
440 err_code = RD_ERROR_NULL;
441 }
442 else
443 {
444 if (autorefresh)
445 {
446 nrf52832_temperature_sample();
447 }
448
449 if (!isnan (temperature))
450 {
451 rd_sensor_data_t d_environmental;
452 rd_sensor_data_fields_t env_fields = {.bitfield = 0};
453 float env_values[1];
454 env_values[0] = temperature;
455 env_fields.datas.temperature_c = 1;
456 d_environmental.data = env_values;
457 d_environmental.valid = env_fields;
458 d_environmental.fields = env_fields;
460 &d_environmental,
461 p_data->fields);
462 p_data->timestamp_ms = tsample;
463 }
464 }
465
466 return err_code;
467}
468
469#endif
rd_status_t ri_environmental_mcu_mode_set(uint8_t *)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_scale_set(uint8_t *scale)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_mode_get(uint8_t *)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_init(rd_sensor_t *environmental_sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
rd_status_t ri_environmental_mcu_resolution_get(uint8_t *resolution)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_samplerate_get(uint8_t *samplerate)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_samplerate_set(uint8_t *samplerate)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_resolution_set(uint8_t *resolution)
rd_sensor_setup_fp
rd_status_t ri_environmental_mcu_dsp_get(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
rd_status_t ri_environmental_mcu_dsp_set(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
rd_status_t ri_environmental_mcu_data_get(rd_sensor_data_t *const data)
rd_sensor_data_fp
rd_status_t ri_environmental_mcu_uninit(rd_sensor_t *environmental_sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
rd_status_t ri_environmental_mcu_scale_get(uint8_t *scale)
rd_sensor_setup_fp
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#define RD_ERROR_NULL
Null Pointer.
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_UINT64_INVALID
Signal that value should not be used.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#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.
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_CFG_NO_CHANGE
Do not change configured value.
rd_bus_t
Type of bus sensor uses.
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.
#define NRF_SDH_ENABLED
Required by SDK BLE module conditional compilation.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Ruuvi sensor interface Lifecycle: Beta
unsigned int temperature_c
Temperature, celcius.
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_setup_fp mode_get
rd_sensor_setup_fp
rd_sensor_setup_fp samplerate_set
rd_sensor_setup_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.