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