1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include "esp_err.h"
12 #include "sdkconfig.h"
13 #include "hal/adc_types.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 
20 /**
21  * @brief Driver Backgrounds
22  *
23  * --------------------------------------------------------------------------------------------------------
24  * |                              Conversion Frame                                                        |
25  * --------------------------------------------------------------------------------------------------------
26  * | Conversion Result | Conversion Result | Conversion Result | Conversion Result |  ...                 |
27  * --------------------------------------------------------------------------------------------------------
28  *
29  * ADC continuous mode conversion is made up with multiple Conversion Frames.
30  * - Conversion Frame:      One Conversion Frame contains multiple Conversion Results.
31  *                          Conversion Frame size is configured in `adc_continuous_handle_cfg_t:conv_frame_size`, in bytes.
32  *                          Each time driver see an interrupt event, this means one Conversion Frame is generated by the hardware.
33  * - Conversion Result:     One Conversion Result contains multiple bytes (see `SOC_ADC_DIGI_RESULT_BYTES`). Its
34  *                          structure is `adc_digi_output_data_t`, including ADC Unit, ADC Channel and Raw Data.
35  *
36  * For example:
37  * conv_frame_size = 100,
38  * then one Conversion Frame contains (100 / `SOC_ADC_DIGI_RESULT_BYTES`) pieces of Conversion Results
39  */
40 
41 /**
42  * @brief ADC read max timeout value, it may make the ``adc_continuous_read`` block forever if the OS supports
43  */
44 #define ADC_MAX_DELAY UINT32_MAX
45 
46 /**
47  * @brief Type of adc continuous mode driver handle
48  */
49 typedef struct adc_continuous_ctx_t *adc_continuous_handle_t;
50 
51 /**
52  * @brief ADC continuous mode driver initial configurations
53  */
54 typedef struct {
55     uint32_t max_store_buf_size;    ///< Max length of the conversion Results that driver can store, in bytes.
56     uint32_t conv_frame_size;       ///< Conversion frame size, in bytes. This should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`.
57 } adc_continuous_handle_cfg_t;
58 
59 /**
60  * @brief ADC continuous mode driver configurations
61  */
62 typedef struct {
63     uint32_t pattern_num;                   ///< Number of ADC channels that will be used
64     adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used
65     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*/
66     adc_digi_convert_mode_t conv_mode;      ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
67     adc_digi_output_format_t format;        ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
68 } adc_continuous_config_t;
69 
70 /**
71  * @brief Event data structure
72  * @note The `conv_frame_buffer` is maintained by the driver itself, so never free this piece of memory.
73  */
74 typedef struct {
75     uint8_t *conv_frame_buffer;             ///< Pointer to conversion result buffer for one conversion frame
76     uint32_t size;                          ///< Conversion frame size
77 } adc_continuous_evt_data_t;
78 
79 /**
80  * @brief Prototype of ADC continuous mode event callback
81  *
82  * @param[in] handle    ADC continuous mode driver handle
83  * @param[in] edata     Pointer to ADC contunuous mode event data
84  * @param[in] user_data User registered context, registered when in `adc_continuous_register_event_callbacks()`
85  *
86  * @return Whether a high priority task is woken up by this function
87  */
88 typedef bool (*adc_continuous_callback_t)(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data);
89 
90 /**
91  * @brief Group of ADC continuous mode callbacks
92  *
93  * @note These callbacks are all running in an ISR environment.
94  * @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
95  *       Involved variables should be in internal RAM as well.
96  */
97 typedef struct {
98     adc_continuous_callback_t on_conv_done;    ///< Event callback, invoked when one conversion frame is done. See `@brief Driver Backgrounds` to konw `conversion frame` concept.
99     adc_continuous_callback_t on_pool_ovf;     ///< Event callback, invoked when the internal pool is full.
100 } adc_continuous_evt_cbs_t;
101 
102 /**
103  * @brief Initialize ADC continuous driver and get a handle to it
104  *
105  * @param[in]  hdl_config  Pointer to ADC initilization config. Refer to ``adc_continuous_handle_cfg_t``.
106  * @param[out] ret_handle  ADC continuous mode driver handle
107  *
108  * @return
109  *         - ESP_ERR_INVALID_ARG   If the combination of arguments is invalid.
110  *         - ESP_ERR_NOT_FOUND     No free interrupt found with the specified flags
111  *         - ESP_ERR_NO_MEM        If out of memory
112  *         - ESP_OK                On success
113  */
114 esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_config, adc_continuous_handle_t *ret_handle);
115 
116 /**
117  * @brief Set ADC continuous mode required configurations
118  *
119  * @param[in] handle ADC continuous mode driver handle
120  * @param[in] config Refer to ``adc_digi_config_t``.
121  *
122  * @return
123  *      - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
124  *      - ESP_ERR_INVALID_ARG:   If the combination of arguments is invalid.
125  *      - ESP_OK:                On success
126  */
127 esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_continuous_config_t *config);
128 
129 /**
130  * @brief Register callbacks
131  *
132  * @note User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member in
133  *       the `cbs` structure to NULL.
134  * @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
135  *       Involved variables (including `user_data`) should be in internal RAM as well.
136  * @note You should only call this API when the ADC continuous mode driver isn't started. Check return value to know this.
137  *
138  * @param[in] handle    ADC continuous mode driver handle
139  * @param[in] cbs       Group of callback functions
140  * @param[in] user_data User data, which will be delivered to the callback functions directly
141  *
142  * @return
143  *        - ESP_OK:                On success
144  *        - ESP_ERR_INVALID_ARG:   Invalid arguments
145  *        - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
146  */
147 esp_err_t adc_continuous_register_event_callbacks(adc_continuous_handle_t handle, const adc_continuous_evt_cbs_t *cbs, void *user_data);
148 
149 /**
150  * @brief Start the ADC under continuous mode. After this, the hardware starts working.
151  *
152  * @param[in]  handle              ADC continuous mode driver handle
153  *
154  * @return
155  *         - ESP_ERR_INVALID_STATE Driver state is invalid.
156  *         - ESP_OK                On success
157  */
158 esp_err_t adc_continuous_start(adc_continuous_handle_t handle);
159 
160 /**
161  * @brief Read bytes from ADC under continuous mode.
162  *
163  * @param[in]  handle              ADC continuous mode driver handle
164  * @param[out] buf                 Conversion result buffer to read from ADC. Suggest convert to `adc_digi_output_data_t` for `ADC Conversion Results`.
165  *                                 See `@brief Driver Backgrounds` to know this concept.
166  * @param[in]  length_max          Expected length of the Conversion Results read from the ADC, in bytes.
167  * @param[out] out_length          Real length of the Conversion Results read from the ADC via this API, in bytes.
168  * @param[in]  timeout_ms          Time to wait for data via this API, in millisecond.
169  *
170  * @return
171  *         - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate.
172  *         - ESP_ERR_TIMEOUT       Operation timed out
173  *         - ESP_OK                On success
174  */
175 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);
176 
177 /**
178  * @brief Stop the ADC. After this, the hardware stops working.
179  *
180  * @param[in]  handle              ADC continuous mode driver handle
181  *
182  * @return
183  *         - ESP_ERR_INVALID_STATE Driver state is invalid.
184  *         - ESP_OK                On success
185  */
186 esp_err_t adc_continuous_stop(adc_continuous_handle_t handle);
187 
188 /**
189  * @brief Deinitialize the ADC continuous driver.
190  *
191  * @param[in]  handle              ADC continuous mode driver handle
192  *
193  * @return
194  *         - ESP_ERR_INVALID_STATE Driver state is invalid.
195  *         - ESP_OK                On success
196  */
197 esp_err_t adc_continuous_deinit(adc_continuous_handle_t handle);
198 
199 /**
200  * @brief Get ADC channel from the given GPIO number
201  *
202  * @param[in]  io_num     GPIO number
203  * @param[out] unit_id    ADC unit
204  * @param[out] channel    ADC channel
205  *
206  * @return
207  *        - ESP_OK:              On success
208  *        - ESP_ERR_INVALID_ARG: Invalid argument
209  *        - ESP_ERR_NOT_FOUND:   The IO is not a valid ADC pad
210  */
211 esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel);
212 
213 /**
214  * @brief Get GPIO number from the given ADC channel
215  *
216  * @param[in]  unit_id    ADC unit
217  * @param[in]  channel    ADC channel
218  * @param[out] io_num     GPIO number
219  *
220  * @param
221  *       - ESP_OK:              On success
222  *       - ESP_ERR_INVALID_ARG: Invalid argument
223  */
224 esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num);
225 
226 
227 #ifdef __cplusplus
228 }
229 #endif
230