esp-idf/components/esp_adc/include/esp_adc/adc_continuous.h

244 wiersze
10 KiB
C

/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "sdkconfig.h"
#include "hal/adc_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Driver Backgrounds
*
* --------------------------------------------------------------------------------------------------------
* | Conversion Frame |
* --------------------------------------------------------------------------------------------------------
* | Conversion Result | Conversion Result | Conversion Result | Conversion Result | ... |
* --------------------------------------------------------------------------------------------------------
*
* ADC continuous mode conversion is made up with multiple Conversion Frames.
* - Conversion Frame: One Conversion Frame contains multiple Conversion Results.
* Conversion Frame size is configured in `adc_continuous_handle_cfg_t:conv_frame_size`, in bytes.
* Each time driver see an interrupt event, this means one Conversion Frame is generated by the hardware.
* - Conversion Result: One Conversion Result contains multiple bytes (see `SOC_ADC_DIGI_RESULT_BYTES`). Its
* structure is `adc_digi_output_data_t`, including ADC Unit, ADC Channel and Raw Data.
*
* For example:
* conv_frame_size = 100 indicates one Conversion Frame contains (100 / `SOC_ADC_DIGI_RESULT_BYTES`) pieces of Conversion Results.
*/
/**
* @brief ADC read max timeout value, it may make the ``adc_continuous_read`` block forever if the OS supports
*/
#define ADC_MAX_DELAY UINT32_MAX
/**
* @brief Type of adc continuous mode driver handle
*/
typedef struct adc_continuous_ctx_t *adc_continuous_handle_t;
/**
* @brief ADC continuous mode driver initial configurations
*/
typedef struct {
uint32_t max_store_buf_size; ///< Max length of the conversion results that driver can store, in bytes.
uint32_t conv_frame_size; ///< Conversion frame size, in bytes. This should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`.
struct {
uint32_t flush_pool: 1; ///< Flush the internal pool when the pool is full.
} flags; ///< Driver flags
} adc_continuous_handle_cfg_t;
/**
* @brief ADC continuous mode driver configurations
*/
typedef struct {
uint32_t pattern_num; ///< Number of ADC channels that will be used
adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used
uint32_t sample_freq_hz; /*!< The expected ADC sampling frequency in Hz. Please refer to `soc/soc_caps.h` to know available sampling frequency range*/
adc_digi_convert_mode_t conv_mode; ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
adc_digi_output_format_t format; ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
} adc_continuous_config_t;
/**
* @brief Event data structure
* @note The `conv_frame_buffer` is maintained by the driver itself, so never free this piece of memory.
*/
typedef struct {
uint8_t *conv_frame_buffer; ///< Pointer to conversion result buffer for one conversion frame
uint32_t size; ///< Conversion frame size
} adc_continuous_evt_data_t;
/**
* @brief Prototype of ADC continuous mode event callback
*
* @param[in] handle ADC continuous mode driver handle
* @param[in] edata Pointer to ADC continuous mode event data
* @param[in] user_data User registered context, registered when in `adc_continuous_register_event_callbacks()`
*
* @return Whether a high priority task is woken up by this function
*/
typedef bool (*adc_continuous_callback_t)(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data);
/**
* @brief Group of ADC continuous mode callbacks
*
* @note These callbacks are all running in an ISR environment.
* @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* Involved variables should be in internal RAM as well.
*/
typedef struct {
adc_continuous_callback_t on_conv_done; ///< Event callback, invoked when one conversion frame is done. See the subsection `Driver Backgrounds` in this header file to learn about the `conversion frame` concept.
adc_continuous_callback_t on_pool_ovf; ///< Event callback, invoked when the internal pool is full.
} adc_continuous_evt_cbs_t;
/**
* @brief Initialize ADC continuous driver and get a handle to it
*
* @param[in] hdl_config Pointer to ADC initialization config. Refer to ``adc_continuous_handle_cfg_t``.
* @param[out] ret_handle ADC continuous mode driver handle
*
* @return
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
* - ESP_ERR_NO_MEM If out of memory
* - ESP_OK On success
*/
esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_config, adc_continuous_handle_t *ret_handle);
/**
* @brief Set ADC continuous mode required configurations
*
* @param[in] handle ADC continuous mode driver handle
* @param[in] config Refer to ``adc_digi_config_t``.
*
* @return
* - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
* - ESP_ERR_INVALID_ARG: If the combination of arguments is invalid.
* - ESP_OK: On success
*/
esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_continuous_config_t *config);
/**
* @brief Register callbacks
*
* @note User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member in
* the `cbs` structure to NULL.
* @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* Involved variables (including `user_data`) should be in internal RAM as well.
* @note You should only call this API when the ADC continuous mode driver isn't started. Check return value to know this.
*
* @param[in] handle ADC continuous mode driver handle
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be delivered to the callback functions directly
*
* @return
* - ESP_OK: On success
* - ESP_ERR_INVALID_ARG: Invalid arguments
* - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
*/
esp_err_t adc_continuous_register_event_callbacks(adc_continuous_handle_t handle, const adc_continuous_evt_cbs_t *cbs, void *user_data);
/**
* @brief Start the ADC under continuous mode. After this, the hardware starts working.
*
* @param[in] handle ADC continuous mode driver handle
*
* @return
* - ESP_ERR_INVALID_STATE Driver state is invalid.
* - ESP_OK On success
*/
esp_err_t adc_continuous_start(adc_continuous_handle_t handle);
/**
* @brief Read bytes from ADC under continuous mode.
*
* @param[in] handle ADC continuous mode driver handle
* @param[out] buf Conversion result buffer to read from ADC. Suggest convert to `adc_digi_output_data_t` for `ADC Conversion Results`.
* See the subsection `Driver Backgrounds` in this header file to learn about this concept.
* @param[in] length_max Expected length of the Conversion Results read from the ADC, in bytes.
* @param[out] out_length Real length of the Conversion Results read from the ADC via this API, in bytes.
* @param[in] timeout_ms Time to wait for data via this API, in millisecond.
*
* @return
* - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate.
* - ESP_ERR_TIMEOUT Operation timed out
* - ESP_OK On success
*/
esp_err_t adc_continuous_read(adc_continuous_handle_t handle, uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms);
/**
* @brief Stop the ADC. After this, the hardware stops working.
*
* @param[in] handle ADC continuous mode driver handle
*
* @return
* - ESP_ERR_INVALID_STATE Driver state is invalid.
* - ESP_OK On success
*/
esp_err_t adc_continuous_stop(adc_continuous_handle_t handle);
/**
* @brief Deinitialize the ADC continuous driver.
*
* @param[in] handle ADC continuous mode driver handle
*
* @return
* - ESP_ERR_INVALID_STATE Driver state is invalid.
* - ESP_OK On success
*/
esp_err_t adc_continuous_deinit(adc_continuous_handle_t handle);
/**
* @brief Flush the driver internal pool
*
* @note This API is not supposed to be called in an ISR context
*
* @param[in] handle ADC continuous mode driver handle
*
* @return
* - ESP_ERR_INVALID_STATE Driver state is invalid, you should call this API when it's in init state
* - ESP_ERR_INVALID_ARG: Invalid arguments
* - ESP_OK On success
*/
esp_err_t adc_continuous_flush_pool(adc_continuous_handle_t handle);
/**
* @brief Get ADC channel from the given GPIO number
*
* @param[in] io_num GPIO number
* @param[out] unit_id ADC unit
* @param[out] channel ADC channel
*
* @return
* - ESP_OK: On success
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_NOT_FOUND: The IO is not a valid ADC pad
*/
esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t * const unit_id, adc_channel_t * const channel);
/**
* @brief Get GPIO number from the given ADC channel
*
* @param[in] unit_id ADC unit
* @param[in] channel ADC channel
* @param[out] io_num GPIO number
*
* @param
* - ESP_OK: On success
* - ESP_ERR_INVALID_ARG: Invalid argument
*/
esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int * const io_num);
#ifdef __cplusplus
}
#endif