48 #if RUUVI_NRF5_SDK15_ADC_ENABLED
52 #include "nrf_drv_saadc.h"
56 #define ADC_REF_VOLTAGE_INVALID 0.0000f
57 #define ADC_REF_DIVIDER_INVALID 0.0000f
58 #define ADC_REF_VOLTAGE_IN_VOLTS 0.600f
59 #define ADC_REF_EXT_VDD_DIV 4
60 #define ADC_PRE_SCALING_COMPENSATION_1_6 6.00f
61 #define ADC_PRE_SCALING_COMPENSATION_1_5 5.00f
62 #define ADC_PRE_SCALING_COMPENSATION_1_4 4.00f
63 #define ADC_PRE_SCALING_COMPENSATION_1_3 3.00f
64 #define ADC_PRE_SCALING_COMPENSATION_1_2 2.00f
65 #define ADC_PRE_SCALING_COMPENSATION_1 1.00f
66 #define ADC_PRE_SCALING_COMPENSATION_2 0.50f
67 #define ADC_PRE_SCALING_COMPENSATION_4 0.25f
68 #define ADC_PRE_SCALING_NUM 8
70 #define ADC_BITS_RESOLUTION_8 8
71 #define ADC_BITS_RESOLUTION_10 10
72 #define ADC_BITS_RESOLUTION_12 12
73 #define ADC_BITS_RESOLUTION_14 14
74 #define ADC_BITS_RESOLUTION_NUM 4
76 static float pre_scaling_values[ADC_PRE_SCALING_NUM] =
78 ADC_PRE_SCALING_COMPENSATION_1_6,
79 ADC_PRE_SCALING_COMPENSATION_1_5,
80 ADC_PRE_SCALING_COMPENSATION_1_4,
81 ADC_PRE_SCALING_COMPENSATION_1_3,
82 ADC_PRE_SCALING_COMPENSATION_1_2,
83 ADC_PRE_SCALING_COMPENSATION_1,
84 ADC_PRE_SCALING_COMPENSATION_2,
85 ADC_PRE_SCALING_COMPENSATION_4
88 static nrf_saadc_channel_config_t channel_configs[NRF_SAADC_CHANNEL_COUNT];
89 static nrf_saadc_channel_config_t * p_channel_configs[NRF_SAADC_CHANNEL_COUNT] =
91 NULL, NULL, NULL, NULL,
92 NULL, NULL, NULL, NULL
94 static bool m_adc_is_init =
false;
95 static nrf_drv_saadc_config_t adc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
97 static uint8_t bits_resolution[ADC_BITS_RESOLUTION_NUM] =
99 ADC_BITS_RESOLUTION_8, ADC_BITS_RESOLUTION_10,
100 ADC_BITS_RESOLUTION_12, ADC_BITS_RESOLUTION_14,
109 return (nrf_saadc_oversample_t) oversample;
118 return (nrf_saadc_resolution_t) resolution;
124 static inline uint8_t nrf_to_bits_resolution (
const nrf_saadc_resolution_t resolution)
126 return bits_resolution[resolution];
132 static inline nrf_saadc_input_t ruuvi_to_nrf_channel (
const ri_adc_channel_t channel)
134 return (nrf_saadc_input_t) channel;
140 static inline nrf_saadc_reference_t ruuvi_to_nrf_vref (
const ri_adc_vref_t vref)
142 nrf_saadc_reference_t nrfref = NRF_SAADC_REFERENCE_INTERNAL;
147 nrfref = NRF_SAADC_REFERENCE_VDD4;
154 nrfref = NRF_SAADC_REFERENCE_INTERNAL;
164 static inline nrf_saadc_mode_t ruuvi_to_nrf_mode (
const ri_adc_mode_t mode)
166 return (nrf_saadc_mode_t) mode;
172 static inline ri_adc_gain_t nrf_to_ruuvi_gain (
const nrf_saadc_gain_t gain)
180 static inline ri_adc_vref_t nrf_to_ruuvi_vref (
const nrf_saadc_reference_t gain)
185 #ifdef RI_ADC_ADV_CONFIG
190 static inline nrf_saadc_resistor_t ruuvi_to_nrf_resistor (
const nri_adc_resistor_t
193 return (nrf_saadc_resistor_t) resistor;
199 static inline nrf_saadc_acqtime_t ruuvi_to_nrf_acqtime (
const ri_adc_acqtime_t acqtime)
201 return (nrf_saadc_acqtime_t) acqtime;
209 static inline nrf_saadc_gain_t ruuvi_to_nrf_gain (
const ri_adc_gain_t gain)
211 return (nrf_saadc_gain_t) gain;
218 static float raw_adc_to_volts (uint8_t channel_num,
222 nrf_saadc_channel_config_t * p_ch_config =
223 p_channel_configs[channel_num];
224 uint16_t counts = 1 << nrf_to_bits_resolution (adc_config.resolution);
228 if (NRF_SAADC_REFERENCE_INTERNAL == p_ch_config->reference)
230 result = (ADC_REF_VOLTAGE_IN_VOLTS * ( (float) (*adc) / (float) counts) *
231 pre_scaling_values[ (uint8_t) nrf_to_ruuvi_gain (p_ch_config->gain)] *
237 result = (p_config->
vdd * ( (float) (*adc) / (float) counts)
238 * pre_scaling_values[ (uint8_t) nrf_to_ruuvi_gain (p_ch_config->gain)]
239 / ADC_REF_EXT_VDD_DIV
249 static float raw_adc_to_ratio (uint8_t channel_num,
253 nrf_saadc_channel_config_t * p_ch_config =
254 p_channel_configs[channel_num];
255 uint16_t counts = 1 << nrf_to_bits_resolution (adc_config.resolution);
259 if (NRF_SAADC_REFERENCE_INTERNAL == p_ch_config->reference)
262 result = (ADC_REF_VOLTAGE_IN_VOLTS * ( (float) (*adc) / (float) counts) *
263 pre_scaling_values[ (uint8_t) nrf_to_ruuvi_gain (p_ch_config->gain)] *
266 result /= p_config->
vdd;
271 result = ( (float) (*adc) / (float) counts);
283 static void saadc_event_handler (nrf_drv_saadc_evt_t
const * p_evt)
285 if (p_evt->type == NRF_DRV_SAADC_EVT_DONE)
292 return m_adc_is_init;
301 if (NULL != p_config)
303 adc_config.resolution = ruuvi_to_nrf_resolution (p_config->
resolution);
304 adc_config.oversample = ruuvi_to_nrf_oversample (p_config->
oversample);
307 if (NRF_SUCCESS == nrf_drv_saadc_init (&adc_config, saadc_event_handler))
309 m_adc_is_init =
true;
327 nrf_drv_saadc_uninit();
329 if (
true == config_default)
331 nrf_drv_saadc_config_t def_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
332 memcpy (&adc_config, &def_config,
sizeof (nrf_drv_saadc_config_t));
334 for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; i++)
336 p_channel_configs[i] = NULL;
340 m_adc_is_init =
false;
352 if (NRF_SAADC_CHANNEL_COUNT > channel_num)
354 nrf_drv_saadc_config_t def_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
356 if (NULL != p_channel_configs[ channel_num])
358 memcpy (&channel_configs[ channel_num],
360 sizeof (nrf_drv_saadc_config_t));
361 p_channel_configs[ channel_num] = NULL;
363 if (NRF_SUCCESS != nrf_drv_saadc_channel_uninit (channel_num))
386 if (
true == nrf_drv_saadc_is_busy())
388 nrf_drv_saadc_abort();
391 if ( (NULL != p_pins) && (NULL != p_config))
393 if ( (NRF_SAADC_CHANNEL_COUNT > channel_num) &&
394 (p_channel_configs[ channel_num] == NULL))
396 nrf_saadc_channel_config_t ch_config;
397 #ifdef RI_ADC_ADV_MODE_CONFIG
399 if (RI_ADC_MODE_DIFFERENTIAL == p_config->
mode)
401 nrf_saadc_channel_config_t def_config = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL (
403 ruuvi_to_nrf_channel (p_pins->n_pin.channel));
404 memcpy (&ch_config, &def_config,
sizeof (nrf_saadc_channel_config_t));
405 #ifdef RI_ADC_ADV_CONFIG
406 ch_config.resistor_p = ruuvi_to_nrf_resistor (p_pins->
p_pin.resistor);
407 ch_config.resistor_n = ruuvi_to_nrf_resistor (p_pins->n_pin.resistor);
413 nrf_saadc_channel_config_t def_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE (
415 memcpy (&ch_config, &def_config,
sizeof (nrf_saadc_channel_config_t));
416 #ifdef RI_ADC_ADV_CONFIG
417 ch_config.resistor_p = ruuvi_to_nrf_resistor (p_pins->
p_pin.resistor);
419 #ifdef RI_ADC_ADV_MODE_CONFIG
423 ch_config.reference = ruuvi_to_nrf_vref (p_config->
vref);
424 #ifdef RI_ADC_ADV_CONFIG
425 ch_config.acq_time = ruuvi_to_nrf_acqtime (p_config->acqtime);
430 if (NRF_SAADC_REFERENCE_INTERNAL == ch_config.reference)
440 ch_config.gain = ruuvi_to_nrf_gain (p_config->
gain);
441 memcpy (&channel_configs[ channel_num],
443 sizeof (nrf_saadc_channel_config_t));
444 p_channel_configs[ channel_num] =
445 &channel_configs[ channel_num];
447 for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; i++)
449 if (NULL != p_channel_configs[i])
451 if (NRF_SUCCESS != nrf_drv_saadc_channel_init (i, &channel_configs[i]))
480 nrf_saadc_value_t adc_buf;
482 if (NRF_SUCCESS == nrf_drv_saadc_sample_convert (channel_num, &adc_buf))
484 (*p_data) = (int16_t) (adc_buf);
494 static rd_status_t nrf5_adc_get_raw (uint8_t channel_num,
496 int16_t *
const p_data)
500 if (NULL == p_config || NULL == p_data)
506 nrf_saadc_channel_config_t * p_ch_config =
507 p_channel_configs[channel_num];
509 if ( (NULL == p_ch_config) ||
510 (p_config->
vdd == ADC_REF_VOLTAGE_INVALID) ||
511 (p_config->
divider == ADC_REF_DIVIDER_INVALID) ||
514 nrf_to_ruuvi_vref (p_ch_config->reference))))
533 rd_status_t status = nrf5_adc_get_raw (channel_num, p_config, &data);
537 (*p_data) = raw_adc_to_volts (channel_num, p_config, &data);
549 rd_status_t status = nrf5_adc_get_raw (channel_num, p_config, &data);
553 (*p_data) = raw_adc_to_ratio (channel_num, p_config, &data);
561 return ch < NRF_SAADC_CHANNEL_COUNT;
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#define RD_ERROR_NULL
Null Pointer.
uint32_t rd_status_t
bitfield for representing errors
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Interface for controlling ADC onboard MCU.
rd_status_t ri_adc_uninit(bool config_default)
Uninitialize ADC.
rd_status_t ri_adc_get_raw_data(uint8_t channel_num, int16_t *p_data)
Get raw ADC data.
@ RI_ADC_VREF_EXTERNAL
External voltage reference.
@ RI_ADC_VREF_INTERNAL
Internal voltage reference.
rd_status_t ri_adc_get_data_ratio(uint8_t channel_num, ri_adc_get_data_t *p_config, float *p_data)
Get ADC data in volts.
rd_status_t ri_adc_get_data_absolute(uint8_t channel_num, ri_adc_get_data_t *p_config, float *p_data)
Get ADC data in volts.
ri_adc_channel_t
Enable implementation selected by application.
bool ri_adc_mcu_is_valid_ch(const uint8_t ch)
Return true if given channel index can be used by underlying implementation.
rd_status_t ri_adc_stop(uint8_t channel_num)
Stop use ADC channel.
rd_status_t ri_adc_configure(uint8_t channel_num, ri_adc_pins_config_t *p_pins, ri_adc_channel_config_t *p_config)
Configure ADC channel.
rd_status_t ri_adc_init(ri_adc_config_t *p_config)
Initialization of ADC.
bool ri_adc_is_init(void)
Check if ADC is initialized.
ri_adc_oversample_t oversample
ri_adc_resolution_t resolution
ri_adc_pin_config_t p_pin