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