1 /*
2 * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <nrfx.h>
32
33 #if NRFX_CHECK(NRFX_SAADC_ENABLED)
34 #include <nrfx_saadc.h>
35
36 #define NRFX_LOG_MODULE SAADC
37 #include <nrfx_log.h>
38
39 #define EVT_TO_STR(event) \
40 (event == NRF_SAADC_EVENT_STARTED ? "NRF_SAADC_EVENT_STARTED" : \
41 (event == NRF_SAADC_EVENT_END ? "NRF_SAADC_EVENT_END" : \
42 (event == NRF_SAADC_EVENT_DONE ? "NRF_SAADC_EVENT_DONE" : \
43 (event == NRF_SAADC_EVENT_RESULTDONE ? "NRF_SAADC_EVENT_RESULTDONE" : \
44 (event == NRF_SAADC_EVENT_CALIBRATEDONE ? "NRF_SAADC_EVENT_CALIBRATEDONE" : \
45 (event == NRF_SAADC_EVENT_STOPPED ? "NRF_SAADC_EVENT_STOPPED" : \
46 "UNKNOWN EVENT"))))))
47
48
49 typedef enum
50 {
51 NRF_SAADC_STATE_IDLE = 0,
52 NRF_SAADC_STATE_BUSY = 1,
53 NRF_SAADC_STATE_CALIBRATION = 2
54 } nrf_saadc_state_t;
55
56
57 typedef struct
58 {
59 nrf_saadc_input_t pselp;
60 nrf_saadc_input_t pseln;
61 } nrf_saadc_psel_buffer;
62
63 /** @brief SAADC control block.*/
64 typedef struct
65 {
66 nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer.
67 volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer.
68 volatile uint16_t buffer_size; ///< Size of the sample buffer.
69 volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer.
70 volatile nrf_saadc_state_t adc_state; ///< State of the SAADC.
71 uint32_t limits_enabled_flags; ///< Enabled limits flags.
72 uint16_t secondary_buffer_size; ///< Size of the secondary buffer.
73 uint16_t buffer_size_left; ///< When low power mode is active indicates how many samples left to convert on current buffer.
74 nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels.
75 nrfx_drv_state_t state; ///< Driver initialization state.
76 uint8_t active_channels; ///< Number of enabled SAADC channels.
77 bool low_power_mode; ///< Indicates if low power mode is active.
78 bool conversions_end; ///< When low power mode is active indicates end of conversions on current buffer.
79 } nrfx_saadc_cb_t;
80
81 static nrfx_saadc_cb_t m_cb;
82
83 #define LOW_LIMIT_TO_FLAG(channel) ((2 * channel + 1))
84 #define HIGH_LIMIT_TO_FLAG(channel) ((2 * channel))
85 #define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH + \
86 4 * idx))
87 #define LIMIT_EVENT_TO_CHANNEL(event) (uint8_t)(((uint32_t)event - \
88 (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) / 8)
89 #define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) \
90 ? NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH)
91 #define HW_TIMEOUT 10000
92
nrfx_saadc_irq_handler(void)93 void nrfx_saadc_irq_handler(void)
94 {
95 if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
96 {
97 nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
98 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END));
99
100 if (!m_cb.low_power_mode || m_cb.conversions_end)
101 {
102 nrfx_saadc_evt_t evt;
103 evt.type = NRFX_SAADC_EVT_DONE;
104 evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer;
105 evt.data.done.size = m_cb.buffer_size;
106
107 if (m_cb.p_secondary_buffer == NULL)
108 {
109 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
110 }
111 else
112 {
113 m_cb.buffer_size_left = m_cb.secondary_buffer_size;
114 m_cb.p_buffer = m_cb.p_secondary_buffer;
115 m_cb.buffer_size = m_cb.secondary_buffer_size;
116 m_cb.p_secondary_buffer = NULL;
117 if (!m_cb.low_power_mode)
118 {
119 nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
120 }
121 }
122 m_cb.event_handler(&evt);
123 m_cb.conversions_end = false;
124 }
125 }
126 if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
127 {
128 nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
129 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED));
130
131 if (m_cb.buffer_size_left > m_cb.active_channels)
132 {
133 // More samples to convert than for single event.
134 m_cb.buffer_size_left -= m_cb.active_channels;
135 nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size -
136 m_cb.buffer_size_left],
137 m_cb.active_channels);
138 }
139 else if ((m_cb.buffer_size_left == m_cb.active_channels) &&
140
141 (m_cb.p_secondary_buffer != NULL))
142 {
143 // Samples to convert for one event, prepare next buffer.
144 m_cb.conversions_end = true;
145 m_cb.buffer_size_left = 0;
146 nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer,
147 m_cb.active_channels);
148 }
149 else if (m_cb.buffer_size_left == m_cb.active_channels)
150 {
151 // Samples to convert for one event, but no second buffer.
152 m_cb.conversions_end = true;
153 m_cb.buffer_size_left = 0;
154 }
155 nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
156 nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
157 }
158 if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
159 {
160 nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
161 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE));
162 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
163
164 nrfx_saadc_evt_t evt;
165 evt.type = NRFX_SAADC_EVT_CALIBRATEDONE;
166 m_cb.event_handler(&evt);
167 }
168 if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
169 {
170 nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
171 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED));
172 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
173 }
174 else
175 {
176 uint32_t limit_flags = m_cb.limits_enabled_flags;
177 uint32_t flag_idx;
178 nrf_saadc_event_t event;
179
180 while (limit_flags)
181 {
182 flag_idx = __CLZ(limit_flags);
183 limit_flags &= ~((1UL << 31) >> flag_idx);
184 event = FLAG_IDX_TO_EVENT(flag_idx);
185 if (nrf_saadc_event_check(event))
186 {
187 nrf_saadc_event_clear(event);
188 nrfx_saadc_evt_t evt;
189 evt.type = NRFX_SAADC_EVT_LIMIT;
190 evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event);
191 evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event);
192 NRFX_LOG_DEBUG("Event limit, channel: %d, limit type: %d.",
193 evt.data.limit.channel,
194 evt.data.limit.limit_type);
195 m_cb.event_handler(&evt);
196 }
197 }
198 }
199 }
200
201
nrfx_saadc_init(nrfx_saadc_config_t const * p_config,nrfx_saadc_event_handler_t event_handler)202 nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config,
203 nrfx_saadc_event_handler_t event_handler)
204 {
205 NRFX_ASSERT(p_config);
206 NRFX_ASSERT(event_handler);
207 nrfx_err_t err_code;
208
209 if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
210 {
211 err_code = NRFX_ERROR_INVALID_STATE;
212 NRFX_LOG_WARNING("Function: %s, error code: %s.",
213 __func__,
214 NRFX_LOG_ERROR_STRING_GET(err_code));
215 return err_code;
216 }
217
218 m_cb.event_handler = event_handler;
219 nrf_saadc_resolution_set(p_config->resolution);
220 nrf_saadc_oversample_set(p_config->oversample);
221 m_cb.low_power_mode = p_config->low_power_mode;
222 m_cb.state = NRFX_DRV_STATE_INITIALIZED;
223 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
224 m_cb.active_channels = 0;
225 m_cb.limits_enabled_flags = 0;
226 m_cb.conversions_end = false;
227
228 nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
229 nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
230 nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
231 NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, p_config->interrupt_priority);
232 NRFX_IRQ_ENABLE(SAADC_IRQn);
233 nrf_saadc_int_enable(NRF_SAADC_INT_END);
234
235 if (m_cb.low_power_mode)
236 {
237 nrf_saadc_int_enable(NRF_SAADC_INT_STARTED);
238 }
239
240 nrf_saadc_enable();
241
242 err_code = NRFX_SUCCESS;
243 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
244
245 return err_code;
246 }
247
248
nrfx_saadc_uninit(void)249 void nrfx_saadc_uninit(void)
250 {
251 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
252
253 nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
254 NRFX_IRQ_DISABLE(SAADC_IRQn);
255 nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
256
257 // Wait for ADC being stopped.
258 bool result;
259 NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result);
260 NRFX_ASSERT(result);
261
262 nrf_saadc_disable();
263 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
264
265 for (uint32_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel)
266 {
267 if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
268 {
269 nrfx_err_t err_code = nrfx_saadc_channel_uninit(channel);
270 NRFX_ASSERT(err_code == NRFX_SUCCESS);
271 }
272 }
273
274 m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
275 }
276
277
nrfx_saadc_channel_init(uint8_t channel,nrf_saadc_channel_config_t const * const p_config)278 nrfx_err_t nrfx_saadc_channel_init(uint8_t channel,
279 nrf_saadc_channel_config_t const * const p_config)
280 {
281 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
282 NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
283 // Oversampling can be used only with one channel.
284 NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) ||
285 (m_cb.active_channels == 0));
286 NRFX_ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) &&
287 (p_config->pin_p > NRF_SAADC_INPUT_DISABLED));
288 NRFX_ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD);
289
290 nrfx_err_t err_code;
291
292 // A channel can only be initialized if the driver is in the idle state.
293 if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
294 {
295 err_code = NRFX_ERROR_BUSY;
296 NRFX_LOG_WARNING("Function: %s, error code: %s.",
297 __func__,
298 NRFX_LOG_ERROR_STRING_GET(err_code));
299 return err_code;
300 }
301
302 #ifdef NRF52_PAN_74
303 if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) ||
304 (p_config->acq_time == NRF_SAADC_ACQTIME_5US))
305 {
306 nrf_saadc_disable();
307 }
308 #endif //NRF52_PAN_74
309
310 if (m_cb.psel[channel].pselp == NRF_SAADC_INPUT_DISABLED)
311 {
312 ++m_cb.active_channels;
313 }
314 m_cb.psel[channel].pselp = p_config->pin_p;
315 m_cb.psel[channel].pseln = p_config->pin_n;
316 nrf_saadc_channel_init(channel, p_config);
317
318 #ifdef NRF52_PAN_74
319 if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) ||
320 (p_config->acq_time == NRF_SAADC_ACQTIME_5US))
321 {
322 nrf_saadc_enable();
323 }
324 #endif //NRF52_PAN_74
325
326 NRFX_LOG_INFO("Channel initialized: %d.", channel);
327 err_code = NRFX_SUCCESS;
328 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
329 return err_code;
330 }
331
332
nrfx_saadc_channel_uninit(uint8_t channel)333 nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel)
334 {
335 NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
336 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
337
338 nrfx_err_t err_code;
339
340 // A channel can only be uninitialized if the driver is in the idle state.
341 if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
342 {
343 err_code = NRFX_ERROR_BUSY;
344 NRFX_LOG_WARNING("Function: %s, error code: %s.",
345 __func__,
346 NRFX_LOG_ERROR_STRING_GET(err_code));
347 return err_code;
348 }
349
350 if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
351 {
352 --m_cb.active_channels;
353 }
354 m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED;
355 m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED;
356 nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
357 nrfx_saadc_limits_set(channel, NRFX_SAADC_LIMITL_DISABLED, NRFX_SAADC_LIMITH_DISABLED);
358 NRFX_LOG_INFO("Channel denitialized: %d.", channel);
359
360 err_code = NRFX_SUCCESS;
361 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
362 return err_code;
363 }
364
365
nrfx_saadc_sample_task_get(void)366 uint32_t nrfx_saadc_sample_task_get(void)
367 {
368 return nrf_saadc_task_address_get(
369 m_cb.low_power_mode ? NRF_SAADC_TASK_START : NRF_SAADC_TASK_SAMPLE);
370 }
371
372
nrfx_saadc_sample_convert(uint8_t channel,nrf_saadc_value_t * p_value)373 nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value)
374 {
375 nrfx_err_t err_code;
376
377 if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
378 {
379 err_code = NRFX_ERROR_BUSY;
380 NRFX_LOG_WARNING("Function: %s error code: %s.",
381 __func__,
382 NRFX_LOG_ERROR_STRING_GET(err_code));
383 return err_code;
384 }
385 m_cb.adc_state = NRF_SAADC_STATE_BUSY;
386 nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
387 nrf_saadc_buffer_init(p_value, 1);
388 if (m_cb.active_channels > 1)
389 {
390 for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
391 {
392 nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
393 }
394 }
395 nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln);
396 nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
397 nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
398
399 bool result;
400 NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result);
401 NRFX_ASSERT(result);
402
403 nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
404 nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
405
406 NRFX_LOG_INFO("Conversion value: %d, channel %d.", *p_value, channel);
407
408 if (m_cb.active_channels > 1)
409 {
410 for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
411 {
412 nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln);
413 }
414 }
415
416 if (m_cb.low_power_mode)
417 {
418 nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
419 }
420 else
421 {
422 nrf_saadc_int_enable(NRF_SAADC_INT_END);
423 }
424
425 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
426
427 err_code = NRFX_SUCCESS;
428 NRFX_LOG_WARNING("Function: %s, error code: %s.",
429 __func__,
430 NRFX_LOG_ERROR_STRING_GET(err_code));
431 return err_code;
432 }
433
434
nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer,uint16_t size)435 nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size)
436 {
437 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
438 NRFX_ASSERT((size % m_cb.active_channels) == 0);
439 nrfx_err_t err_code;
440
441 nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
442 if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION)
443 {
444 nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
445 err_code = NRFX_ERROR_BUSY;
446 NRFX_LOG_WARNING("Function: %s, error code: %s.",
447 __func__,
448 NRFX_LOG_ERROR_STRING_GET(err_code));
449 return err_code;
450 }
451 if (m_cb.adc_state == NRF_SAADC_STATE_BUSY)
452 {
453 if ( m_cb.p_secondary_buffer)
454 {
455 nrf_saadc_int_enable(NRF_SAADC_INT_END);
456 err_code = NRFX_ERROR_BUSY;
457 NRFX_LOG_WARNING("Function: %s, error code: %s.",
458 __func__,
459 NRFX_LOG_ERROR_STRING_GET(err_code));
460 return err_code;
461 }
462 else
463 {
464 m_cb.p_secondary_buffer = p_buffer;
465 m_cb.secondary_buffer_size = size;
466 if (!m_cb.low_power_mode)
467 {
468 while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0);
469 nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
470 nrf_saadc_buffer_init(p_buffer, size);
471 }
472 nrf_saadc_int_enable(NRF_SAADC_INT_END);
473 err_code = NRFX_SUCCESS;
474 NRFX_LOG_WARNING("Function: %s, error code: %s.",
475 __func__,
476 NRFX_LOG_ERROR_STRING_GET(err_code));
477 return err_code;
478 }
479 }
480 nrf_saadc_int_enable(NRF_SAADC_INT_END);
481 m_cb.adc_state = NRF_SAADC_STATE_BUSY;
482
483 m_cb.p_buffer = p_buffer;
484 m_cb.buffer_size = size;
485 m_cb.p_secondary_buffer = NULL;
486
487 NRFX_LOG_INFO("Function: %s, buffer length: %d, active channels: %d.",
488 __func__,
489 size,
490 m_cb.active_channels);
491
492 if (m_cb.low_power_mode)
493 {
494 m_cb.buffer_size_left = size;
495 nrf_saadc_buffer_init(p_buffer, m_cb.active_channels);
496 }
497 else
498 {
499 nrf_saadc_buffer_init(p_buffer, size);
500 nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
501 nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
502 }
503
504 err_code = NRFX_SUCCESS;
505 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
506 return err_code;
507 }
508
509
nrfx_saadc_sample()510 nrfx_err_t nrfx_saadc_sample()
511 {
512 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
513
514 nrfx_err_t err_code = NRFX_SUCCESS;
515 if (m_cb.adc_state != NRF_SAADC_STATE_BUSY)
516 {
517 err_code = NRFX_ERROR_INVALID_STATE;
518 }
519 else if (m_cb.low_power_mode)
520 {
521 nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
522 }
523 else
524 {
525 nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
526 }
527
528 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
529 return err_code;
530 }
531
532
nrfx_saadc_calibrate_offset()533 nrfx_err_t nrfx_saadc_calibrate_offset()
534 {
535 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
536
537 nrfx_err_t err_code;
538
539 if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
540 {
541 err_code = NRFX_ERROR_BUSY;
542 NRFX_LOG_WARNING("Function: %s, error code: %s.",
543 __func__,
544 NRFX_LOG_ERROR_STRING_GET(err_code));
545 return err_code;
546 }
547
548 m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION;
549
550 nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
551 nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE);
552 nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);
553 err_code = NRFX_SUCCESS;
554 NRFX_LOG_INFO("Function: %s, error code: %s.",
555 __func__,
556 NRFX_LOG_ERROR_STRING_GET(err_code));
557 return err_code;
558 }
559
560
nrfx_saadc_is_busy(void)561 bool nrfx_saadc_is_busy(void)
562 {
563 return (m_cb.adc_state != NRF_SAADC_STATE_IDLE);
564 }
565
566
nrfx_saadc_abort(void)567 void nrfx_saadc_abort(void)
568 {
569 if (nrfx_saadc_is_busy())
570 {
571 nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
572 nrf_saadc_int_enable(NRF_SAADC_INT_STOPPED);
573 nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
574
575 if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION)
576 {
577 m_cb.adc_state = NRF_SAADC_STATE_IDLE;
578 }
579 else
580 {
581 // Wait for ADC being stopped.
582 bool result;
583 NRFX_WAIT_FOR((m_cb.adc_state != NRF_SAADC_STATE_IDLE), HW_TIMEOUT, 0, result);
584 NRFX_ASSERT(result);
585 }
586
587 nrf_saadc_int_disable(NRF_SAADC_INT_STOPPED);
588
589 m_cb.p_buffer = 0;
590 m_cb.p_secondary_buffer = 0;
591 NRFX_LOG_INFO("Conversion aborted.");
592 }
593 }
594
595
nrfx_saadc_limits_set(uint8_t channel,int16_t limit_low,int16_t limit_high)596 void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
597 {
598 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
599 NRFX_ASSERT(m_cb.event_handler); // only non blocking mode supported
600 NRFX_ASSERT(limit_low >= NRFX_SAADC_LIMITL_DISABLED);
601 NRFX_ASSERT(limit_high <= NRFX_SAADC_LIMITH_DISABLED);
602 NRFX_ASSERT(limit_low < limit_high);
603 nrf_saadc_channel_limits_set(channel, limit_low, limit_high);
604
605 uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
606 if (limit_low == NRFX_SAADC_LIMITL_DISABLED)
607 {
608 m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
609 nrf_saadc_int_disable(int_mask);
610 }
611 else
612 {
613 m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
614 nrf_saadc_int_enable(int_mask);
615 }
616
617 int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
618 if (limit_high == NRFX_SAADC_LIMITH_DISABLED)
619 {
620 m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
621 nrf_saadc_int_disable(int_mask);
622 }
623 else
624 {
625 m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
626 nrf_saadc_int_enable(int_mask);
627 }
628 }
629 #endif // NRFX_CHECK(NRFX_SAADC_ENABLED)
630