8#if SOC_ADC_DIG_CTRL_SUPPORTED && SOC_ADC_DMA_SUPPORTED
10bool ESP32ADC::IsDigiUnitSupported(adc_unit_t unit)
12 return SOC_ADC_DIG_SUPPORTED_UNIT(
static_cast<int>(unit)) != 0;
15adc_digi_output_format_t ESP32ADC::ResolveContinuousFormat()
17#if SOC_ADC_DIGI_RESULT_BYTES == 2
18 return ADC_DIGI_OUTPUT_FORMAT_TYPE1;
20 return ADC_DIGI_OUTPUT_FORMAT_TYPE2;
24void ESP32ADC::DrainContinuousFrames(uint32_t timeout_ms)
26 if ((backend_ != Backend::CONTINUOUS_DMA) || (continuous_handle_ ==
nullptr) ||
27 (continuous_read_buf_ ==
nullptr) || (continuous_parsed_buf_ ==
nullptr) ||
28 (continuous_frame_size_ == 0U))
33 std::array<uint32_t, SOC_ADC_MAX_CHANNEL_NUM> sums = {};
34 std::array<uint32_t, SOC_ADC_MAX_CHANNEL_NUM> counts = {};
35 bool first_read =
true;
36 bool any_sample =
false;
40 uint32_t out_length = 0U;
41 const esp_err_t read_err = adc_continuous_read(
42 continuous_handle_, continuous_read_buf_, continuous_frame_size_, &out_length,
43 first_read ? timeout_ms : 0U);
46 if (read_err == ESP_ERR_TIMEOUT)
51 ASSERT(read_err == ESP_OK);
52 if (read_err != ESP_OK)
54 if (read_err == ESP_ERR_INVALID_STATE)
56 (void)adc_continuous_flush_pool(continuous_handle_);
66 uint32_t parsed_count = 0U;
67 const esp_err_t parse_err =
68 adc_continuous_parse_data(continuous_handle_, continuous_read_buf_, out_length,
69 continuous_parsed_buf_, &parsed_count);
70 ASSERT(parse_err == ESP_OK);
71 if (parse_err != ESP_OK)
76 for (uint32_t i = 0; i < parsed_count; ++i)
78 const adc_continuous_data_t& sample = continuous_parsed_buf_[i];
79 if (!sample.valid || (sample.unit != unit_))
84 const uint8_t sample_channel =
static_cast<uint8_t
>(sample.channel);
85 if (sample_channel >= SOC_ADC_MAX_CHANNEL_NUM)
90 const uint8_t sample_idx = channel_idx_map_[sample_channel];
91 if ((sample_idx == INVALID_CHANNEL_IDX) || (sample_idx >= num_channels_))
96 sums[sample_idx] += sample.raw_data;
97 counts[sample_idx] += 1U;
107 for (uint8_t i = 0; i < num_channels_; ++i)
114 const uint16_t raw =
static_cast<uint16_t
>(sums[i] / counts[i]);
115 latest_raw_[i] = raw;
116 latest_values_[i] = RawToVoltage(i, raw);
117 channel_ready_[i] =
true;
121ESP32ADC::ContinuousInitResult ESP32ADC::InitContinuous(uint32_t freq,
124 if (!IsDigiUnitSupported(unit_))
126 return ContinuousInitResult::UNSUPPORTED;
129 const uint32_t sample_freq = ClampSampleFreq(freq);
130 const uint32_t min_frame =
131 static_cast<uint32_t
>(num_channels_) * SOC_ADC_DIGI_RESULT_BYTES;
132 const uint32_t frame_size = AlignUp(min_frame, SOC_ADC_DIGI_DATA_BYTES_PER_CONV);
133 const uint32_t store_size =
134 AlignUp(
static_cast<uint32_t
>((dma_buf_size >
static_cast<size_t>(frame_size))
137 SOC_ADC_DIGI_DATA_BYTES_PER_CONV);
138 const uint32_t parsed_capacity = frame_size / SOC_ADC_DIGI_RESULT_BYTES;
140 continuous_read_buf_ =
new uint8_t[frame_size];
141 continuous_parsed_buf_ =
new adc_continuous_data_t[parsed_capacity];
143 adc_continuous_handle_cfg_t handle_cfg = {};
144 handle_cfg.max_store_buf_size = store_size;
145 handle_cfg.conv_frame_size = frame_size;
146 handle_cfg.flags.flush_pool = 1U;
147 if (adc_continuous_new_handle(&handle_cfg, &continuous_handle_) != ESP_OK)
149 return ContinuousInitResult::FAILED;
152 std::array<adc_digi_pattern_config_t, SOC_ADC_PATT_LEN_MAX> patterns = {};
153 ASSERT(num_channels_ <= patterns.size());
154 if (num_channels_ > patterns.size())
156 return ContinuousInitResult::FAILED;
159 for (uint8_t i = 0; i < num_channels_; ++i)
161 patterns[i].atten =
static_cast<uint8_t
>(attenuation_);
162 patterns[i].channel =
static_cast<uint8_t
>(channel_ids_[i]);
163 patterns[i].unit =
static_cast<uint8_t
>(unit_);
164 patterns[i].bit_width =
static_cast<uint8_t
>(bitwidth_);
165 ConfigureAnalogPad(channel_ids_[i]);
166 channel_ready_[i] =
false;
167 latest_values_[i] = 0.0f;
171 adc_continuous_config_t config = {};
172 config.pattern_num = num_channels_;
173 config.adc_pattern = patterns.data();
174 config.sample_freq_hz = sample_freq;
176 (unit_ == ADC_UNIT_2) ? ADC_CONV_SINGLE_UNIT_2 : ADC_CONV_SINGLE_UNIT_1;
177 config.format = ResolveContinuousFormat();
178 if (adc_continuous_config(continuous_handle_, &config) != ESP_OK)
180 return ContinuousInitResult::FAILED;
183 if (adc_continuous_start(continuous_handle_) != ESP_OK)
185 return ContinuousInitResult::FAILED;
188 continuous_frame_size_ = frame_size;
189 continuous_prime_timeout_ms_ =
190 ((1000U *
static_cast<uint32_t
>(num_channels_) * 2U) / sample_freq) + 5U;
191 if (continuous_prime_timeout_ms_ < 5U)
193 continuous_prime_timeout_ms_ = 5U;
195 if (continuous_prime_timeout_ms_ > 50U)
197 continuous_prime_timeout_ms_ = 50U;
200 backend_ = Backend::CONTINUOUS_DMA;
201 DrainContinuousFrames(continuous_prime_timeout_ms_);
202 return ContinuousInitResult::STARTED;
207ESP32ADC::ContinuousInitResult ESP32ADC::InitContinuous(uint32_t,
size_t)
209 return ContinuousInitResult::UNSUPPORTED;