9#if SOC_ADC_DIG_CTRL_SUPPORTED && SOC_ADC_DMA_SUPPORTED
11bool ESP32ADC::IsDigiUnitSupported(adc_unit_t unit)
13 return SOC_ADC_DIG_SUPPORTED_UNIT(
static_cast<int>(unit)) != 0;
16adc_digi_output_format_t ESP32ADC::ResolveContinuousFormat()
18#if SOC_ADC_DIGI_RESULT_BYTES == 2
19 return ADC_DIGI_OUTPUT_FORMAT_TYPE1;
21 return ADC_DIGI_OUTPUT_FORMAT_TYPE2;
25void ESP32ADC::DrainContinuousFrames(uint32_t timeout_ms)
27 if ((backend_ != Backend::CONTINUOUS_DMA) || (continuous_handle_ ==
nullptr) ||
28 (continuous_read_buf_ ==
nullptr) || (continuous_parsed_buf_ ==
nullptr) ||
29 (continuous_frame_size_ == 0U))
34 std::array<uint32_t, SOC_ADC_MAX_CHANNEL_NUM> sums = {};
35 std::array<uint32_t, SOC_ADC_MAX_CHANNEL_NUM> counts = {};
36 bool first_read =
true;
37 bool any_sample =
false;
41 uint32_t out_length = 0U;
42 const esp_err_t read_err = adc_continuous_read(
43 continuous_handle_, continuous_read_buf_, continuous_frame_size_, &out_length,
44 first_read ? timeout_ms : 0U);
47 if (read_err == ESP_ERR_TIMEOUT)
52 ASSERT(read_err == ESP_OK);
53 if (read_err != ESP_OK)
55 if (read_err == ESP_ERR_INVALID_STATE)
57 (void)adc_continuous_flush_pool(continuous_handle_);
67 uint32_t parsed_count = 0U;
68 const esp_err_t parse_err =
69 adc_continuous_parse_data(continuous_handle_, continuous_read_buf_, out_length,
70 continuous_parsed_buf_, &parsed_count);
71 ASSERT(parse_err == ESP_OK);
72 if (parse_err != ESP_OK)
77 for (uint32_t i = 0; i < parsed_count; ++i)
79 const adc_continuous_data_t& sample = continuous_parsed_buf_[i];
80 if (!sample.valid || (sample.unit != unit_))
85 const uint8_t sample_channel =
static_cast<uint8_t
>(sample.channel);
86 if (sample_channel >= SOC_ADC_MAX_CHANNEL_NUM)
91 const uint8_t sample_idx = channel_idx_map_[sample_channel];
92 if ((sample_idx == kInvalidChannelIdx) || (sample_idx >= num_channels_))
97 sums[sample_idx] += sample.raw_data;
98 counts[sample_idx] += 1U;
108 for (uint8_t i = 0; i < num_channels_; ++i)
115 const uint16_t raw =
static_cast<uint16_t
>(sums[i] / counts[i]);
116 latest_raw_[i] = raw;
117 latest_values_[i] = RawToVoltage(i, raw);
118 channel_ready_[i] =
true;
122ESP32ADC::ContinuousInitResult ESP32ADC::InitContinuous(uint32_t freq,
125 if (!IsDigiUnitSupported(unit_))
127 return ContinuousInitResult::UNSUPPORTED;
130 const uint32_t sample_freq = ClampSampleFreq(freq);
131 const uint32_t min_frame =
132 static_cast<uint32_t
>(num_channels_) * SOC_ADC_DIGI_RESULT_BYTES;
133 const uint32_t frame_size = AlignUp(min_frame, SOC_ADC_DIGI_DATA_BYTES_PER_CONV);
134 const uint32_t store_size =
135 AlignUp(
static_cast<uint32_t
>((dma_buf_size >
static_cast<size_t>(frame_size))
138 SOC_ADC_DIGI_DATA_BYTES_PER_CONV);
139 const uint32_t parsed_capacity = frame_size / SOC_ADC_DIGI_RESULT_BYTES;
141 continuous_read_buf_ =
new (std::nothrow) uint8_t[frame_size];
142 continuous_parsed_buf_ =
new (std::nothrow) adc_continuous_data_t[parsed_capacity];
143 ASSERT((continuous_read_buf_ !=
nullptr) && (continuous_parsed_buf_ !=
nullptr));
144 if ((continuous_read_buf_ ==
nullptr) || (continuous_parsed_buf_ ==
nullptr))
146 return ContinuousInitResult::FAILED;
149 adc_continuous_handle_cfg_t handle_cfg = {};
150 handle_cfg.max_store_buf_size = store_size;
151 handle_cfg.conv_frame_size = frame_size;
152 handle_cfg.flags.flush_pool = 1U;
153 if (adc_continuous_new_handle(&handle_cfg, &continuous_handle_) != ESP_OK)
155 return ContinuousInitResult::FAILED;
158 std::array<adc_digi_pattern_config_t, SOC_ADC_PATT_LEN_MAX> patterns = {};
159 ASSERT(num_channels_ <= patterns.size());
160 if (num_channels_ > patterns.size())
162 return ContinuousInitResult::FAILED;
165 for (uint8_t i = 0; i < num_channels_; ++i)
167 patterns[i].atten =
static_cast<uint8_t
>(attenuation_);
168 patterns[i].channel =
static_cast<uint8_t
>(channel_ids_[i]);
169 patterns[i].unit =
static_cast<uint8_t
>(unit_);
170 patterns[i].bit_width =
static_cast<uint8_t
>(bitwidth_);
171 ConfigureAnalogPad(channel_ids_[i]);
172 channel_ready_[i] =
false;
173 latest_values_[i] = 0.0f;
177 adc_continuous_config_t config = {};
178 config.pattern_num = num_channels_;
179 config.adc_pattern = patterns.data();
180 config.sample_freq_hz = sample_freq;
182 (unit_ == ADC_UNIT_2) ? ADC_CONV_SINGLE_UNIT_2 : ADC_CONV_SINGLE_UNIT_1;
183 config.format = ResolveContinuousFormat();
184 if (adc_continuous_config(continuous_handle_, &config) != ESP_OK)
186 return ContinuousInitResult::FAILED;
189 if (adc_continuous_start(continuous_handle_) != ESP_OK)
191 return ContinuousInitResult::FAILED;
194 continuous_frame_size_ = frame_size;
195 continuous_prime_timeout_ms_ =
196 ((1000U *
static_cast<uint32_t
>(num_channels_) * 2U) / sample_freq) + 5U;
197 if (continuous_prime_timeout_ms_ < 5U)
199 continuous_prime_timeout_ms_ = 5U;
201 if (continuous_prime_timeout_ms_ > 50U)
203 continuous_prime_timeout_ms_ = 50U;
206 backend_ = Backend::CONTINUOUS_DMA;
207 DrainContinuousFrames(continuous_prime_timeout_ms_);
208 return ContinuousInitResult::STARTED;
213ESP32ADC::ContinuousInitResult ESP32ADC::InitContinuous(uint32_t,
size_t)
215 return ContinuousInitResult::UNSUPPORTED;