1 /*
2  * Copyright (c) 2015 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <nrfx.h>
34 
35 #if NRFX_CHECK(NRFX_SAADC_ENABLED)
36 #include <nrfx_saadc.h>
37 
38 #define NRFX_LOG_MODULE SAADC
39 #include <nrfx_log.h>
40 
41 #if defined(NRF52_SERIES) && !defined(USE_WORKAROUND_FOR_ANOMALY_212)
42     // ANOMALY 212 - SAADC events are missing when switching from single channel
43     //               to multi channel configuration with burst enabled.
44     #define USE_WORKAROUND_FOR_ANOMALY_212 1
45 #endif
46 
47 #if defined(NRF53_SERIES) || defined(NRF91_SERIES)
48     // Make sure that SAADC is stopped before channel configuration.
49     #define STOP_SAADC_ON_CHANNEL_CONFIG 1
50 #endif
51 
52 /** @brief Bitmask of all available SAADC channels. */
53 #define SAADC_ALL_CHANNELS_MASK ((1UL << SAADC_CH_NUM) - 1UL)
54 
55 /** @brief SAADC driver states.*/
56 typedef enum
57 {
58     NRF_SAADC_STATE_UNINITIALIZED = 0,
59     NRF_SAADC_STATE_IDLE,
60     NRF_SAADC_STATE_SIMPLE_MODE,
61     NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE,
62     NRF_SAADC_STATE_ADV_MODE,
63     NRF_SAADC_STATE_ADV_MODE_SAMPLE,
64     NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED,
65     NRF_SAADC_STATE_CALIBRATION
66 } nrf_saadc_state_t;
67 
68 /** @brief SAADC control block.*/
69 typedef struct
70 {
71     nrfx_saadc_event_handler_t event_handler;                ///< Event handler function pointer.
72     nrfx_saadc_event_handler_t calib_event_handler;          ///< Event handler function pointer for calibration event.
73     nrfy_saadc_buffer_t        buffer_primary;               ///< Primary buffer description structure.
74     nrfy_saadc_buffer_t        buffer_secondary;             ///< Secondary buffer description structure.
75     uint16_t                   calib_samples[2];             ///< Scratch buffer for post-calibration samples.
76     uint16_t                   samples_converted;            ///< Number of samples present in result buffer when in the blocking mode.
77     nrfy_saadc_channel_input_t channels_input[SAADC_CH_NUM]; ///< Array holding input of each of the channels.
78     nrf_saadc_state_t          saadc_state;                  ///< State of the SAADC driver.
79     nrf_saadc_state_t          saadc_state_prev;             ///< Previous state of the SAADC driver.
80     uint8_t                    channels_configured;          ///< Bitmask of the configured channels.
81     uint8_t                    channels_activated;           ///< Bitmask of the activated channels.
82     uint8_t                    channels_activated_count;     ///< Number of the activated channels.
83     uint8_t                    limits_low_activated;         ///< Bitmask of the activated low limits.
84     uint8_t                    limits_high_activated;        ///< Bitmask of the activated high limits.
85     bool                       start_on_end;                 ///< Flag indicating if the START task is to be triggered on the END event.
86     bool                       oversampling_without_burst;   ///< Flag indicating whether oversampling without burst is configured.
87 } nrfx_saadc_cb_t;
88 
89 static nrfx_saadc_cb_t m_cb;
90 
91 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
saadc_anomaly_212_workaround_apply(void)92 static void saadc_anomaly_212_workaround_apply(void)
93 {
94     uint32_t c[SAADC_CH_NUM];
95     uint32_t l[SAADC_CH_NUM];
96 
97     for (uint32_t i = 0; i < SAADC_CH_NUM; i++)
98     {
99         c[i] = NRF_SAADC->CH[i].CONFIG;
100         l[i] = NRF_SAADC->CH[i].LIMIT;
101     }
102     nrf_saadc_resolution_t resolution = nrfy_saadc_resolution_get(NRF_SAADC);
103     uint32_t u640 = *(volatile uint32_t *)0x40007640;
104     uint32_t u644 = *(volatile uint32_t *)0x40007644;
105     uint32_t u648 = *(volatile uint32_t *)0x40007648;
106 
107     *(volatile uint32_t *)0x40007FFC = 0;
108     *(volatile uint32_t *)0x40007FFC = 1;
109 
110     for (uint32_t i = 0; i < SAADC_CH_NUM; i++)
111     {
112         NRF_SAADC->CH[i].CONFIG = c[i];
113         NRF_SAADC->CH[i].LIMIT = l[i];
114     }
115     *(volatile uint32_t *)0x40007640 = u640;
116     *(volatile uint32_t *)0x40007644 = u644;
117     *(volatile uint32_t *)0x40007648 = u648;
118     nrfy_saadc_resolution_set(NRF_SAADC, resolution);
119 }
120 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
121 
saadc_channel_count_get(uint32_t ch_to_activate_mask,uint8_t * p_active_ch_count)122 static nrfx_err_t saadc_channel_count_get(uint32_t  ch_to_activate_mask,
123                                           uint8_t * p_active_ch_count)
124 {
125     NRFX_ASSERT(ch_to_activate_mask);
126     NRFX_ASSERT(ch_to_activate_mask < (1 << SAADC_CH_NUM));
127 
128     uint8_t active_ch_count = 0;
129     for (uint32_t ch_mask = 1; ch_mask < (1 << SAADC_CH_NUM); ch_mask <<= 1)
130     {
131         if (ch_to_activate_mask & ch_mask)
132         {
133             // Check if requested channels are configured.
134             if (!(m_cb.channels_configured & ch_mask))
135             {
136                 return NRFX_ERROR_INVALID_PARAM;
137             }
138             active_ch_count++;
139         }
140     }
141 
142     *p_active_ch_count = active_ch_count;
143     return NRFX_SUCCESS;
144 }
145 
saadc_channel_config(nrfx_saadc_channel_t const * p_channel)146 static void saadc_channel_config(nrfx_saadc_channel_t const * p_channel)
147 {
148     NRFX_ASSERT(p_channel->pin_p != NRF_SAADC_INPUT_DISABLED);
149 
150     uint8_t channel_index = p_channel->channel_index;
151     nrfy_saadc_channel_configure(NRF_SAADC, channel_index, &p_channel->channel_config, NULL);
152     m_cb.channels_input[channel_index].input_p = p_channel->pin_p;
153     m_cb.channels_input[channel_index].input_n = p_channel->pin_n;
154     m_cb.channels_configured |= (uint8_t)(1U << channel_index);
155 }
156 
saadc_channels_deconfig(uint32_t channel_mask)157 static void saadc_channels_deconfig(uint32_t channel_mask)
158 {
159     while (channel_mask)
160     {
161         uint8_t channel = (uint8_t)NRF_CTZ(channel_mask);
162 
163         channel_mask             &= ~(1UL << channel);
164         m_cb.channels_configured &= (uint8_t)~(1UL << channel);
165 
166         m_cb.channels_input[channel].input_p = NRF_SAADC_INPUT_DISABLED;
167         m_cb.channels_input[channel].input_n = NRF_SAADC_INPUT_DISABLED;
168     }
169 }
170 
saadc_channels_disable(uint32_t channel_mask)171 static void saadc_channels_disable(uint32_t channel_mask)
172 {
173     while (channel_mask)
174     {
175         uint8_t channel = (uint8_t)NRF_CTZ(channel_mask);
176         channel_mask &= ~(1UL << channel);
177         nrfy_saadc_channel_input_set(NRF_SAADC, channel,
178                                      NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
179     }
180 }
181 
saadc_busy_check(void)182 static bool saadc_busy_check(void)
183 {
184     if ((m_cb.saadc_state == NRF_SAADC_STATE_IDLE)     ||
185         (m_cb.saadc_state == NRF_SAADC_STATE_ADV_MODE) ||
186         (m_cb.saadc_state == NRF_SAADC_STATE_SIMPLE_MODE))
187     {
188         return false;
189     }
190     else
191     {
192         return true;
193     }
194 }
195 
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)196 static void saadc_generic_mode_set(uint32_t                   ch_to_activate_mask,
197                                    nrf_saadc_resolution_t     resolution,
198                                    nrf_saadc_oversample_t     oversampling,
199                                    nrf_saadc_burst_t          burst,
200                                    nrfx_saadc_event_handler_t event_handler)
201 {
202 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
203     saadc_anomaly_212_workaround_apply();
204 #endif
205 
206 #if NRFX_CHECK(STOP_SAADC_ON_CHANNEL_CONFIG)
207     nrfy_saadc_int_disable(NRF_SAADC, NRF_SAADC_INT_STOPPED);
208     nrfy_saadc_stop(NRF_SAADC, true);
209 #endif
210 
211     m_cb.limits_low_activated  = 0;
212     m_cb.limits_high_activated = 0;
213 
214     m_cb.buffer_primary.p_buffer   = NULL;
215     m_cb.buffer_secondary.p_buffer = NULL;
216     m_cb.event_handler             = event_handler;
217     m_cb.channels_activated        = (uint8_t)ch_to_activate_mask;
218     m_cb.samples_converted         = 0;
219 
220     nrfy_saadc_config_t config = {.resolution = resolution, .oversampling = oversampling};
221     nrfy_saadc_periph_configure(NRF_SAADC, &config);
222     if (event_handler)
223     {
224         nrfy_saadc_int_set(NRF_SAADC,
225                            NRF_SAADC_INT_STARTED |
226                            NRF_SAADC_INT_STOPPED |
227                            NRF_SAADC_INT_END);
228     }
229     else
230     {
231         nrfy_saadc_int_set(NRF_SAADC, 0);
232     }
233 
234     for (uint32_t ch_pos = 0; ch_pos < SAADC_CH_NUM; ch_pos++)
235     {
236         nrf_saadc_burst_t burst_to_set = NRF_SAADC_BURST_DISABLED;
237         nrfy_saadc_channel_input_t input = {.input_p = NRF_SAADC_INPUT_DISABLED,
238                                             .input_n = NRF_SAADC_INPUT_DISABLED};
239         if (ch_to_activate_mask & (1 << ch_pos))
240         {
241             input = m_cb.channels_input[ch_pos];
242             burst_to_set = burst;
243         }
244         nrfy_saadc_burst_set(NRF_SAADC, (uint8_t)ch_pos, burst_to_set);
245         nrfy_saadc_channel_configure(NRF_SAADC, (uint8_t)ch_pos, NULL, &input);
246     }
247 }
248 
nrfx_saadc_init(uint8_t interrupt_priority)249 nrfx_err_t nrfx_saadc_init(uint8_t interrupt_priority)
250 {
251     nrfx_err_t err_code;
252     if (m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED)
253     {
254 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
255         err_code = NRFX_ERROR_ALREADY;
256 #else
257         err_code = NRFX_ERROR_INVALID_STATE;
258 #endif
259         NRFX_LOG_WARNING("Function: %s, error code: %s.",
260                          __func__,
261                          NRFX_LOG_ERROR_STRING_GET(err_code));
262         return err_code;
263     }
264     m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
265 
266     saadc_channels_deconfig(SAADC_ALL_CHANNELS_MASK);
267     uint32_t mask = NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_STARTED) |
268                     NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_STOPPED) |
269                     NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_END) |
270                     NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_CALIBRATEDONE);
271 
272     nrfy_saadc_int_init(NRF_SAADC, mask, interrupt_priority, false);
273     m_cb.event_handler = NULL;
274 
275     err_code = NRFX_SUCCESS;
276     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
277 
278     return err_code;
279 }
280 
nrfx_saadc_uninit(void)281 void nrfx_saadc_uninit(void)
282 {
283     nrfx_saadc_abort();
284 
285     nrfy_saadc_int_uninit(NRF_SAADC);
286     nrfy_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_DONE);
287     nrfy_saadc_disable(NRF_SAADC);
288     saadc_channels_disable(m_cb.channels_configured | m_cb.channels_activated);
289     m_cb.saadc_state = NRF_SAADC_STATE_UNINITIALIZED;
290 }
291 
nrfx_saadc_init_check(void)292 bool nrfx_saadc_init_check(void)
293 {
294     return (m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
295 }
296 
nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,uint32_t channel_count)297 nrfx_err_t nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,
298                                       uint32_t                     channel_count)
299 {
300     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
301     NRFX_ASSERT(p_channels);
302     NRFX_ASSERT(channel_count <= SAADC_CH_NUM);
303 
304     if (saadc_busy_check())
305     {
306         return NRFX_ERROR_BUSY;
307     }
308 
309     saadc_channels_deconfig(SAADC_ALL_CHANNELS_MASK);
310     for (uint8_t i = 0; i < channel_count; i++)
311     {
312         if (m_cb.channels_configured & (1 << p_channels[i].channel_index))
313         {
314             // This channel is already configured!
315             return NRFX_ERROR_INVALID_PARAM;
316         }
317 
318         saadc_channel_config(&p_channels[i]);
319     }
320 
321     return NRFX_SUCCESS;
322 }
323 
nrfx_saadc_channel_config(nrfx_saadc_channel_t const * p_channel)324 nrfx_err_t nrfx_saadc_channel_config(nrfx_saadc_channel_t const * p_channel)
325 {
326     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
327     NRFX_ASSERT(p_channel);
328 
329     if (saadc_busy_check())
330     {
331         return NRFX_ERROR_BUSY;
332     }
333 
334     saadc_channel_config(p_channel);
335 
336     return NRFX_SUCCESS;
337 }
338 
nrfx_saadc_channels_configured_get(void)339 uint32_t nrfx_saadc_channels_configured_get(void)
340 {
341     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
342 
343     return m_cb.channels_configured;
344 }
345 
nrfx_saadc_channels_deconfig(uint32_t channel_mask)346 nrfx_err_t nrfx_saadc_channels_deconfig(uint32_t channel_mask)
347 {
348     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
349 
350     if (saadc_busy_check())
351     {
352         return NRFX_ERROR_BUSY;
353     }
354 
355     saadc_channels_deconfig(channel_mask);
356 
357     return NRFX_SUCCESS;
358 }
359 
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)360 nrfx_err_t nrfx_saadc_simple_mode_set(uint32_t                   channel_mask,
361                                       nrf_saadc_resolution_t     resolution,
362                                       nrf_saadc_oversample_t     oversampling,
363                                       nrfx_saadc_event_handler_t event_handler)
364 {
365     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
366 
367     if (saadc_busy_check())
368     {
369         return NRFX_ERROR_BUSY;
370     }
371 
372     uint8_t active_ch_count;
373     nrfx_err_t err = saadc_channel_count_get(channel_mask, &active_ch_count);
374     if (err != NRFX_SUCCESS)
375     {
376         return err;
377     }
378 
379     nrf_saadc_burst_t burst;
380     if (oversampling == NRF_SAADC_OVERSAMPLE_DISABLED)
381     {
382         burst = NRF_SAADC_BURST_DISABLED;
383     }
384     else
385     {
386         // Burst is implicitly enabled if oversampling is enabled.
387         burst = NRF_SAADC_BURST_ENABLED;
388     }
389 
390     saadc_generic_mode_set(channel_mask,
391                            resolution,
392                            oversampling,
393                            burst,
394                            event_handler);
395 
396     m_cb.channels_activated_count = active_ch_count;
397     m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE;
398 
399     return NRFX_SUCCESS;
400 }
401 
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)402 nrfx_err_t nrfx_saadc_advanced_mode_set(uint32_t                        channel_mask,
403                                         nrf_saadc_resolution_t          resolution,
404                                         nrfx_saadc_adv_config_t const * p_config,
405                                         nrfx_saadc_event_handler_t      event_handler)
406 {
407     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
408     NRFX_ASSERT(p_config);
409 
410     if (saadc_busy_check())
411     {
412         return NRFX_ERROR_BUSY;
413     }
414 
415     uint8_t active_ch_count;
416     nrfx_err_t err = saadc_channel_count_get(channel_mask, &active_ch_count);
417     if (err != NRFX_SUCCESS)
418     {
419         return err;
420     }
421 
422     if ((p_config->internal_timer_cc) && ((active_ch_count > 1) || (!event_handler)))
423     {
424         return NRFX_ERROR_NOT_SUPPORTED;
425     }
426 
427     bool oversampling_without_burst = false;
428     if ((p_config->oversampling != NRF_SAADC_OVERSAMPLE_DISABLED) &&
429         (p_config->burst == NRF_SAADC_BURST_DISABLED))
430     {
431         if (active_ch_count > 1)
432         {
433             // Oversampling without burst is possible only on single channel.
434             return NRFX_ERROR_NOT_SUPPORTED;
435         }
436         else
437         {
438             oversampling_without_burst = true;
439         }
440     }
441 
442     saadc_generic_mode_set(channel_mask,
443                            resolution,
444                            p_config->oversampling,
445                            p_config->burst,
446                            event_handler);
447 
448     if (p_config->internal_timer_cc)
449     {
450         nrfy_saadc_continuous_mode_enable(NRF_SAADC, p_config->internal_timer_cc);
451     }
452     else
453     {
454         nrfy_saadc_continuous_mode_disable(NRF_SAADC);
455     }
456 
457     m_cb.channels_activated_count = active_ch_count;
458     m_cb.start_on_end = p_config->start_on_end;
459     m_cb.oversampling_without_burst = oversampling_without_burst;
460 
461     m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE;
462 
463     return NRFX_SUCCESS;
464 }
465 
nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer,uint16_t size)466 nrfx_err_t nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer, uint16_t size)
467 {
468     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
469 
470     if (m_cb.buffer_secondary.p_buffer)
471     {
472         return NRFX_ERROR_ALREADY;
473     }
474 
475     if (!nrfx_is_in_ram(p_buffer))
476     {
477         return NRFX_ERROR_INVALID_ADDR;
478     }
479 
480     if ((size % m_cb.channels_activated_count != 0) ||
481         (size > SAADC_RESULT_MAXCNT_MAXCNT_Msk)  ||
482         (!size))
483     {
484         return NRFX_ERROR_INVALID_LENGTH;
485     }
486 
487     nrfy_saadc_buffer_t buffer = {.p_buffer = p_buffer, .length = size};
488     switch (m_cb.saadc_state)
489     {
490         case NRF_SAADC_STATE_SIMPLE_MODE:
491             if (m_cb.channels_activated_count != size)
492             {
493                 return NRFX_ERROR_INVALID_LENGTH;
494             }
495             m_cb.buffer_primary = buffer;
496             break;
497 
498         case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
499             nrfy_saadc_buffer_set(NRF_SAADC, &buffer, false, false);
500             /* FALLTHROUGH */
501 
502         case NRF_SAADC_STATE_ADV_MODE:
503             /* FALLTHROUGH */
504 
505         case NRF_SAADC_STATE_ADV_MODE_SAMPLE:
506             if (m_cb.buffer_primary.p_buffer)
507             {
508                 m_cb.buffer_secondary = buffer;
509             }
510             else
511             {
512                 m_cb.buffer_primary = buffer;
513             }
514             break;
515 
516         default:
517             return NRFX_ERROR_INVALID_STATE;
518     }
519 
520     return NRFX_SUCCESS;
521 }
522 
nrfx_saadc_mode_trigger(void)523 nrfx_err_t nrfx_saadc_mode_trigger(void)
524 {
525     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
526     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_IDLE);
527 
528     if (!m_cb.buffer_primary.p_buffer)
529     {
530         return NRFX_ERROR_NO_MEM;
531     }
532 
533     nrfx_err_t result = NRFX_SUCCESS;
534     switch (m_cb.saadc_state)
535     {
536         case NRF_SAADC_STATE_SIMPLE_MODE:
537         {
538             nrfy_saadc_enable(NRF_SAADC);
539             // When in simple blocking or non-blocking mode, buffer size is equal to activated channel count.
540             // Single SAMPLE task is enough to obtain one sample on each activated channel.
541             // This will result in buffer being filled with samples and therefore END event will appear.
542 
543             if (m_cb.event_handler)
544             {
545                 m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE;
546                 nrfy_saadc_buffer_set(NRF_SAADC, &m_cb.buffer_primary, true, false);
547             }
548             else
549             {
550                 nrfy_saadc_buffer_set(NRF_SAADC, &m_cb.buffer_primary, true, true);
551                 nrfy_saadc_sample_start(NRF_SAADC, &m_cb.buffer_primary);
552                 nrfy_saadc_disable(NRF_SAADC);
553             }
554             break;
555         }
556 
557         case NRF_SAADC_STATE_ADV_MODE:
558         {
559             nrfy_saadc_enable(NRF_SAADC);
560             if (m_cb.event_handler)
561             {
562                 // When in advanced non-blocking mode, latch whole buffer in EasyDMA.
563                 // END event will arrive when whole buffer is filled with samples.
564 
565                 m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE_SAMPLE;
566                 nrfy_saadc_buffer_set(NRF_SAADC, &m_cb.buffer_primary, true, false);
567                 break;
568             }
569             // When in advanced blocking mode, latch single chunk of buffer in EasyDMA.
570             // Each chunk consists of single sample from each activated channels.
571             // END event will arrive when single chunk is filled with samples.
572             nrfy_saadc_buffer_t chunk = { .length = m_cb.channels_activated_count};
573 
574 #if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8)
575             if (nrfy_saadc_resolution_get(NRF_SAADC) == NRF_SAADC_RESOLUTION_8BIT)
576             {
577                 chunk.p_buffer = (nrf_saadc_value_t *)
578                     &((uint8_t *)m_cb.buffer_primary.p_buffer)[m_cb.samples_converted];
579             }
580             else
581 #endif
582             {
583                 chunk.p_buffer = (nrf_saadc_value_t *)
584                     &((uint16_t *)m_cb.buffer_primary.p_buffer)[m_cb.samples_converted];
585             }
586             nrfy_saadc_buffer_set(NRF_SAADC, &chunk, true, true);
587             if (m_cb.oversampling_without_burst)
588             {
589                 // Oversampling without burst is possible only on single channel.
590                 // In this configuration more than one SAMPLE task is needed to obtain single sample.
591                 uint32_t samples_to_take =
592                     nrfy_saadc_oversample_sample_count_get(nrfy_saadc_oversample_get(NRF_SAADC));
593 
594                 for (uint32_t sample_idx = 0; sample_idx < samples_to_take - 1; sample_idx++)
595                 {
596                     nrfy_saadc_sample_start(NRF_SAADC, NULL);
597                     uint32_t evt_mask = NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_DONE);
598                     while (!nrfy_saadc_events_process(NRF_SAADC, evt_mask, NULL))
599                     {}
600                 }
601             }
602             // Single SAMPLE task is enough to obtain one sample on each activated channel.
603             // This will result in chunk being filled with samples and therefore END event will appear.
604             nrfy_saadc_sample_start(NRF_SAADC, &chunk);
605 
606             m_cb.samples_converted += m_cb.channels_activated_count;
607             if (m_cb.samples_converted < m_cb.buffer_primary.length)
608             {
609                 result = NRFX_ERROR_BUSY;
610             }
611             else
612             {
613                 m_cb.samples_converted         = 0;
614                 m_cb.buffer_primary            = m_cb.buffer_secondary;
615                 m_cb.buffer_secondary.p_buffer = NULL;
616             }
617             nrfy_saadc_disable(NRF_SAADC);
618             break;
619         }
620 
621         default:
622             result = NRFX_ERROR_INVALID_STATE;
623             break;
624     }
625 
626     return result;
627 }
628 
nrfx_saadc_abort(void)629 void nrfx_saadc_abort(void)
630 {
631     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
632 
633     if (m_cb.saadc_state == NRF_SAADC_STATE_CALIBRATION ? m_cb.calib_event_handler :
634                                                           m_cb.event_handler)
635     {
636         nrfy_saadc_abort(NRF_SAADC, NULL);
637     }
638     else
639     {
640         m_cb.buffer_primary.p_buffer   = NULL;
641         m_cb.buffer_secondary.p_buffer = NULL;
642         m_cb.samples_converted         = 0;
643     }
644 }
645 
nrfx_saadc_limits_set(uint8_t channel,int16_t limit_low,int16_t limit_high)646 nrfx_err_t nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
647 {
648     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
649     NRFX_ASSERT(limit_high >= limit_low);
650 
651     if (!m_cb.event_handler)
652     {
653         return NRFX_ERROR_FORBIDDEN;
654     }
655 
656     if ((m_cb.saadc_state == NRF_SAADC_STATE_IDLE) ||
657         (m_cb.saadc_state == NRF_SAADC_STATE_CALIBRATION))
658     {
659         return NRFX_ERROR_INVALID_STATE;
660     }
661 
662     if (!(m_cb.channels_activated & (1 << channel)))
663     {
664         return NRFX_ERROR_INVALID_PARAM;
665     }
666 
667     nrfy_saadc_channel_limits_set(NRF_SAADC, channel, limit_low, limit_high);
668 
669     uint32_t int_mask = nrfy_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
670     if (limit_low == INT16_MIN)
671     {
672         m_cb.limits_low_activated &= (uint8_t)~(1UL << channel);
673         nrfy_saadc_int_disable(NRF_SAADC, int_mask);
674     }
675     else
676     {
677         m_cb.limits_low_activated |= (uint8_t)(1UL << channel);
678         nrfy_saadc_int_enable(NRF_SAADC, int_mask);
679     }
680 
681     int_mask = nrfy_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
682     if (limit_high == INT16_MAX)
683     {
684         m_cb.limits_high_activated &= (uint8_t)~(1UL << channel);
685         nrfy_saadc_int_disable(NRF_SAADC, int_mask);
686     }
687     else
688     {
689         m_cb.limits_high_activated |= (uint8_t)(1UL << channel);
690         nrfy_saadc_int_enable(NRF_SAADC, int_mask);
691     }
692 
693     return NRFX_SUCCESS;
694 }
695 
nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t calib_event_handler)696 nrfx_err_t nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t calib_event_handler)
697 {
698     NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
699 
700     if (saadc_busy_check())
701     {
702         return NRFX_ERROR_BUSY;
703     }
704 
705     m_cb.saadc_state_prev = m_cb.saadc_state;
706     m_cb.saadc_state = NRF_SAADC_STATE_CALIBRATION;
707     m_cb.calib_event_handler = calib_event_handler;
708 
709     nrfy_saadc_enable(NRF_SAADC);
710 
711     uint32_t int_mask = nrfy_saadc_int_enable_check(NRF_SAADC, ~0UL);
712     nrfy_saadc_int_set(NRF_SAADC, 0);
713     if (calib_event_handler)
714     {
715         nrfy_saadc_calibrate(NRF_SAADC, false);
716         // Make sure that LIMIT feature is disabled before offset calibration.
717         int_mask &= ~(uint32_t)(NRF_SAADC_INT_CH0LIMITL | NRF_SAADC_INT_CH0LIMITH);
718         nrfy_saadc_int_set(NRF_SAADC, int_mask | NRF_SAADC_INT_STARTED | NRF_SAADC_INT_STOPPED |
719                                       NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
720     }
721     else
722     {
723         nrfy_saadc_calibrate(NRF_SAADC, true);
724 
725         nrfy_saadc_buffer_t calib_buffer = {.p_buffer = m_cb.calib_samples,
726                                             .length   = NRFX_ARRAY_SIZE(m_cb.calib_samples)};
727         nrfy_saadc_buffer_set(NRF_SAADC, &calib_buffer, true, true);
728 
729         nrfy_saadc_stop(NRF_SAADC, true);
730         nrfy_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
731         nrfy_saadc_disable(NRF_SAADC);
732         m_cb.saadc_state = m_cb.saadc_state_prev;
733 
734         nrfy_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CH0_LIMITL);
735         nrfy_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CH0_LIMITH);
736         nrfy_saadc_int_set(NRF_SAADC, int_mask);
737     }
738 
739     return NRFX_SUCCESS;
740 }
741 
saadc_pre_calibration_state_restore(void)742 static void saadc_pre_calibration_state_restore(void)
743 {
744     nrfy_saadc_disable(NRF_SAADC);
745     uint32_t int_mask = nrfy_saadc_int_enable_check(NRF_SAADC, ~0UL) &
746                         (uint32_t)(~(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_STOPPED |
747                                      NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE));
748     m_cb.saadc_state = m_cb.saadc_state_prev;
749     if (m_cb.event_handler)
750     {
751         // Restore interrupts that are used in sampling if user provided event handler
752         // during mode configuration.
753         int_mask |= NRF_SAADC_INT_STARTED | NRF_SAADC_INT_STOPPED | NRF_SAADC_INT_END;
754     }
755     nrfy_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CH0_LIMITL);
756     nrfy_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CH0_LIMITH);
757     if (m_cb.limits_low_activated & 0x1UL)
758     {
759         int_mask |= NRF_SAADC_INT_CH0LIMITL;
760     }
761     if (m_cb.limits_high_activated & 0x1UL)
762     {
763         int_mask |= NRF_SAADC_INT_CH0LIMITH;
764     }
765     nrfy_saadc_int_set(NRF_SAADC, int_mask);
766 }
767 
saadc_event_started_handle(void)768 static void saadc_event_started_handle(void)
769 {
770     nrfx_saadc_evt_t evt_data;
771 
772     switch (m_cb.saadc_state)
773     {
774         case NRF_SAADC_STATE_ADV_MODE_SAMPLE:
775             evt_data.type = NRFX_SAADC_EVT_READY;
776             m_cb.event_handler(&evt_data);
777 
778             if (nrfy_saadc_continuous_mode_enable_check(NRF_SAADC))
779             {
780                 // Trigger internal timer
781                 nrfy_saadc_sample_start(NRF_SAADC, NULL);
782             }
783 
784             m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED;
785             if (m_cb.buffer_secondary.p_buffer)
786             {
787                 nrfy_saadc_buffer_set(NRF_SAADC, &m_cb.buffer_secondary, false, false);
788             }
789             /* FALLTHROUGH */
790 
791         case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
792             if (!m_cb.buffer_secondary.p_buffer)
793             {
794                 // Send next buffer request only if it was not provided earlier,
795                 // before conversion start or outside of user's callback context.
796                 evt_data.type = NRFX_SAADC_EVT_BUF_REQ;
797                 m_cb.event_handler(&evt_data);
798             }
799             break;
800 
801         case NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE:
802             nrfy_saadc_sample_start(NRF_SAADC, NULL);
803             break;
804 
805         case NRF_SAADC_STATE_CALIBRATION:
806             // Stop the SAADC immediately after the temporary buffer is latched to drop spurious samples.
807             // This will cause STOPPED and END events to arrive.
808             nrfy_saadc_stop(NRF_SAADC, false);
809             break;
810 
811         default:
812             break;
813     }
814 }
815 
saadc_event_end_handle(void)816 static void saadc_event_end_handle(void)
817 {
818     nrfx_saadc_evt_t evt_data;
819     evt_data.type = NRFX_SAADC_EVT_DONE;
820     evt_data.data.done.p_buffer = m_cb.buffer_primary.p_buffer;
821     evt_data.data.done.size = (uint16_t)m_cb.buffer_primary.length;
822 
823     switch (m_cb.saadc_state)
824     {
825         case NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE:
826             nrfy_saadc_disable(NRF_SAADC);
827             m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE;
828             /* In the simple, non-blocking mode the event handler must be
829              * called after the internal driver state is updated. This will
830              * allow starting a new conversion from the event handler context.
831              */
832             m_cb.event_handler(&evt_data);
833             break;
834 
835         case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
836             if (m_cb.start_on_end && m_cb.buffer_secondary.p_buffer)
837             {
838                 nrfy_saadc_buffer_latch(NRF_SAADC, false);
839             }
840             m_cb.event_handler(&evt_data);
841             m_cb.buffer_primary = m_cb.buffer_secondary;
842             m_cb.buffer_secondary.p_buffer = NULL;
843             if (!m_cb.buffer_primary.p_buffer)
844             {
845                 nrfy_saadc_disable(NRF_SAADC);
846                 m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE;
847                 evt_data.type = NRFX_SAADC_EVT_FINISHED;
848                 m_cb.event_handler(&evt_data);
849             }
850             break;
851 
852         case NRF_SAADC_STATE_CALIBRATION:
853             // Spurious samples were successfully dropped and they won't affect next conversion.
854             saadc_pre_calibration_state_restore();
855             evt_data.type = NRFX_SAADC_EVT_CALIBRATEDONE;
856             m_cb.calib_event_handler(&evt_data);
857             break;
858 
859         default:
860             break;
861     }
862 }
863 
saadc_event_limits_handle(void)864 static void saadc_event_limits_handle(void)
865 {
866     uint32_t limits_activated = nrfy_saadc_int_enable_check(NRF_SAADC,
867                                                             NRF_SAADC_ALL_CHANNELS_LIMITS_INT_MASK);
868     uint32_t limits_triggered = nrfy_saadc_events_process(NRF_SAADC, limits_activated, NULL) >>
869                                 NRF_SAADC_LIMITS_INT_OFFSET;
870 
871     while (limits_triggered)
872     {
873         uint8_t limit = (uint8_t)NRF_CTZ((uint32_t)limits_triggered);
874         limits_triggered &= ~(1UL << limit);
875 
876          // There are two limits per channel.
877         uint8_t channel = limit / 2;
878 
879         // Limits are organised into single pair (high limit and low limit) per channel.
880         // Do not assume whether high limit or low limit is first in the bitmask.
881         nrf_saadc_limit_t limit_type =
882             ((limit & 0x1) == (NRFY_EVENT_TO_INT_BITPOS(NRF_SAADC_EVENT_CH0_LIMITH) & 0x1)) ?
883             NRF_SAADC_LIMIT_HIGH : NRF_SAADC_LIMIT_LOW;
884 
885         nrfx_saadc_evt_t evt_data;
886         evt_data.type = NRFX_SAADC_EVT_LIMIT;
887         evt_data.data.limit.channel = channel;
888         evt_data.data.limit.limit_type = limit_type;
889         m_cb.event_handler(&evt_data);
890     }
891 }
892 
nrfx_saadc_irq_handler(void)893 void nrfx_saadc_irq_handler(void)
894 {
895     uint32_t evt_mask = NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_STARTED) |
896                         NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_STOPPED) |
897                         NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_END) |
898                         NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_CALIBRATEDONE);
899     evt_mask = nrfy_saadc_events_process(NRF_SAADC, evt_mask, &m_cb.buffer_primary);
900 
901     if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_CALIBRATEDONE))
902     {
903         nrfy_saadc_int_disable(NRF_SAADC, NRF_SAADC_INT_CALIBRATEDONE);
904         // Latch the temporary buffer to intercept any spurious samples that may appear after calibration.
905         nrfy_saadc_buffer_t calib_buffer = {.p_buffer = m_cb.calib_samples,
906                                             .length  = NRFX_ARRAY_SIZE(m_cb.calib_samples)};
907         nrfy_saadc_buffer_set(NRF_SAADC, &calib_buffer, true, false);
908     }
909 
910     if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_STOPPED))
911     {
912         if (m_cb.saadc_state != NRF_SAADC_STATE_CALIBRATION)
913         {
914             // If there was ongoing conversion the STOP task also triggers the END event
915             m_cb.buffer_primary.length = nrfy_saadc_amount_get(NRF_SAADC);
916             m_cb.buffer_secondary.p_buffer = NULL;
917         }
918 
919         if (nrfy_saadc_int_enable_check(NRF_SAADC, NRF_SAADC_INT_CALIBRATEDONE))
920         {
921             // If STOP event arrived before CALIBRATEDONE then the calibration was aborted
922             // and END event will not appear.
923             // Calibration procedure was not completed and user handler will not be called.
924             saadc_pre_calibration_state_restore();
925         }
926         /* fall-through to the END event handler */
927     }
928 
929     if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_END))
930     {
931         saadc_event_end_handle();
932     }
933 
934     if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_SAADC_EVENT_STARTED))
935     {
936         saadc_event_started_handle();
937     }
938 
939     if (m_cb.saadc_state != NRF_SAADC_STATE_CALIBRATION)
940     {
941         saadc_event_limits_handle();
942     }
943 }
944 
945 #endif // NRFX_CHECK(NRFX_SAADC_ENABLED)
946