1 /*
2 * Copyright (c) 2015 - 2020, 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 #if defined(NRF52_SERIES) && !defined(USE_WORKAROUND_FOR_ANOMALY_212)
40 // ANOMALY 212 - SAADC events are missing when switching from single channel
41 // to multi channel configuration with burst enabled.
42 #define USE_WORKAROUND_FOR_ANOMALY_212 1
43 #endif
44
45 #if defined(NRF53_SERIES) || defined(NRF91_SERIES)
46 // Make sure that SAADC is stopped before channel configuration.
47 #define STOP_SAADC_ON_CHANNEL_CONFIG 1
48
49 // Make sure that SAADC calibration samples do not affect next conversions.
50 #define INTERCEPT_SAADC_CALIBRATION_SAMPLES 1
51 #endif
52
53 /** @brief SAADC driver states.*/
54 typedef enum
55 {
56 NRF_SAADC_STATE_UNINITIALIZED = 0,
57 NRF_SAADC_STATE_IDLE,
58 NRF_SAADC_STATE_SIMPLE_MODE,
59 NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE,
60 NRF_SAADC_STATE_ADV_MODE,
61 NRF_SAADC_STATE_ADV_MODE_SAMPLE,
62 NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED,
63 NRF_SAADC_STATE_CALIBRATION
64 } nrf_saadc_state_t;
65
66 /** @brief SAADC control block.*/
67 typedef struct
68 {
69 nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer.
70 nrf_saadc_value_t * p_buffer_primary; ///< Pointer to the primary result buffer.
71 nrf_saadc_value_t * p_buffer_secondary; ///< Pointer to the secondary result buffer.
72 #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
73 nrf_saadc_value_t calib_samples[6]; ///< Scratch buffer for calibration samples.
74 #endif
75 uint16_t size_primary; ///< Size of the primary result buffer.
76 uint16_t size_secondary; ///< Size of the secondary result buffer.
77 uint16_t samples_converted; ///< Number of samples present in result buffer when in the blocking mode.
78 nrf_saadc_input_t channels_pselp[SAADC_CH_NUM]; ///< Array holding each channel positive input.
79 nrf_saadc_input_t channels_pseln[SAADC_CH_NUM]; ///< Array holding each channel negative input.
80 nrf_saadc_state_t saadc_state; ///< State of the SAADC driver.
81 uint8_t channels_configured; ///< Bitmask of the configured channels.
82 uint8_t channels_activated; ///< Bitmask of the activated channels.
83 uint8_t channels_activated_count; ///< Number of the activated channels.
84 uint8_t limits_low_activated; ///< Bitmask of the activated low limits.
85 uint8_t limits_high_activated; ///< Bitmask of the activated high limits.
86 bool start_on_end; ///< Flag indicating if the START task is to be triggered on the END event.
87 bool oversampling_without_burst; ///< Flag indicating whether oversampling without burst is configured.
88 } nrfx_saadc_cb_t;
89
90 static nrfx_saadc_cb_t m_cb;
91
92 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
saadc_anomaly_212_workaround_apply(void)93 static void saadc_anomaly_212_workaround_apply(void)
94 {
95 uint32_t c[SAADC_CH_NUM];
96 uint32_t l[SAADC_CH_NUM];
97
98 for (uint32_t i = 0; i < SAADC_CH_NUM; i++)
99 {
100 c[i] = NRF_SAADC->CH[i].CONFIG;
101 l[i] = NRF_SAADC->CH[i].LIMIT;
102 }
103 nrf_saadc_resolution_t resolution = nrf_saadc_resolution_get(NRF_SAADC);
104 uint32_t u640 = *(volatile uint32_t *)0x40007640;
105 uint32_t u644 = *(volatile uint32_t *)0x40007644;
106 uint32_t u648 = *(volatile uint32_t *)0x40007648;
107
108 *(volatile uint32_t *)0x40007FFC = 0;
109 *(volatile uint32_t *)0x40007FFC = 1;
110
111 for (uint32_t i = 0; i < SAADC_CH_NUM; i++)
112 {
113 NRF_SAADC->CH[i].CONFIG = c[i];
114 NRF_SAADC->CH[i].LIMIT = l[i];
115 }
116 *(volatile uint32_t *)0x40007640 = u640;
117 *(volatile uint32_t *)0x40007644 = u644;
118 *(volatile uint32_t *)0x40007648 = u648;
119 nrf_saadc_resolution_set(NRF_SAADC, resolution);
120 }
121 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
122
saadc_channel_count_get(uint32_t ch_to_activate_mask,uint8_t * p_active_ch_count)123 static nrfx_err_t saadc_channel_count_get(uint32_t ch_to_activate_mask,
124 uint8_t * p_active_ch_count)
125 {
126 NRFX_ASSERT(ch_to_activate_mask);
127 NRFX_ASSERT(ch_to_activate_mask < (1 << SAADC_CH_NUM));
128
129 uint8_t active_ch_count = 0;
130 for (uint32_t ch_mask = 1; ch_mask < (1 << SAADC_CH_NUM); ch_mask <<= 1)
131 {
132 if (ch_to_activate_mask & ch_mask)
133 {
134 // Check if requested channels are configured.
135 if (!(m_cb.channels_configured & ch_mask))
136 {
137 return NRFX_ERROR_INVALID_PARAM;
138 }
139 active_ch_count++;
140 }
141 }
142
143 *p_active_ch_count = active_ch_count;
144 return NRFX_SUCCESS;
145 }
146
saadc_busy_check(void)147 static bool saadc_busy_check(void)
148 {
149 if ((m_cb.saadc_state == NRF_SAADC_STATE_IDLE) ||
150 (m_cb.saadc_state == NRF_SAADC_STATE_ADV_MODE) ||
151 (m_cb.saadc_state == NRF_SAADC_STATE_SIMPLE_MODE))
152 {
153 return false;
154 }
155 else
156 {
157 return true;
158 }
159 }
160
saadc_generic_mode_set(uint32_t ch_to_activate_mask,nrf_saadc_resolution_t resolution,nrf_saadc_oversample_t oversampling,nrf_saadc_burst_t burst,nrfx_saadc_event_handler_t event_handler)161 static void saadc_generic_mode_set(uint32_t ch_to_activate_mask,
162 nrf_saadc_resolution_t resolution,
163 nrf_saadc_oversample_t oversampling,
164 nrf_saadc_burst_t burst,
165 nrfx_saadc_event_handler_t event_handler)
166 {
167 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
168 saadc_anomaly_212_workaround_apply();
169 #endif
170
171 #if NRFX_CHECK(STOP_SAADC_ON_CHANNEL_CONFIG)
172 nrf_saadc_int_disable(NRF_SAADC, NRF_SAADC_INT_STOPPED);
173 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP);
174 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STOPPED))
175 {}
176 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STOPPED);
177 #endif
178
179 m_cb.limits_low_activated = 0;
180 m_cb.limits_high_activated = 0;
181
182 m_cb.p_buffer_primary = NULL;
183 m_cb.p_buffer_secondary = NULL;
184 m_cb.event_handler = event_handler;
185 m_cb.channels_activated = ch_to_activate_mask;
186 m_cb.samples_converted = 0;
187
188 nrf_saadc_resolution_set(NRF_SAADC, resolution);
189 nrf_saadc_oversample_set(NRF_SAADC, oversampling);
190 if (event_handler)
191 {
192 nrf_saadc_int_set(NRF_SAADC,
193 NRF_SAADC_INT_STARTED |
194 NRF_SAADC_INT_STOPPED |
195 NRF_SAADC_INT_END);
196 }
197 else
198 {
199 nrf_saadc_int_set(NRF_SAADC, 0);
200 }
201
202 for (uint32_t ch_pos = 0; ch_pos < SAADC_CH_NUM; ch_pos++)
203 {
204 nrf_saadc_burst_t burst_to_set;
205 nrf_saadc_input_t pselp;
206 nrf_saadc_input_t pseln;
207 if (ch_to_activate_mask & (1 << ch_pos))
208 {
209 pselp = m_cb.channels_pselp[ch_pos];
210 pseln = m_cb.channels_pseln[ch_pos];
211 burst_to_set = burst;
212 }
213 else
214 {
215 pselp = NRF_SAADC_INPUT_DISABLED;
216 pseln = NRF_SAADC_INPUT_DISABLED;
217 burst_to_set = NRF_SAADC_BURST_DISABLED;
218 }
219 nrf_saadc_burst_set(NRF_SAADC, ch_pos, burst_to_set);
220 nrf_saadc_channel_input_set(NRF_SAADC, ch_pos, pselp, pseln);
221 }
222 }
223
nrfx_saadc_init(uint8_t interrupt_priority)224 nrfx_err_t nrfx_saadc_init(uint8_t interrupt_priority)
225 {
226 nrfx_err_t err_code;
227 if (m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED)
228 {
229 err_code = NRFX_ERROR_INVALID_STATE;
230 NRFX_LOG_WARNING("Function: %s, error code: %s.",
231 __func__,
232 NRFX_LOG_ERROR_STRING_GET(err_code));
233 return err_code;
234 }
235 m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
236
237 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED);
238 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STOPPED);
239 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
240 nrf_saadc_int_set(NRF_SAADC, 0);
241 NRFX_IRQ_ENABLE(SAADC_IRQn);
242 NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, interrupt_priority);
243
244 err_code = NRFX_SUCCESS;
245 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
246
247 return err_code;
248 }
249
nrfx_saadc_uninit(void)250 void nrfx_saadc_uninit(void)
251 {
252 nrfx_saadc_abort();
253 NRFX_IRQ_DISABLE(SAADC_IRQn);
254 nrf_saadc_disable(NRF_SAADC);
255 m_cb.saadc_state = NRF_SAADC_STATE_UNINITIALIZED;
256 }
257
nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,uint32_t channel_count)258 nrfx_err_t nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,
259 uint32_t channel_count)
260 {
261 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
262 NRFX_ASSERT(channel_count <= SAADC_CH_NUM);
263
264 if (saadc_busy_check())
265 {
266 return NRFX_ERROR_BUSY;
267 }
268
269 m_cb.channels_configured = 0;
270 uint8_t i = 0;
271
272 for (; i < SAADC_CH_NUM; i++)
273 {
274 m_cb.channels_pselp[i] = NRF_SAADC_INPUT_DISABLED;
275 m_cb.channels_pseln[i] = NRF_SAADC_INPUT_DISABLED;
276 }
277
278 for (i = 0; i < channel_count; i++)
279 {
280 if (m_cb.channels_configured & (1 << p_channels[i].channel_index))
281 {
282 // This channel is already configured!
283 return NRFX_ERROR_INVALID_PARAM;
284 }
285 nrf_saadc_channel_init(NRF_SAADC,
286 p_channels[i].channel_index,
287 &p_channels[i].channel_config);
288
289 NRFX_ASSERT(p_channels[i].pin_p != NRF_SAADC_INPUT_DISABLED);
290 m_cb.channels_pselp[p_channels[i].channel_index] = p_channels[i].pin_p;
291 m_cb.channels_pseln[p_channels[i].channel_index] = p_channels[i].pin_n;
292 m_cb.channels_configured |= 1U << p_channels[i].channel_index;
293 }
294
295 return NRFX_SUCCESS;
296 }
297
nrfx_saadc_simple_mode_set(uint32_t channel_mask,nrf_saadc_resolution_t resolution,nrf_saadc_oversample_t oversampling,nrfx_saadc_event_handler_t event_handler)298 nrfx_err_t nrfx_saadc_simple_mode_set(uint32_t channel_mask,
299 nrf_saadc_resolution_t resolution,
300 nrf_saadc_oversample_t oversampling,
301 nrfx_saadc_event_handler_t event_handler)
302 {
303 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
304
305 if (saadc_busy_check())
306 {
307 return NRFX_ERROR_BUSY;
308 }
309
310 uint8_t active_ch_count;
311 nrfx_err_t err = saadc_channel_count_get(channel_mask, &active_ch_count);
312 if (err != NRFX_SUCCESS)
313 {
314 return err;
315 }
316
317 nrf_saadc_burst_t burst;
318 if (oversampling == NRF_SAADC_OVERSAMPLE_DISABLED)
319 {
320 burst = NRF_SAADC_BURST_DISABLED;
321 }
322 else
323 {
324 // Burst is implicitly enabled if oversampling is enabled.
325 burst = NRF_SAADC_BURST_ENABLED;
326 }
327
328 saadc_generic_mode_set(channel_mask,
329 resolution,
330 oversampling,
331 burst,
332 event_handler);
333
334 m_cb.channels_activated_count = active_ch_count;
335 m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE;
336
337 return NRFX_SUCCESS;
338 }
339
nrfx_saadc_advanced_mode_set(uint32_t channel_mask,nrf_saadc_resolution_t resolution,nrfx_saadc_adv_config_t const * p_config,nrfx_saadc_event_handler_t event_handler)340 nrfx_err_t nrfx_saadc_advanced_mode_set(uint32_t channel_mask,
341 nrf_saadc_resolution_t resolution,
342 nrfx_saadc_adv_config_t const * p_config,
343 nrfx_saadc_event_handler_t event_handler)
344 {
345 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
346 NRFX_ASSERT(p_config);
347
348 if (saadc_busy_check())
349 {
350 return NRFX_ERROR_BUSY;
351 }
352
353 uint8_t active_ch_count;
354 nrfx_err_t err = saadc_channel_count_get(channel_mask, &active_ch_count);
355 if (err != NRFX_SUCCESS)
356 {
357 return err;
358 }
359
360 if ((p_config->internal_timer_cc) && ((active_ch_count > 1) || (!event_handler)))
361 {
362 return NRFX_ERROR_NOT_SUPPORTED;
363 }
364
365 bool oversampling_without_burst = false;
366 if ((p_config->oversampling != NRF_SAADC_OVERSAMPLE_DISABLED) &&
367 (p_config->burst == NRF_SAADC_BURST_DISABLED))
368 {
369 if (active_ch_count > 1)
370 {
371 // Oversampling without burst is possible only on single channel.
372 return NRFX_ERROR_NOT_SUPPORTED;
373 }
374 else
375 {
376 oversampling_without_burst = true;
377 }
378 }
379
380 saadc_generic_mode_set(channel_mask,
381 resolution,
382 p_config->oversampling,
383 p_config->burst,
384 event_handler);
385
386 if (p_config->internal_timer_cc)
387 {
388 nrf_saadc_continuous_mode_enable(NRF_SAADC, p_config->internal_timer_cc);
389 }
390 else
391 {
392 nrf_saadc_continuous_mode_disable(NRF_SAADC);
393 }
394
395 m_cb.channels_activated_count = active_ch_count;
396 m_cb.start_on_end = p_config->start_on_end;
397 m_cb.oversampling_without_burst = oversampling_without_burst;
398
399 m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE;
400
401 return NRFX_SUCCESS;
402 }
403
nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer,uint16_t size)404 nrfx_err_t nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer, uint16_t size)
405 {
406 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
407
408 if (m_cb.p_buffer_secondary)
409 {
410 return NRFX_ERROR_ALREADY_INITIALIZED;
411 }
412
413 if (!nrfx_is_in_ram(p_buffer))
414 {
415 return NRFX_ERROR_INVALID_ADDR;
416 }
417
418 if ((size % m_cb.channels_activated_count != 0) ||
419 (size >= (1 << SAADC_EASYDMA_MAXCNT_SIZE)) ||
420 (!size))
421 {
422 return NRFX_ERROR_INVALID_LENGTH;
423 }
424
425 switch (m_cb.saadc_state)
426 {
427 case NRF_SAADC_STATE_SIMPLE_MODE:
428 if (m_cb.channels_activated_count != size)
429 {
430 return NRFX_ERROR_INVALID_LENGTH;
431 }
432 m_cb.size_primary = size;
433 m_cb.p_buffer_primary = p_buffer;
434 break;
435
436 case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
437 nrf_saadc_buffer_init(NRF_SAADC, p_buffer, size);
438 /* fall-through */
439
440 case NRF_SAADC_STATE_ADV_MODE:
441 /* fall-through */
442
443 case NRF_SAADC_STATE_ADV_MODE_SAMPLE:
444 if (m_cb.p_buffer_primary)
445 {
446 m_cb.size_secondary = size;
447 m_cb.p_buffer_secondary = p_buffer;
448 }
449 else
450 {
451 m_cb.size_primary = size;
452 m_cb.p_buffer_primary = p_buffer;
453 }
454 break;
455
456 default:
457 return NRFX_ERROR_INVALID_STATE;
458 }
459
460 return NRFX_SUCCESS;
461 }
462
nrfx_saadc_mode_trigger(void)463 nrfx_err_t nrfx_saadc_mode_trigger(void)
464 {
465 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
466 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_IDLE);
467
468 if (!m_cb.p_buffer_primary)
469 {
470 return NRFX_ERROR_NO_MEM;
471 }
472
473 nrfx_err_t result = NRFX_SUCCESS;
474 switch (m_cb.saadc_state)
475 {
476 case NRF_SAADC_STATE_SIMPLE_MODE:
477 nrf_saadc_enable(NRF_SAADC);
478 // When in simple blocking or non-blocking mode, buffer size is equal to activated channel count.
479 // Single SAMPLE task is enough to obtain one sample on each activated channel.
480 // This will result in buffer being filled with samples and therefore END event will appear.
481 nrf_saadc_buffer_init(NRF_SAADC, m_cb.p_buffer_primary, m_cb.size_primary);
482 if (m_cb.event_handler)
483 {
484 m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE;
485 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
486 }
487 else
488 {
489 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
490 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STARTED))
491 {}
492 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED);
493
494 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
495 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END))
496 {}
497 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
498 nrf_saadc_disable(NRF_SAADC);
499 }
500 break;
501
502 case NRF_SAADC_STATE_ADV_MODE:
503 nrf_saadc_enable(NRF_SAADC);
504 if (m_cb.event_handler)
505 {
506 // When in advanced non-blocking mode, latch whole buffer in EasyDMA.
507 // END event will arrive when whole buffer is filled with samples.
508 m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE_SAMPLE;
509 nrf_saadc_buffer_init(NRF_SAADC, m_cb.p_buffer_primary, m_cb.size_primary);
510 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
511 break;
512 }
513
514 // When in advanced blocking mode, latch single chunk of buffer in EasyDMA.
515 // Each chunk consists of single sample from each activated channels.
516 // END event will arrive when single chunk is filled with samples.
517 nrf_saadc_buffer_init(NRF_SAADC,
518 &m_cb.p_buffer_primary[m_cb.samples_converted],
519 m_cb.channels_activated_count);
520
521 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
522 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STARTED))
523 {}
524 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED);
525
526 if (m_cb.oversampling_without_burst)
527 {
528 // Oversampling without burst is possible only on single channel.
529 // In this configuration more than one SAMPLE task is needed to obtain single sample.
530 uint32_t samples_to_take =
531 nrf_saadc_oversample_sample_count_get(nrf_saadc_oversample_get(NRF_SAADC));
532
533 for (uint32_t sample_idx = 0; sample_idx < samples_to_take; sample_idx++)
534 {
535 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_DONE);
536 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
537 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_DONE))
538 {}
539 }
540 }
541 else
542 {
543 // Single SAMPLE task is enough to obtain one sample on each activated channel.
544 // This will result in chunk being filled with samples and therefore END event will appear.
545 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
546 }
547 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END))
548 {}
549 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
550
551 m_cb.samples_converted += m_cb.channels_activated_count;
552 if (m_cb.samples_converted < m_cb.size_primary)
553 {
554 result = NRFX_ERROR_BUSY;
555 }
556 else
557 {
558 m_cb.samples_converted = 0;
559 m_cb.p_buffer_primary = m_cb.p_buffer_secondary;
560 m_cb.size_primary = m_cb.size_secondary;
561 m_cb.p_buffer_secondary = NULL;
562 }
563 nrf_saadc_disable(NRF_SAADC);
564 break;
565
566 default:
567 result = NRFX_ERROR_INVALID_STATE;
568 break;
569 }
570
571 return result;
572 }
573
nrfx_saadc_abort(void)574 void nrfx_saadc_abort(void)
575 {
576 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
577
578 if (!m_cb.event_handler)
579 {
580 m_cb.p_buffer_primary = NULL;
581 m_cb.p_buffer_secondary = NULL;
582 m_cb.samples_converted = 0;
583 }
584 else
585 {
586 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP);
587 if (m_cb.saadc_state == NRF_SAADC_STATE_CALIBRATION)
588 {
589 // STOPPED event does not appear when the calibration is ongoing
590 m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
591 }
592 }
593 }
594
nrfx_saadc_limits_set(uint8_t channel,int16_t limit_low,int16_t limit_high)595 nrfx_err_t nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
596 {
597 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
598 NRFX_ASSERT(limit_high >= limit_low);
599
600 if (!m_cb.event_handler)
601 {
602 return NRFX_ERROR_FORBIDDEN;
603 }
604
605 if ((m_cb.saadc_state == NRF_SAADC_STATE_IDLE) ||
606 (m_cb.saadc_state == NRF_SAADC_STATE_CALIBRATION))
607 {
608 return NRFX_ERROR_INVALID_STATE;
609 }
610
611 if (!(m_cb.channels_activated & (1 << channel)))
612 {
613 return NRFX_ERROR_INVALID_PARAM;
614 }
615
616 nrf_saadc_channel_limits_set(NRF_SAADC, channel, limit_low, limit_high);
617
618 uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
619 if (limit_low == INT16_MIN)
620 {
621 m_cb.limits_low_activated &= ~(1 << channel);
622 nrf_saadc_int_disable(NRF_SAADC, int_mask);
623 }
624 else
625 {
626 m_cb.limits_low_activated |= (1 << channel);
627 nrf_saadc_int_enable(NRF_SAADC, int_mask);
628 }
629
630 int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
631 if (limit_high == INT16_MAX)
632 {
633 m_cb.limits_high_activated &= ~(1 << channel);
634 nrf_saadc_int_disable(NRF_SAADC, int_mask);
635 }
636 else
637 {
638 m_cb.limits_high_activated |= (1 << channel);
639 nrf_saadc_int_enable(NRF_SAADC, int_mask);
640 }
641
642 return NRFX_SUCCESS;
643 }
644
nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t event_handler)645 nrfx_err_t nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t event_handler)
646 {
647 NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
648
649 if (saadc_busy_check())
650 {
651 return NRFX_ERROR_BUSY;
652 }
653
654 m_cb.saadc_state = NRF_SAADC_STATE_CALIBRATION;
655 m_cb.event_handler = event_handler;
656
657 nrf_saadc_enable(NRF_SAADC);
658 #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
659 nrf_saadc_buffer_init(NRF_SAADC, m_cb.calib_samples, NRFX_ARRAY_SIZE(m_cb.calib_samples));
660 if (event_handler)
661 {
662 nrf_saadc_int_set(NRF_SAADC, NRF_SAADC_INT_STARTED | NRF_SAADC_INT_CALIBRATEDONE);
663 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
664 }
665 else
666 {
667 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
668 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STARTED))
669 {}
670 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED);
671
672 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_CALIBRATEOFFSET);
673 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE))
674 {}
675 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE);
676 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
677
678 nrf_saadc_disable(NRF_SAADC);
679 m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
680 }
681 #else
682 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_CALIBRATEOFFSET);
683 if (event_handler)
684 {
685 nrf_saadc_int_enable(NRF_SAADC, NRF_SAADC_INT_CALIBRATEDONE);
686 }
687 else
688 {
689 while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE))
690 {}
691 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE);
692 nrf_saadc_disable(NRF_SAADC);
693 m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
694 }
695 #endif // NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
696
697 return NRFX_SUCCESS;
698 }
699
saadc_event_started_handle(void)700 static void saadc_event_started_handle(void)
701 {
702 nrfx_saadc_evt_t evt_data;
703
704 switch (m_cb.saadc_state)
705 {
706 case NRF_SAADC_STATE_ADV_MODE_SAMPLE:
707 evt_data.type = NRFX_SAADC_EVT_READY;
708 m_cb.event_handler(&evt_data);
709
710 if (nrf_saadc_continuous_mode_enable_check(NRF_SAADC))
711 {
712 // Trigger internal timer
713 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
714 }
715
716 m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED;
717 if (m_cb.p_buffer_secondary)
718 {
719 nrf_saadc_buffer_init(NRF_SAADC,
720 m_cb.p_buffer_secondary,
721 m_cb.size_secondary);
722 }
723 /* fall-through */
724
725 case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
726 if (!m_cb.p_buffer_secondary)
727 {
728 // Send next buffer request only if it was not provided earlier,
729 // before conversion start or outside of user's callback context.
730 evt_data.type = NRFX_SAADC_EVT_BUF_REQ;
731 m_cb.event_handler(&evt_data);
732 }
733 break;
734
735 case NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE:
736 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
737 break;
738
739 #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
740 case NRF_SAADC_STATE_CALIBRATION:
741 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_CALIBRATEOFFSET);
742 break;
743 #endif
744
745 default:
746 break;
747 }
748 }
749
saadc_event_end_handle(void)750 static void saadc_event_end_handle(void)
751 {
752 nrfx_saadc_evt_t evt_data;
753 evt_data.type = NRFX_SAADC_EVT_DONE;
754 evt_data.data.done.p_buffer = m_cb.p_buffer_primary;
755 evt_data.data.done.size = m_cb.size_primary;
756 m_cb.event_handler(&evt_data);
757
758 switch (m_cb.saadc_state)
759 {
760 case NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE:
761 nrf_saadc_disable(NRF_SAADC);
762 m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE;
763 break;
764
765 case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
766 m_cb.p_buffer_primary = m_cb.p_buffer_secondary;
767 m_cb.size_primary = m_cb.size_secondary;
768 m_cb.p_buffer_secondary = NULL;
769 if (m_cb.p_buffer_primary)
770 {
771 if (m_cb.start_on_end)
772 {
773 nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);
774 }
775 }
776 else
777 {
778 nrf_saadc_disable(NRF_SAADC);
779 m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE;
780 evt_data.type = NRFX_SAADC_EVT_FINISHED;
781 m_cb.event_handler(&evt_data);
782 }
783 break;
784
785 default:
786 break;
787 }
788 }
789
saadc_event_limits_handle(uint8_t limits_activated,nrf_saadc_limit_t limit_type)790 static void saadc_event_limits_handle(uint8_t limits_activated, nrf_saadc_limit_t limit_type)
791 {
792 while (limits_activated)
793 {
794 uint8_t channel = __CLZ(__RBIT((uint32_t)limits_activated));
795 limits_activated &= ~(1 << channel);
796
797 nrf_saadc_event_t event = nrf_saadc_limit_event_get(channel, limit_type);
798 if (nrf_saadc_event_check(NRF_SAADC, event))
799 {
800 nrf_saadc_event_clear(NRF_SAADC, event);
801
802 nrfx_saadc_evt_t evt_data;
803 evt_data.type = NRFX_SAADC_EVT_LIMIT;
804 evt_data.data.limit.channel = channel;
805 evt_data.data.limit.limit_type = limit_type;
806 m_cb.event_handler(&evt_data);
807 }
808 }
809 }
810
nrfx_saadc_irq_handler(void)811 void nrfx_saadc_irq_handler(void)
812 {
813 if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STARTED))
814 {
815 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED);
816 saadc_event_started_handle();
817 }
818
819 if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STOPPED))
820 {
821 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STOPPED);
822
823 // If there was ongoing conversion the STOP task also triggers the END event
824 m_cb.size_primary = nrf_saadc_amount_get(NRF_SAADC);
825 m_cb.p_buffer_secondary = NULL;
826 /* fall-through to the END event handler */
827 }
828
829 if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END))
830 {
831 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
832
833 #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
834 // When samples are intercepted into scratch buffer during calibration,
835 // END event appears when the calibration finishes. This event should be ignored.
836 if (m_cb.saadc_state != NRF_SAADC_STATE_CALIBRATION)
837 #endif
838 {
839 saadc_event_end_handle();
840 }
841 }
842
843 saadc_event_limits_handle(m_cb.limits_low_activated, NRF_SAADC_LIMIT_LOW);
844 saadc_event_limits_handle(m_cb.limits_high_activated, NRF_SAADC_LIMIT_HIGH);
845
846 if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE))
847 {
848 nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE);
849 nrf_saadc_disable(NRF_SAADC);
850
851 m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
852
853 nrfx_saadc_evt_t evt_data;
854 evt_data.type = NRFX_SAADC_EVT_CALIBRATEDONE;
855 m_cb.event_handler(&evt_data);
856
857 }
858 }
859 #endif // NRFX_CHECK(NRFX_SAADC_ENABLED)
860