1 /*
2  * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*----------------------------------------------------------------------------------
8         This file contains ESP32 and ESP32S2 Depricated ADC APIs and functions
9 -----------------------------------------------------------------------------------*/
10 
11 #include "sdkconfig.h"
12 #include "esp_types.h"
13 #include "esp_log.h"
14 #include "esp_intr_alloc.h"
15 #include "driver/rtc_io.h"
16 #include "hal/adc_hal.h"
17 #include "hal/adc_ll.h"
18 #include "hal/adc_types.h"
19 #ifdef CONFIG_PM_ENABLE
20 #include "esp_pm.h"
21 #endif
22 #include "freertos/FreeRTOS.h"
23 
24 #include "driver/adc_i2s_legacy.h"
25 #include "driver/adc_types_legacy.h"
26 
27 static __attribute__((unused)) const char *ADC_TAG = "ADC";
28 
29 #define ADC_CHECK_RET(fun_ret) ({                  \
30     if (fun_ret != ESP_OK) {                                \
31         ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__);  \
32         return ESP_FAIL;                                    \
33     }                                                       \
34 })
35 
36 #define ADC_CHECK(a, str, ret_val) ({                                               \
37     if (!(a)) {                                                                     \
38         ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str);                \
39         return (ret_val);                                                           \
40     }                                                                               \
41 })
42 
43 #define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
44 #define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
45 
46 extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
47 #define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
48 #define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
49 
50 #ifdef CONFIG_PM_ENABLE
51 esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL;
52 #endif  //CONFIG_PM_ENABLE
53 
54 
55 #if CONFIG_IDF_TARGET_ESP32
56 /*---------------------------------------------------------------
57         ESP32 Depricated ADC APIs and functions
58 ---------------------------------------------------------------*/
59 #define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
60 #define DIG_ADC_ATTEN_DEFUALT         (ADC_ATTEN_DB_11)
61 #define DIG_ADC_BIT_WIDTH_DEFUALT     (3)   //3 for ADC_WIDTH_BIT_12
62 
63 /**
64  * @brief ADC digital controller (DMA mode) conversion rules setting.
65  */
66 typedef struct {
67     union {
68         struct {
69             uint8_t atten:     2;   /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
70                                          0: measurement range 0 - 800mV,
71                                          1: measurement range 0 - 1100mV,
72                                          2: measurement range 0 - 1350mV,
73                                          3: measurement range 0 - 2600mV. */
74             uint8_t bit_width: 2;   /*!< ADC resolution.
75 -                                         0: 9 bit;
76 -                                         1: 10 bit;
77 -                                         2: 11 bit;
78 -                                         3: 12 bit. */
79             int8_t channel:   4;   /*!< ADC channel index. */
80         };
81         uint8_t val;                /*!<Raw data value */
82     };
83 } adc_digi_pattern_table_t;
84 
85 /**
86  * @brief ADC digital controller (DMA mode) output data format option.
87  */
88 typedef enum {
89     ADC_DIGI_FORMAT_12BIT,  /*!<ADC to DMA data format,                [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`). Note: For single convert mode. */
90     ADC_DIGI_FORMAT_11BIT,  /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`). Note: For multi or alter convert mode. */
91     ADC_DIGI_FORMAT_MAX,
92 } adc_digi_format_t;
93 
94 /**
95   * Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
96   *
97   *     +---------------------+--------+--------+--------+
98   *     | conv_mode           | single |  both  |  alter |
99   *     +---------------------+--------+--------+--------+
100   *     | trigger meas times  |    1   |    1   |    1   |
101   *     +---------------------+--------+--------+--------+
102   *     | conv_limit_num      |   +1   |   +1   |   +1   |
103   *     | dma_eof_num         |   +1   |   +2   |   +1   |
104   *     | dma output (byte)   |   +2   |   +4   |   +2   |
105   *     +---------------------+--------+--------+--------+
106   */
107 typedef struct {
108     uint32_t adc1_pattern_len;               /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
109                                                  The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
110                                                  resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
111                                                  pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
112     uint32_t adc2_pattern_len;               /*!<Refer to ``adc1_pattern_len`` */
113     adc_digi_pattern_table_t *adc1_pattern;  /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
114     adc_digi_pattern_table_t *adc2_pattern;  /*!<Refer to `adc1_pattern` */
115     adc_digi_convert_mode_t conv_mode;       /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
116     adc_digi_format_t format;                /*!<ADC output data format for digital controller. See ``adc_digi_format_t``. */
117 } adc_digi_config_t;
118 
119 /**
120  * Set adc output 16-bit-data format from digital controller.
121  *
122  * @param data_sel 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode.
123  *                 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode
124  * @note see `adc_ll_digi_pattern_table_t` for more detail of data bit width
125  */
adc_ll_digi_set_output_format(bool data_sel)126 static inline void adc_ll_digi_set_output_format(bool data_sel)
127 {
128     SYSCON.saradc_ctrl.data_sar_sel = data_sel;
129 }
130 
adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n,uint32_t pattern_index,adc_digi_pattern_table_t pattern)131 static inline void adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
132 {
133     uint32_t tab;
134     uint8_t index = pattern_index / 4;
135     uint8_t offset = (pattern_index % 4) * 8;
136     if (adc_n == ADC_UNIT_1) {
137         tab = SYSCON.saradc_sar1_patt_tab[index];   // Read old register value
138         tab &= (~(0xFF000000 >> offset));           // clear old data
139         tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
140         SYSCON.saradc_sar1_patt_tab[index] = tab;   // Write back
141     } else { // adc_n == ADC_UNIT_2
142         tab = SYSCON.saradc_sar2_patt_tab[index];   // Read old register value
143         tab &= (~(0xFF000000 >> offset));           // clear old data
144         tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
145         SYSCON.saradc_sar2_patt_tab[index] = tab;   // Write back
146     }
147 }
148 
adc_digi_controller_reg_set(const adc_digi_config_t * cfg)149 static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
150 {
151     /* On ESP32, only support ADC1 */
152     switch (cfg->conv_mode) {
153         case ADC_CONV_SINGLE_UNIT_1:
154             adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
155             break;
156         case ADC_CONV_SINGLE_UNIT_2:
157             adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
158             break;
159         case ADC_CONV_BOTH_UNIT:
160             adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
161             break;
162         case ADC_CONV_ALTER_UNIT:
163             adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
164             break;
165         default:
166             abort();
167     }
168 
169     if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
170         adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
171         if (cfg->adc1_pattern_len) {
172             adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
173             adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, cfg->adc1_pattern_len);
174             for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
175                 adc_ll_digi_prepare_pattern_table(ADC_UNIT_1, i, cfg->adc1_pattern[i]);
176             }
177         }
178     }
179     if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
180         adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_DIG);
181         if (cfg->adc2_pattern_len) {
182             adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
183             adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, cfg->adc2_pattern_len);
184             for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
185                 adc_ll_digi_prepare_pattern_table(ADC_UNIT_2, i, cfg->adc2_pattern[i]);
186             }
187         }
188     }
189     adc_ll_digi_set_output_format(cfg->format);
190     adc_ll_digi_convert_limit_enable(ADC_LL_DEFAULT_CONV_LIMIT_EN);
191     adc_ll_digi_set_convert_limit_num(ADC_LL_DEFAULT_CONV_LIMIT_NUM);
192     adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
193 }
194 
adc_set_i2s_data_source(adc_i2s_source_t src)195 esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
196 {
197     ADC_CHECK((src == ADC_I2S_DATA_SRC_IO_SIG || src == ADC_I2S_DATA_SRC_ADC), "ADC i2s data source error", ESP_ERR_INVALID_ARG);
198     ADC_ENTER_CRITICAL();
199     adc_ll_digi_set_data_source(src);
200     ADC_EXIT_CRITICAL();
201     return ESP_OK;
202 }
203 
204 extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
adc_i2s_mode_init(adc_unit_t adc_unit,adc_channel_t channel)205 esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
206 {
207     if (adc_unit == ADC_UNIT_1) {
208         ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
209     } else if (adc_unit == ADC_UNIT_2) {
210         //ADC2 does not support DMA mode
211         ADC_CHECK(false, "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
212         ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
213     }
214 
215     adc_digi_pattern_table_t adc1_pattern[1];
216     adc_digi_pattern_table_t adc2_pattern[1];
217     adc_digi_config_t dig_cfg = {
218         .format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
219         .conv_mode = ADC_CONV_SINGLE_UNIT_1,
220     };
221 
222     if (adc_unit == ADC_UNIT_1) {
223         adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
224         adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
225         adc1_pattern[0].channel = channel;
226         dig_cfg.adc1_pattern_len = 1;
227         dig_cfg.adc1_pattern = adc1_pattern;
228     } else if (adc_unit == ADC_UNIT_2) {
229         adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
230         adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
231         adc2_pattern[0].channel = channel;
232         dig_cfg.adc2_pattern_len = 1;
233         dig_cfg.adc2_pattern = adc2_pattern;
234     }
235     adc_common_gpio_init(adc_unit, channel);
236     ADC_ENTER_CRITICAL();
237     adc_ll_digi_set_fsm_time(ADC_LL_FSM_RSTB_WAIT_DEFAULT, ADC_LL_FSM_START_WAIT_DEFAULT,
238                              ADC_LL_FSM_STANDBY_WAIT_DEFAULT);
239     adc_ll_set_sample_cycle(ADC_LL_SAMPLE_CYCLE_DEFAULT);
240     adc_hal_pwdet_set_cct(ADC_LL_PWDET_CCT_DEFAULT);
241     adc_ll_digi_output_invert(ADC_UNIT_1, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
242     adc_ll_digi_output_invert(ADC_UNIT_2, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
243     adc_ll_digi_set_clk_div(ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT);
244     adc_digi_controller_reg_set(&dig_cfg);
245     ADC_EXIT_CRITICAL();
246 
247     return ESP_OK;
248 }
249 
250 #endif  //#if CONFIG_IDF_TARGET_ESP32
251