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