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_CONVTIME || 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 #if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8) || defined(__NRFX_DOXYGEN__)
139 /**
140  * @brief Macro for getting number of bytes needed to store specified number of SAADC samples
141  *        for given resolution of the SAADC.
142  *
143  * @param[in] _resolution Resolution expressed as @ref nrf_saadc_resolution_t.
144  * @param[in] _samples    Number of samples.
145  *
146  * @return Number of bytes needed to store specified number of samples.
147  */
148 #define NRFX_SAADC_SAMPLES_TO_BYTES(_resolution, _samples) \
149     ((_resolution) == NRF_SAADC_RESOLUTION_8BIT ? _samples : (_samples * 2))
150 #else
151 #define NRFX_SAADC_SAMPLES_TO_BYTES(_resolution, _samples) (_samples)
152 #endif
153 
154 #if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8) || defined(__NRFX_DOXYGEN__)
155 /**
156  * @brief Macro for getting specified SAADC sample from the filled buffer.
157  *
158  * @param[in] _resolution Resolution expressed as @ref nrf_saadc_resolution_t.
159  * @param[in] _samples    Pointer to the buffer filled with SAADC samples.
160  * @param[in] _index      Sample index.
161  *
162  * @return Specified sample.
163  */
164 #define NRFX_SAADC_SAMPLE_GET(_resolution, _samples, _index) \
165     ((_resolution) == NRF_SAADC_RESOLUTION_8BIT ? (((int8_t *) (_samples))[(_index)]) : \
166                                                   (((int16_t *)(_samples))[(_index)]))
167 #else
168 #define NRFX_SAADC_SAMPLE_GET(_resolution, _samples, _index) (((int16_t *)(_samples))[(_index)])
169 #endif
170 
171 /**
172  * @brief SAADC driver advanced mode default configuration.
173  *
174  * This configuration sets up advanced mode of the SAADC driver with the following options:
175  * - oversampling disabled
176  * - burst disabled
177  * - internal sampling timer disabled
178  * - triggering of the START task on the END event disabled
179  *
180  * @param[in] _pin_p Positive input analog pin.
181  * @param[in] _pin_n Negative input analog pin.
182  * @param[in] _index Channel index.
183  *
184  * @sa nrfx_saadc_adv_config_t
185  */
186 #define NRFX_SAADC_DEFAULT_ADV_CONFIG                                           \
187 {                                                                               \
188     .oversampling      = NRF_SAADC_OVERSAMPLE_DISABLED,                         \
189     .burst             = NRF_SAADC_BURST_DISABLED,                              \
190     .internal_timer_cc = 0,                                                     \
191     .start_on_end      = false,                                                 \
192 }
193 
194 /** @brief SAADC channel configuration structure. */
195 typedef struct
196 {
197     nrf_saadc_channel_config_t channel_config; ///< Channel hardware configuration.
198     nrf_saadc_input_t          pin_p;          ///< Input positive pin selection.
199     nrf_saadc_input_t          pin_n;          ///< Input negative pin selection.
200     uint8_t                    channel_index;  ///< Channel index.
201 } nrfx_saadc_channel_t;
202 
203 /** @brief SAADC driver advanced mode configuration structure. */
204 typedef struct
205 {
206     nrf_saadc_oversample_t oversampling;      ///< Oversampling configuration.
207     nrf_saadc_burst_t      burst;             ///< Burst configuration.
208     uint16_t               internal_timer_cc; ///< Internal timer capture and compare value.
209     bool                   start_on_end;      ///< Flag indicating if the START task is to be triggered on the END event.
210 } nrfx_saadc_adv_config_t;
211 
212 /** @brief SAADC driver event types. */
213 typedef enum
214 {
215     NRFX_SAADC_EVT_DONE,          ///< Event generated when the buffer is filled with samples.
216     NRFX_SAADC_EVT_LIMIT,         ///< Event generated when one of the limits is reached.
217     NRFX_SAADC_EVT_CALIBRATEDONE, ///< Event generated when the calibration is complete.
218     NRFX_SAADC_EVT_BUF_REQ,       ///< Event generated when the next buffer for continuous conversion is requested.
219     NRFX_SAADC_EVT_READY,         ///< Event generated when the first buffer is acquired by the peripheral and sampling can be started.
220     NRFX_SAADC_EVT_FINISHED,      ///< Event generated when all supplied buffers are filled with results.
221 } nrfx_saadc_evt_type_t;
222 
223 /** @brief SAADC driver done event data. */
224 typedef struct
225 {
226     nrf_saadc_value_t * p_buffer; ///< Pointer to the buffer with converted samples.
227     uint16_t            size;     ///< Number of samples in the buffer.
228 } nrfx_saadc_done_evt_t;
229 
230 /** @brief SAADC driver limit event data. */
231 typedef struct
232 {
233     uint8_t           channel;    ///< Channel on which the limit was detected.
234     nrf_saadc_limit_t limit_type; ///< Type of limit detected.
235 } nrfx_saadc_limit_evt_t;
236 
237 /** @brief SAADC driver event structure. */
238 typedef struct
239 {
240     nrfx_saadc_evt_type_t type; ///< Event type.
241     union
242     {
243         nrfx_saadc_done_evt_t  done;  ///< Data for @ref NRFX_SAADC_EVT_DONE event.
244         nrfx_saadc_limit_evt_t limit; ///< Data for @ref NRFX_SAADC_EVT_LIMIT event.
245     } data;                           ///< Union to store event data.
246 } nrfx_saadc_evt_t;
247 
248 /**
249  * @brief SAADC driver event handler.
250  *
251  * When operating in the advanced mode:
252  * - when the sampling is performed by the external timer, the external timer can be safely started
253  *   on @ref NRFX_SAADC_EVT_READY and stopped on @ref NRFX_SAADC_EVT_FINISHED.
254  * - call the @ref nrfx_saadc_buffer_set() on @ref NRFX_SAADC_EVT_BUF_REQ to achieve the continuous conversion.
255  *
256  * @param[in] p_event Pointer to an SAADC driver event. The event structure is allocated on
257  *                    the stack, so it is valid only within the context of the event handler.
258  */
259 typedef void (* nrfx_saadc_event_handler_t)(nrfx_saadc_evt_t const * p_event);
260 
261 /**
262  * @brief Function for initializing the SAADC driver.
263  *
264  * @param[in] interrupt_priority Interrupt priority.
265  *
266  * @retval NRFX_SUCCESS             Initialization was successful.
267  * @retval NRFX_ERROR_ALREADY       The driver is already initialized.
268  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
269  *                                  Deprecated - use @ref NRFX_ERROR_ALREADY instead.
270  */
271 nrfx_err_t nrfx_saadc_init(uint8_t interrupt_priority);
272 
273 /**
274  * @brief Function for uninitializing the SAADC driver.
275  *
276  * This function stops all ongoing conversions and disables all channels.
277  */
278 void nrfx_saadc_uninit(void);
279 
280 /**
281  * @brief Function for checking if the SAADC driver is initialized.
282  *
283  * @retval true  Driver is already initialized.
284  * @retval false Driver is not initialized.
285  */
286 bool nrfx_saadc_init_check(void);
287 
288 /**
289  * @brief Function for configuring multiple SAADC channels.
290  *
291  * @note The values of the @ref nrf_saadc_channel_config_t.burst fields in channel configurations
292  *       are ignored. They will be overridden with the value suitable for the selected driver
293  *       operation mode.
294  * @note The desired mode (simple or advanced) must be set after the channels are configured.
295  *
296  * @warning This function overrides previous configuration done on any channel by
297  *          @ref nrfx_saadc_channels_config or @ref nrfx_saadc_channel_config.
298  *
299  * @param[in] p_channels    Pointer to the array of channel configuration structures.
300  * @param[in] channel_count Number of channels to be configured.
301  *
302  * @retval NRFX_SUCCESS             Configuration was successful.
303  * @retval NRFX_ERROR_BUSY          There is a conversion or calibration ongoing.
304  * @retval NRFX_ERROR_INVALID_PARAM Attempt to configure the same channel more than once.
305  */
306 nrfx_err_t nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,
307                                       uint32_t                     channel_count);
308 
309 /**
310  * @brief Function for configuring single SAADC channel.
311  *
312  * @note The values of the @ref nrf_saadc_channel_config_t.burst fields in channel configurations
313  *       are ignored. They will be overridden with the value suitable for the selected driver
314  *       operation mode.
315  *
316  * @warning This function overrides previous configuration done on specified channel by
317  *          @ref nrfx_saadc_channels_config or @ref nrfx_saadc_channel_config.
318  *
319  * @param[in] p_channel Pointer to the channel configuration structure.
320  *
321  * @retval NRFX_SUCCESS    Configuration was successful.
322  * @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
323  */
324 nrfx_err_t nrfx_saadc_channel_config(nrfx_saadc_channel_t const * p_channel);
325 
326 /**
327  * @brief Function for getting the currently configured SAADC channels.
328  *
329  * @return Bitmask of configured channels.
330  */
331 uint32_t nrfx_saadc_channels_configured_get(void);
332 
333 /**
334  * @brief Function for deconfiguring the specified SAADC channels.
335  *
336  * @warning Pins associated with the deconfigured channels will be released after
337  *          next @ref nrfx_saadc_simple_mode_set() or @ref nrfx_saadc_advanced_mode_set() call.
338  *
339  * @param[in] channel_mask Bitmask of channels to be deconfigured.
340  *
341  * @retval NRFX_SUCCESS    Deconfiguration was successful.
342  * @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
343  */
344 nrfx_err_t nrfx_saadc_channels_deconfig(uint32_t channel_mask);
345 
346 /**
347  * @brief Function for setting the SAADC driver in the simple mode.
348  *
349  * The simple mode allows obtaining a single sample from each requested channel.
350  * The conversion can be done in a blocking or non-blocking manner.
351  * Sampling is initiated by calling @ref nrfx_saadc_mode_trigger() once.
352  *
353  * @param[in] channel_mask  Bitmask of channels to be used in the simple mode.
354  * @param[in] resolution    Resolution configuration.
355  * @param[in] oversampling  Oversampling configuration.
356  * @param[in] event_handler Event handler provided by the user. In case of providing NULL,
357  *                          the conversion will be performed in the blocking manner.
358  *
359  * @retval NRFX_SUCCESS             Initialization was successful.
360  * @retval NRFX_ERROR_BUSY          There is a conversion or calibration ongoing.
361  * @retval NRFX_ERROR_INVALID_PARAM Attempt to activate channel that is not configured.
362  */
363 nrfx_err_t nrfx_saadc_simple_mode_set(uint32_t                   channel_mask,
364                                       nrf_saadc_resolution_t     resolution,
365                                       nrf_saadc_oversample_t     oversampling,
366                                       nrfx_saadc_event_handler_t event_handler);
367 
368 /**
369  * @brief Function for setting the SAADC driver in the advanced mode.
370  *
371  * The advanced mode allows performing double-buffered conversions of arbitrary length.
372  * The conversions can be done in a blocking or non-blocking manner. When performing conversions
373  * in the non-blocking manner and @ref nrfx_saadc_adv_config_t.internal_timer_cc is set to 0,
374  * sampling needs to be done by triggering @ref NRF_SAADC_TASK_SAMPLE externally
375  * (for example by using the TIMER and/or the PPI/DPPI).
376  * When performing conversions in the non-blocking manner and @ref nrfx_saadc_adv_config_t.start_on_end
377  * is false, the @ref NRF_SAADC_TASK_START needs to be triggered on @ref NRF_SAADC_EVENT_END
378  * externally (for example by using the PPI/DPPI).
379  * Sampling is initiated by calling @ref nrfx_saadc_mode_trigger(). In case of performing
380  * conversions in the blocking manner, @ref nrfx_saadc_mode_trigger() may need to be called several
381  * times as each call sample each requested channel once.
382  *
383  * @note The internal timer can only be used when a single input channel is enabled.
384  * @note The internal timer can only be used in the non-blocking mode.
385  *
386  * @param[in] channel_mask  Bitmask of channels to be used in the advanced mode.
387  * @param[in] resolution    Resolution configuration.
388  * @param[in] p_config      Pointer to the structure with the advanced mode configuration.
389  * @param[in] event_handler Event handler provided by the user. In case of providing NULL,
390  *                          the conversion will be performed in the blocking manner.
391  *
392  * @retval NRFX_SUCCESS             Initialization was successful.
393  * @retval NRFX_ERROR_BUSY          There is a conversion or calibration ongoing.
394  * @retval NRFX_ERROR_INVALID_PARAM Attempt to activate channel that is not configured.
395  * @retval NRFX_ERROR_NOT_SUPPORTED Attempt to activate either of the following:
396  *                                  * internal timer in the blocking mode,
397  *                                  * internal timer with multiple channels enabled,
398  *                                  * oversampling without burst with multiple channels enabled.
399  */
400 nrfx_err_t nrfx_saadc_advanced_mode_set(uint32_t                        channel_mask,
401                                         nrf_saadc_resolution_t          resolution,
402                                         nrfx_saadc_adv_config_t const * p_config,
403                                         nrfx_saadc_event_handler_t      event_handler);
404 
405 /**
406  * @brief Function for supplying the buffer to be used in the next part of
407  *        the conversion.
408  *
409  * @param[in] p_buffer Pointer to the buffer to be filled with conversion results.
410  * @param[in] size     Number of samples in the buffer.
411  *
412  * @retval NRFX_SUCCESS              Buffer was supplied successfully.
413  * @retval NRFX_ERROR_INVALID_ADDR   The provided buffer is not in the Data RAM region.
414  * @retval NRFX_ERROR_INVALID_LENGTH The provided buffer is not aligned to the number of activated channels
415  *                                   or is too long for the EasyDMA to handle.
416  * @retval NRFX_ERROR_INVALID_STATE  The driver is in the idle mode.
417  * @retval NRFX_ERROR_ALREADY        Both buffers for double-buffered conversions are already set.
418  */
419 nrfx_err_t nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer, uint16_t size);
420 
421 /**
422  * @brief Function for triggering the conversion in the configured mode.
423  *
424  * @retval NRFX_SUCCESS             Operation finished successfully in the blocking manner or started
425  *                                  successfully in the non-blocking manner.
426  * @retval NRFX_ERROR_BUSY          The driver is performing the conversion in the advanced blocking mode.
427  *                                  Call the function again to continue the conversion.
428  * @retval NRFX_ERROR_NO_MEM        There is no buffer provided.
429  *                                  Supply the buffer using @ref nrfx_saadc_buffer_set() and try again.
430  * @retval NRFX_ERROR_INVALID_STATE There is an ongoing conversion or calibration being performed
431  *                                  in the non-blocking manner or the driver is in the idle mode.
432  */
433 nrfx_err_t nrfx_saadc_mode_trigger(void);
434 
435 /**
436  * @brief Function for aborting the ongoing and buffered conversions.
437  *
438  * @warning Aborting blocking conversion or calibration from different context is not supported.
439  *          Perform the operation in non-blocking manner instead.
440  *
441  * @note @ref NRFX_SAADC_EVT_DONE event will be generated if there is a conversion in progress.
442  *       Event will contain number of words in the sample buffer.
443  */
444 void nrfx_saadc_abort(void);
445 
446 /**
447  * @brief Function for setting the SAADC channel limits.
448  *
449  * When limits are enabled and the conversion result exceeds the defined bounds,
450  * the handler function is called with the corresponding event as parameter.
451  *
452  * @note Before the limits are set, the driver operation mode (simple or advanced) has
453  *       to be configured. Only non-blocking conversions can be monitored.
454  *
455  * @note Changing of the driver operation mode disables all configured limits.
456  *
457  * @param[in] channel    Channel index.
458  * @param[in] limit_low  Limit low value to generate interrupt. Use @c INT16_MIN
459  *                       to disable interrupt generation.
460  * @param[in] limit_high Limit high value to generate interrupt. Use @c INT16_MAX
461  *                       to disable interrupt generation.
462  *
463  * @retval NRFX_SUCCESS             Requested channel limits were set.
464  * @retval NRFX_ERROR_INVALID_PARAM Attempt to activate the limits on disabled channel.
465  * @retval NRFX_ERROR_FORBIDDEN     Attempt to activate the limits for blocking conversions.
466  * @retval NRFX_ERROR_INVALID_STATE Attempt to activate the limits without configured mode.
467  */
468 nrfx_err_t nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high);
469 
470 /**
471  * @brief Function for starting the SAADC offset calibration.
472  *
473  * @param[in] calib_event_handler Calibration event handler provided by the user. In case of providing NULL,
474  *                                the calibration will be performed in the blocking manner.
475  *
476  * @retval NRFX_SUCCESS    Calibration finished successfully in the blocking manner
477  *                         or started successfully in the non-blocking manner.
478  * @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
479  */
480 nrfx_err_t nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t calib_event_handler);
481 
482 /** @} */
483 
484 void nrfx_saadc_irq_handler(void);
485 
486 #ifdef __cplusplus
487 }
488 #endif
489 
490 #endif // NRFX_SAADC_H__
491 
492