1
6
7
10
11
18
19
20
21
22
23
24
25
26
27
28
34
35
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
64
82
83
86
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
110
111
112
113
114
115
116
117
124
128
129
146
147
148
149
150
166
167
177
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
212
213
214
215
219
220
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* ... */
/* ... */
#include "sdkconfig.h"
#include "esp_types.h"
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "driver/rtc_io.h"
#include "hal/adc_ll.h"
#include "hal/adc_types.h"7 includes
#ifdef CONFIG_PM_ENABLE
#include "esp_pm.h"
#endif
#include "freertos/FreeRTOS.h"
#include "driver/adc_i2s_legacy.h"
#include "driver/adc_types_legacy.h"
static __attribute__((unused)) const char *ADC_TAG = "ADC";
#define ADC_CHECK_RET(fun_ret) ({ \
if (fun_ret != ESP_OK) { \
ESP_LOGE(ADC_TAG,"%s:%d",__FUNCTION__,__LINE__); \
return ESP_FAIL; \
}{...} \
}{...})...
#define ADC_CHECK(a, str, ret_val) ({ \
if (!(a)) { \
ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}{...} \
}{...})...
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
extern portMUX_TYPE rtc_spinlock;
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL;
#endif
#if CONFIG_IDF_TARGET_ESP32
/* ... */
#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_12)
#define DIG_ADC_BIT_WIDTH_DEFUALT (3)
/* ... */
typedef struct {
union {
struct {
uint8_t atten: 2;
/* ... */
uint8_t bit_width: 2;
/* ... */
int8_t channel: 4;
}{ ... };
uint8_t val;
}{ ... };
}{ ... } adc_digi_pattern_table_t;
/* ... */
typedef enum {
ADC_DIGI_FORMAT_12BIT,
ADC_DIGI_FORMAT_11BIT,
ADC_DIGI_FORMAT_MAX,
}{ ... } adc_digi_format_t;
/* ... */
typedef struct {
uint32_t adc1_pattern_len;
/* ... */
uint32_t adc2_pattern_len;
adc_digi_pattern_table_t *adc1_pattern;
adc_digi_pattern_table_t *adc2_pattern;
adc_digi_convert_mode_t conv_mode;
adc_digi_format_t format;
}{ ... } adc_digi_config_t;
/* ... */
static inline void adc_ll_digi_set_output_format(bool data_sel)
{
SYSCON.saradc_ctrl.data_sar_sel = data_sel;
}{ ... }
static inline void adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
{
uint32_t tab;
uint8_t index = pattern_index / 4;
uint8_t offset = (pattern_index % 4) * 8;
if (adc_n == ADC_UNIT_1) {
tab = SYSCON.saradc_sar1_patt_tab[index];
tab &= (~(0xFF000000 >> offset));
tab |= ((uint32_t)pattern.val << 24) >> offset;
SYSCON.saradc_sar1_patt_tab[index] = tab;
}{...} else {
tab = SYSCON.saradc_sar2_patt_tab[index];
tab &= (~(0xFF000000 >> offset));
tab |= ((uint32_t)pattern.val << 24) >> offset;
SYSCON.saradc_sar2_patt_tab[index] = tab;
}{...}
}{ ... }
static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
{
switch (cfg->conv_mode) {
case ADC_CONV_SINGLE_UNIT_1:
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
break;...
case ADC_CONV_SINGLE_UNIT_2:
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
break;...
case ADC_CONV_BOTH_UNIT:
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
break;...
case ADC_CONV_ALTER_UNIT:
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
break;...
default:
abort();...
}{...}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
if (cfg->adc1_pattern_len) {
adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, cfg->adc1_pattern_len);
for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
adc_ll_digi_prepare_pattern_table(ADC_UNIT_1, i, cfg->adc1_pattern[i]);
}{...}
}{...}
}{...}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_DIG);
if (cfg->adc2_pattern_len) {
adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, cfg->adc2_pattern_len);
for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
adc_ll_digi_prepare_pattern_table(ADC_UNIT_2, i, cfg->adc2_pattern[i]);
}{...}
}{...}
}{...}
adc_ll_digi_set_output_format(cfg->format);
adc_ll_digi_convert_limit_enable(ADC_LL_DEFAULT_CONV_LIMIT_EN);
adc_ll_digi_set_convert_limit_num(ADC_LL_DEFAULT_CONV_LIMIT_NUM);
adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
}{ ... }
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
{
ADC_CHECK((src == ADC_I2S_DATA_SRC_IO_SIG || src == ADC_I2S_DATA_SRC_ADC), "ADC i2s data source error", ESP_ERR_INVALID_ARG);
ADC_ENTER_CRITICAL();
adc_ll_digi_set_data_source(src);
ADC_EXIT_CRITICAL();
return ESP_OK;
}{ ... }
extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
{
if (adc_unit == ADC_UNIT_1) {
ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
}{...} else if (adc_unit == ADC_UNIT_2) {
ADC_CHECK(false, "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
}{...}
adc_digi_pattern_table_t adc1_pattern[1];
adc_digi_pattern_table_t adc2_pattern[1];
adc_digi_config_t dig_cfg = {
.format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
.conv_mode = ADC_CONV_SINGLE_UNIT_1,
}{...};
if (adc_unit == ADC_UNIT_1) {
adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
adc1_pattern[0].channel = channel;
dig_cfg.adc1_pattern_len = 1;
dig_cfg.adc1_pattern = adc1_pattern;
}{...} else if (adc_unit == ADC_UNIT_2) {
adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
adc2_pattern[0].channel = channel;
dig_cfg.adc2_pattern_len = 1;
dig_cfg.adc2_pattern = adc2_pattern;
}{...}
adc_common_gpio_init(adc_unit, channel);
ADC_ENTER_CRITICAL();
adc_ll_digi_set_fsm_time(ADC_LL_FSM_RSTB_WAIT_DEFAULT, ADC_LL_FSM_START_WAIT_DEFAULT,
ADC_LL_FSM_STANDBY_WAIT_DEFAULT);
adc_ll_set_sample_cycle(ADC_LL_SAMPLE_CYCLE_DEFAULT);
adc_ll_pwdet_set_cct(ADC_LL_PWDET_CCT_DEFAULT);
adc_ll_digi_output_invert(ADC_UNIT_1, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
adc_ll_digi_output_invert(ADC_UNIT_2, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
adc_ll_digi_set_clk_div(ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT);
adc_digi_controller_reg_set(&dig_cfg);
ADC_EXIT_CRITICAL();
return ESP_OK;
}{ ... }
/* ... */#endif