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 
34 #ifndef NRFX_SAADC_H__
35 #define NRFX_SAADC_H__
36 
37 #include <nrfx.h>
38 #include <haly/nrfy_saadc.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * @defgroup nrfx_saadc SAADC driver
46  * @{
47  * @ingroup nrf_saadc
48  * @brief   Successive Approximation Analog-to-Digital Converter (SAADC) peripheral driver.
49  */
50 
51 #if NRF_SAADC_HAS_ACQTIME_ENUM || defined(__NRFX_DOXYGEN__)
52 /** @brief Auxiliary symbol specifying default value for the SAADC acquisition time. */
53 #define NRFX_SAADC_DEFAULT_ACQTIME NRF_SAADC_ACQTIME_10US
54 #else
55 #define NRFX_SAADC_DEFAULT_ACQTIME 79
56 #endif
57 
58 #if NRF_SAADC_HAS_CONV_TIME || defined(__NRFX_DOXYGEN__)
59 /** @brief Auxiliary symbol specifying default value for the SAADC conversion time. */
60 #define NRFX_SAADC_DEFAULT_CONV_TIME 7
61 #endif
62 
63 /**
64  * @brief SAADC channel default configuration for the single-ended mode.
65  *
66  * This configuration sets up single-ended SAADC channel with the following options:
67  * - resistor ladder disabled
68  * - gain: 1
69  * - reference voltage: internal
70  * - sample acquisition time: 10 us
71  * - burst disabled
72  *
73  * @param[in] _pin_p Positive input analog pin.
74  * @param[in] _index Channel index.
75  *
76  * @sa nrfx_saadc_channel_t
77  */
78 #define NRFX_SAADC_DEFAULT_CHANNEL_SE(_pin_p, _index)                  \
79 {                                                                      \
80     .channel_config =                                                  \
81     {                                                                  \
82         NRFX_COND_CODE_1(NRF_SAADC_HAS_CH_CONFIG_RES,                  \
83                          (.resistor_p = NRF_SAADC_RESISTOR_DISABLED,   \
84                           .resistor_n = NRF_SAADC_RESISTOR_DISABLED,), \
85                          ())                                           \
86         .gain       = NRF_SAADC_GAIN1,                                 \
87         .reference  = NRF_SAADC_REFERENCE_INTERNAL,                    \
88         .acq_time   = NRFX_SAADC_DEFAULT_ACQTIME,                      \
89         NRFX_COND_CODE_1(NRF_SAADC_HAS_CONV_TIME,                      \
90                          (.conv_time = NRFX_SAADC_DEFAULT_CONV_TIME,), \
91                          ())                                           \
92         .mode       = NRF_SAADC_MODE_SINGLE_ENDED,                     \
93         .burst      = NRF_SAADC_BURST_DISABLED,                        \
94     },                                                                 \
95     .pin_p          = (nrf_saadc_input_t)_pin_p,                       \
96     .pin_n          = NRF_SAADC_INPUT_DISABLED,                        \
97     .channel_index  = _index,                                          \
98 }
99 
100 /**
101  * @brief SAADC channel default configuration for the differential mode.
102  *
103  * This configuration sets up differential SAADC channel with the following options:
104  * - resistor ladder disabled
105  * - gain: 1/6
106  * - reference voltage: internal
107  * - sample acquisition time: 10 us
108  * - burst disabled
109  *
110  * @param[in] _pin_p Positive input analog pin.
111  * @param[in] _pin_n Negative input analog pin.
112  * @param[in] _index Channel index.
113  *
114  * @sa nrfx_saadc_channel_t
115  */
116 #define NRFX_SAADC_DEFAULT_CHANNEL_DIFFERENTIAL(_pin_p, _pin_n, _index) \
117 {                                                                       \
118     .channel_config =                                                   \
119     {                                                                   \
120         NRFX_COND_CODE_1(NRF_SAADC_HAS_CH_CONFIG_RES,                   \
121                          (.resistor_p = NRF_SAADC_RESISTOR_DISABLED,    \
122                           .resistor_n = NRF_SAADC_RESISTOR_DISABLED,),  \
123                          ())                                            \
124         .gain       = NRF_SAADC_GAIN1,                                  \
125         .reference  = NRF_SAADC_REFERENCE_INTERNAL,                     \
126         .acq_time   = NRFX_SAADC_DEFAULT_ACQTIME,                       \
127         NRFX_COND_CODE_1(NRF_SAADC_HAS_CONV_TIME,                       \
128                          (.conv_time = NRFX_SAADC_DEFAULT_CONV_TIME,),  \
129                          ())                                            \
130         .mode       = NRF_SAADC_MODE_DIFFERENTIAL,                      \
131         .burst      = NRF_SAADC_BURST_DISABLED,                         \
132     },                                                                  \
133     .pin_p          = (nrf_saadc_input_t)_pin_p,                        \
134     .pin_n          = (nrf_saadc_input_t)_pin_n,                        \
135     .channel_index  = _index,                                           \
136 }
137 
138 /**
139  * @brief SAADC driver advanced mode default configuration.
140  *
141  * This configuration sets up advanced mode of the SAADC driver with the following options:
142  * - oversampling disabled
143  * - burst disabled
144  * - internal sampling timer disabled
145  * - triggering of the START task on the END event disabled
146  *
147  * @param[in] _pin_p Positive input analog pin.
148  * @param[in] _pin_n Negative input analog pin.
149  * @param[in] _index Channel index.
150  *
151  * @sa nrfx_saadc_adv_config_t
152  */
153 #define NRFX_SAADC_DEFAULT_ADV_CONFIG                                           \
154 {                                                                               \
155     .oversampling      = NRF_SAADC_OVERSAMPLE_DISABLED,                         \
156     .burst             = NRF_SAADC_BURST_DISABLED,                              \
157     .internal_timer_cc = 0,                                                     \
158     .start_on_end      = false,                                                 \
159 }
160 
161 /** @brief SAADC channel configuration structure. */
162 typedef struct
163 {
164     nrf_saadc_channel_config_t channel_config; ///< Channel hardware configuration.
165     nrf_saadc_input_t          pin_p;          ///< Input positive pin selection.
166     nrf_saadc_input_t          pin_n;          ///< Input negative pin selection.
167     uint8_t                    channel_index;  ///< Channel index.
168 } nrfx_saadc_channel_t;
169 
170 /** @brief SAADC driver advanced mode configuration structure. */
171 typedef struct
172 {
173     nrf_saadc_oversample_t oversampling;      ///< Oversampling configuration.
174     nrf_saadc_burst_t      burst;             ///< Burst configuration.
175     uint16_t               internal_timer_cc; ///< Internal timer capture and compare value.
176     bool                   start_on_end;      ///< Flag indicating if the START task is to be triggered on the END event.
177 } nrfx_saadc_adv_config_t;
178 
179 /** @brief SAADC driver event types. */
180 typedef enum
181 {
182     NRFX_SAADC_EVT_DONE,          ///< Event generated when the buffer is filled with samples.
183     NRFX_SAADC_EVT_LIMIT,         ///< Event generated when one of the limits is reached.
184     NRFX_SAADC_EVT_CALIBRATEDONE, ///< Event generated when the calibration is complete.
185     NRFX_SAADC_EVT_BUF_REQ,       ///< Event generated when the next buffer for continuous conversion is requested.
186     NRFX_SAADC_EVT_READY,         ///< Event generated when the first buffer is acquired by the peripheral and sampling can be started.
187     NRFX_SAADC_EVT_FINISHED,      ///< Event generated when all supplied buffers are filled with results.
188 } nrfx_saadc_evt_type_t;
189 
190 /** @brief SAADC driver done event data. */
191 typedef struct
192 {
193     nrf_saadc_value_t * p_buffer; ///< Pointer to the buffer with converted samples.
194     uint16_t            size;     ///< Number of samples in the buffer.
195 } nrfx_saadc_done_evt_t;
196 
197 /** @brief SAADC driver limit event data. */
198 typedef struct
199 {
200     uint8_t           channel;    ///< Channel on which the limit was detected.
201     nrf_saadc_limit_t limit_type; ///< Type of limit detected.
202 } nrfx_saadc_limit_evt_t;
203 
204 /** @brief SAADC driver event structure. */
205 typedef struct
206 {
207     nrfx_saadc_evt_type_t type; ///< Event type.
208     union
209     {
210         nrfx_saadc_done_evt_t  done;  ///< Data for @ref NRFX_SAADC_EVT_DONE event.
211         nrfx_saadc_limit_evt_t limit; ///< Data for @ref NRFX_SAADC_EVT_LIMIT event.
212     } data;                           ///< Union to store event data.
213 } nrfx_saadc_evt_t;
214 
215 /**
216  * @brief SAADC driver event handler.
217  *
218  * When operating in the advanced mode:
219  * - when the sampling is performed by the external timer, the external timer can be safely started
220  *   on @ref NRFX_SAADC_EVT_READY and stopped on @ref NRFX_SAADC_EVT_FINISHED.
221  * - call the @ref nrfx_saadc_buffer_set() on @ref NRFX_SAADC_EVT_BUF_REQ to achieve the continuous conversion.
222  *
223  * @param[in] p_event Pointer to an SAADC driver event. The event structure is allocated on
224  *                    the stack, so it is valid only within the context of the event handler.
225  */
226 typedef void (* nrfx_saadc_event_handler_t)(nrfx_saadc_evt_t const * p_event);
227 
228 /**
229  * @brief Function for initializing the SAADC driver.
230  *
231  * @param[in] interrupt_priority Interrupt priority.
232  *
233  * @retval NRFX_SUCCESS             Initialization was successful.
234  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
235  */
236 nrfx_err_t nrfx_saadc_init(uint8_t interrupt_priority);
237 
238 /**
239  * @brief Function for uninitializing the SAADC driver.
240  *
241  * This function stops all ongoing conversions and disables all channels.
242  */
243 void nrfx_saadc_uninit(void);
244 
245 /**
246  * @brief Function for configuring multiple SAADC channels.
247  *
248  * @note The values of the @ref nrf_saadc_channel_config_t.burst fields in channel configurations
249  *       are ignored. They will be overridden with the value suitable for the selected driver
250  *       operation mode.
251  * @note The desired mode (simple or advanced) must be set after the channels are configured.
252  *
253  * @warning This function overrides previous configuration done on any channel by
254  *          @ref nrfx_saadc_channels_config or @ref nrfx_saadc_channel_config.
255  *
256  * @param[in] p_channels    Pointer to the array of channel configuration structures.
257  * @param[in] channel_count Number of channels to be configured.
258  *
259  * @retval NRFX_SUCCESS             Configuration was successful.
260  * @retval NRFX_ERROR_BUSY          There is a conversion or calibration ongoing.
261  * @retval NRFX_ERROR_INVALID_PARAM Attempt to configure the same channel more than once.
262  */
263 nrfx_err_t nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,
264                                       uint32_t                     channel_count);
265 
266 /**
267  * @brief Function for configuring single SAADC channel.
268  *
269  * @note The values of the @ref nrf_saadc_channel_config_t.burst fields in channel configurations
270  *       are ignored. They will be overridden with the value suitable for the selected driver
271  *       operation mode.
272  *
273  * @warning This function overrides previous configuration done on specified channel by
274  *          @ref nrfx_saadc_channels_config or @ref nrfx_saadc_channel_config.
275  *
276  * @param[in] p_channel Pointer to the channel configuration structure.
277  *
278  * @retval NRFX_SUCCESS    Configuration was successful.
279  * @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
280  */
281 nrfx_err_t nrfx_saadc_channel_config(nrfx_saadc_channel_t const * p_channel);
282 
283 /**
284  * @brief Function for getting the currently configured SAADC channels.
285  *
286  * @return Bitmask of configured channels.
287  */
288 uint32_t nrfx_saadc_channels_configured_get(void);
289 
290 /**
291  * @brief Function for deconfiguring the specified SAADC channels.
292  *
293  * @warning Pins associated with the deconfigured channels will be released after
294  *          next @ref nrfx_saadc_simple_mode_set() or @ref nrfx_saadc_advanced_mode_set() call.
295  *
296  * @param[in] channel_mask Bitmask of channels to be deconfigured.
297  *
298  * @retval NRFX_SUCCESS    Deconfiguration was successful.
299  * @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
300  */
301 nrfx_err_t nrfx_saadc_channels_deconfig(uint32_t channel_mask);
302 
303 /**
304  * @brief Function for setting the SAADC driver in the simple mode.
305  *
306  * The simple mode allows obtaining a single sample from each requested channel.
307  * The conversion can be done in a blocking or non-blocking manner.
308  * Sampling is initiated by calling @ref nrfx_saadc_mode_trigger() once.
309  *
310  * @param[in] channel_mask  Bitmask of channels to be used in the simple mode.
311  * @param[in] resolution    Resolution configuration.
312  * @param[in] oversampling  Oversampling configuration.
313  * @param[in] event_handler Event handler provided by the user. In case of providing NULL,
314  *                          the conversion will be performed in the blocking manner.
315  *
316  * @retval NRFX_SUCCESS             Initialization was successful.
317  * @retval NRFX_ERROR_BUSY          There is a conversion or calibration ongoing.
318  * @retval NRFX_ERROR_INVALID_PARAM Attempt to activate channel that is not configured.
319  */
320 nrfx_err_t nrfx_saadc_simple_mode_set(uint32_t                   channel_mask,
321                                       nrf_saadc_resolution_t     resolution,
322                                       nrf_saadc_oversample_t     oversampling,
323                                       nrfx_saadc_event_handler_t event_handler);
324 
325 /**
326  * @brief Function for setting the SAADC driver in the advanced mode.
327  *
328  * The advanced mode allows performing double-buffered conversions of arbitrary length.
329  * The conversions can be done in a blocking or non-blocking manner. When performing conversions
330  * in the non-blocking manner and @ref nrfx_saadc_adv_config_t.internal_timer_cc is set to 0,
331  * sampling needs to be done by triggering @ref NRF_SAADC_TASK_SAMPLE externally
332  * (for example by using the TIMER and/or the PPI/DPPI).
333  * When performing conversions in the non-blocking manner and @ref nrfx_saadc_adv_config_t.start_on_end
334  * is false, the @ref NRF_SAADC_TASK_START needs to be triggered on @ref NRF_SAADC_EVENT_END
335  * externally (for example by using the PPI/DPPI).
336  * Sampling is initiated by calling @ref nrfx_saadc_mode_trigger(). In case of performing
337  * conversions in the blocking manner, @ref nrfx_saadc_mode_trigger() may need to be called several
338  * times as each call sample each requested channel once.
339  *
340  * @note The internal timer can only be used when a single input channel is enabled.
341  * @note The internal timer can only be used in the non-blocking mode.
342  *
343  * @param[in] channel_mask  Bitmask of channels to be used in the advanced mode.
344  * @param[in] resolution    Resolution configuration.
345  * @param[in] p_config      Pointer to the structure with the advanced mode configuration.
346  * @param[in] event_handler Event handler provided by the user. In case of providing NULL,
347  *                          the conversion will be performed in the blocking manner.
348  *
349  * @retval NRFX_SUCCESS             Initialization was successful.
350  * @retval NRFX_ERROR_BUSY          There is a conversion or calibration ongoing.
351  * @retval NRFX_ERROR_INVALID_PARAM Attempt to activate channel that is not configured.
352  * @retval NRFX_ERROR_NOT_SUPPORTED Attempt to activate either of the following:
353  *                                  * internal timer in the blocking mode,
354  *                                  * internal timer with multiple channels enabled,
355  *                                  * oversampling without burst with multiple channels enabled.
356  */
357 nrfx_err_t nrfx_saadc_advanced_mode_set(uint32_t                        channel_mask,
358                                         nrf_saadc_resolution_t          resolution,
359                                         nrfx_saadc_adv_config_t const * p_config,
360                                         nrfx_saadc_event_handler_t      event_handler);
361 
362 /**
363  * @brief Function for supplying the buffer to be used in the next part of
364  *        the conversion.
365  *
366  * @param[in] p_buffer Pointer to the buffer to be filled with conversion results.
367  * @param[in] size     Number of @ref nrf_saadc_value_t samples in buffer.
368  *
369  * @retval NRFX_SUCCESS                   Buffer was supplied successfully.
370  * @retval NRFX_ERROR_INVALID_ADDR        The provided buffer is not in the Data RAM region.
371  * @retval NRFX_ERROR_INVALID_LENGTH      The provided buffer is not aligned to the number of activated channels
372  *                                        or is too long for the EasyDMA to handle.
373  * @retval NRFX_ERROR_INVALID_STATE       The driver is in the idle mode.
374  * @retval NRFX_ERROR_ALREADY_INITIALIZED Both buffers for double-buffered conversions are already set.
375  */
376 nrfx_err_t nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer, uint16_t size);
377 
378 /**
379  * @brief Function for triggering the conversion in the configured mode.
380  *
381  * @retval NRFX_SUCCESS             Operation finished successfully in the blocking manner or started
382  *                                  successfully in the non-blocking manner.
383  * @retval NRFX_ERROR_BUSY          The driver is performing the conversion in the advanced blocking mode.
384  *                                  Call the function again to continue the conversion.
385  * @retval NRFX_ERROR_NO_MEM        There is no buffer provided.
386  *                                  Supply the buffer using @ref nrfx_saadc_buffer_set() and try again.
387  * @retval NRFX_ERROR_INVALID_STATE There is an ongoing conversion or calibration being performed
388  *                                  in the non-blocking manner or the driver is in the idle mode.
389  */
390 nrfx_err_t nrfx_saadc_mode_trigger(void);
391 
392 /**
393  * @brief Function for aborting the ongoing and buffered conversions.
394  *
395  * @warning Aborting blocking conversion or calibration from different context is not supported.
396  *          Perform the operation in non-blocking manner instead.
397  *
398  * @note @ref NRFX_SAADC_EVT_DONE event will be generated if there is a conversion in progress.
399  *       Event will contain number of words in the sample buffer.
400  */
401 void nrfx_saadc_abort(void);
402 
403 /**
404  * @brief Function for setting the SAADC channel limits.
405  *
406  * When limits are enabled and the conversion result exceeds the defined bounds,
407  * the handler function is called with the corresponding event as parameter.
408  *
409  * @note Before the limits are set, the driver operation mode (simple or advanced) has
410  *       to be configured. Only non-blocking conversions can be monitored.
411  *
412  * @note Changing of the driver operation mode disables all configured limits.
413  *
414  * @param[in] channel    Channel index.
415  * @param[in] limit_low  Limit low value to generate interrupt. Use @c INT16_MIN
416  *                       to disable interrupt generation.
417  * @param[in] limit_high Limit high value to generate interrupt. Use @c INT16_MAX
418  *                       to disable interrupt generation.
419  *
420  * @retval NRFX_SUCCESS             Requested channel limits were set.
421  * @retval NRFX_ERROR_INVALID_PARAM Attempt to activate the limits on disabled channel.
422  * @retval NRFX_ERROR_FORBIDDEN     Attempt to activate the limits for blocking conversions.
423  * @retval NRFX_ERROR_INVALID_STATE Attempt to activate the limits without configured mode.
424  */
425 nrfx_err_t nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high);
426 
427 /**
428  * @brief Function for starting the SAADC offset calibration.
429  *
430  * @param[in] calib_event_handler Calibration event handler provided by the user. In case of providing NULL,
431  *                                the calibration will be performed in the blocking manner.
432  *
433  * @retval NRFX_SUCCESS    Calibration finished successfully in the blocking manner
434  *                         or started successfully in the non-blocking manner.
435  * @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
436  */
437 nrfx_err_t nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t calib_event_handler);
438 
439 /** @} */
440 
441 void nrfx_saadc_irq_handler(void);
442 
443 #ifdef __cplusplus
444 }
445 #endif
446 
447 #endif // NRFX_SAADC_H__
448 
449