libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
esp_adc_continuous.cpp
1#include <array>
2#include <new>
3
4#include "esp_adc.hpp"
5
6namespace LibXR
7{
8
9#if SOC_ADC_DIG_CTRL_SUPPORTED && SOC_ADC_DMA_SUPPORTED
10
11bool ESP32ADC::IsDigiUnitSupported(adc_unit_t unit)
12{
13 return SOC_ADC_DIG_SUPPORTED_UNIT(static_cast<int>(unit)) != 0;
14}
15
16adc_digi_output_format_t ESP32ADC::ResolveContinuousFormat()
17{
18#if SOC_ADC_DIGI_RESULT_BYTES == 2
19 return ADC_DIGI_OUTPUT_FORMAT_TYPE1;
20#else
21 return ADC_DIGI_OUTPUT_FORMAT_TYPE2;
22#endif
23}
24
25void ESP32ADC::DrainContinuousFrames(uint32_t timeout_ms)
26{
27 if ((backend_ != Backend::CONTINUOUS_DMA) || (continuous_handle_ == nullptr) ||
28 (continuous_read_buf_ == nullptr) || (continuous_parsed_buf_ == nullptr) ||
29 (continuous_frame_size_ == 0U))
30 {
31 return;
32 }
33
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;
38
39 while (true)
40 {
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);
45 first_read = false;
46
47 if (read_err == ESP_ERR_TIMEOUT)
48 {
49 break;
50 }
51
52 ASSERT(read_err == ESP_OK);
53 if (read_err != ESP_OK)
54 {
55 if (read_err == ESP_ERR_INVALID_STATE)
56 {
57 (void)adc_continuous_flush_pool(continuous_handle_);
58 }
59 break;
60 }
61
62 if (out_length == 0U)
63 {
64 break;
65 }
66
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)
73 {
74 break;
75 }
76
77 for (uint32_t i = 0; i < parsed_count; ++i)
78 {
79 const adc_continuous_data_t& sample = continuous_parsed_buf_[i];
80 if (!sample.valid || (sample.unit != unit_))
81 {
82 continue;
83 }
84
85 const uint8_t sample_channel = static_cast<uint8_t>(sample.channel);
86 if (sample_channel >= SOC_ADC_MAX_CHANNEL_NUM)
87 {
88 continue;
89 }
90
91 const uint8_t sample_idx = channel_idx_map_[sample_channel];
92 if ((sample_idx == kInvalidChannelIdx) || (sample_idx >= num_channels_))
93 {
94 continue;
95 }
96
97 sums[sample_idx] += sample.raw_data;
98 counts[sample_idx] += 1U;
99 any_sample = true;
100 }
101 }
102
103 if (!any_sample)
104 {
105 return;
106 }
107
108 for (uint8_t i = 0; i < num_channels_; ++i)
109 {
110 if (counts[i] == 0U)
111 {
112 continue;
113 }
114
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;
119 }
120}
121
122ESP32ADC::ContinuousInitResult ESP32ADC::InitContinuous(uint32_t freq,
123 size_t dma_buf_size)
124{
125 if (!IsDigiUnitSupported(unit_))
126 {
127 return ContinuousInitResult::UNSUPPORTED;
128 }
129
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))
136 ? dma_buf_size
137 : frame_size * 5U),
138 SOC_ADC_DIGI_DATA_BYTES_PER_CONV);
139 const uint32_t parsed_capacity = frame_size / SOC_ADC_DIGI_RESULT_BYTES;
140
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))
145 {
146 return ContinuousInitResult::FAILED;
147 }
148
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)
154 {
155 return ContinuousInitResult::FAILED;
156 }
157
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())
161 {
162 return ContinuousInitResult::FAILED;
163 }
164
165 for (uint8_t i = 0; i < num_channels_; ++i)
166 {
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;
174 latest_raw_[i] = 0U;
175 }
176
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;
181 config.conv_mode =
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)
185 {
186 return ContinuousInitResult::FAILED;
187 }
188
189 if (adc_continuous_start(continuous_handle_) != ESP_OK)
190 {
191 return ContinuousInitResult::FAILED;
192 }
193
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)
198 {
199 continuous_prime_timeout_ms_ = 5U;
200 }
201 if (continuous_prime_timeout_ms_ > 50U)
202 {
203 continuous_prime_timeout_ms_ = 50U;
204 }
205
206 backend_ = Backend::CONTINUOUS_DMA;
207 DrainContinuousFrames(continuous_prime_timeout_ms_);
208 return ContinuousInitResult::STARTED;
209}
210
211#else
212
213ESP32ADC::ContinuousInitResult ESP32ADC::InitContinuous(uint32_t, size_t)
214{
215 return ContinuousInitResult::UNSUPPORTED;
216}
217
218#endif
219
220} // namespace LibXR
LibXR 命名空间
Definition ch32_can.hpp:14