libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::ESP32ADC Class Reference
Collaboration diagram for LibXR::ESP32ADC:
[legend]

Data Structures

class  Channel
 

Public Types

enum class  ContinuousInitResult : uint8_t { STARTED = 0 , UNSUPPORTED , FAILED }
 

Public Member Functions

 ESP32ADC (adc_unit_t unit, const adc_channel_t *channels, uint8_t num_channels, uint32_t freq=SOC_ADC_SAMPLE_FREQ_THRES_LOW, adc_atten_t attenuation=ADC_ATTEN_DB_12, adc_bitwidth_t bitwidth=static_cast< adc_bitwidth_t >(SOC_ADC_DIGI_MAX_BITWIDTH), float reference_voltage=3.3f, size_t dma_buf_size=256)
 
ChannelGetChannel (uint8_t idx)
 
float ReadChannel (uint8_t idx)
 

Private Types

enum class  Backend : uint8_t { NONE = 0 , CONTINUOUS_DMA , ONESHOT }
 

Private Member Functions

float Normalize (float raw) const
 
bool IsValidChannel (adc_channel_t channel) const
 
void ConfigureAnalogPad (adc_channel_t channel) const
 
bool InitCalibration ()
 
bool InitOneshot ()
 
float RawToVoltage (uint8_t idx, uint16_t raw) const
 

Static Private Member Functions

static adc_bitwidth_t ResolveBitwidth (adc_bitwidth_t bitwidth)
 
static uint32_t ClampSampleFreq (uint32_t freq)
 
static uint32_t AlignUp (uint32_t value, uint32_t align)
 

Private Attributes

Channelchannels_ = nullptr
 
adc_channel_t * channel_ids_ = nullptr
 
uint8_t channel_idx_map_ [SOC_ADC_MAX_CHANNEL_NUM] = {}
 
bool * channel_ready_ = nullptr
 
float * latest_values_ = nullptr
 
uint16_t * latest_raw_ = nullptr
 
adc_cali_handle_t cali_handles_ [SOC_ADC_MAX_CHANNEL_NUM] = {}
 
adc_unit_t unit_
 
uint8_t num_channels_
 
adc_atten_t attenuation_
 
adc_bitwidth_t bitwidth_
 
float reference_voltage_
 
uint16_t max_raw_
 
Backend backend_ = Backend::NONE
 
adc_oneshot_hal_ctx_t * oneshot_hal_ = nullptr
 
bool oneshot_inited_ = false
 
bool valid_ = false
 

Static Private Attributes

static constexpr uint8_t kInvalidChannelIdx = 0xFFU
 

Detailed Description

Definition at line 23 of file esp_adc.hpp.

Member Enumeration Documentation

◆ Backend

enum class LibXR::ESP32ADC::Backend : uint8_t
strongprivate

Definition at line 63 of file esp_adc.hpp.

64 {
65 NONE = 0,
66 CONTINUOUS_DMA,
67 ONESHOT,
68 };

◆ ContinuousInitResult

enum class LibXR::ESP32ADC::ContinuousInitResult : uint8_t
strong

Definition at line 42 of file esp_adc.hpp.

43 {
44 STARTED = 0,
45 UNSUPPORTED,
46 FAILED,
47 };
@ FAILED
操作失败 | Operation failed

Constructor & Destructor Documentation

◆ ESP32ADC()

LibXR::ESP32ADC::ESP32ADC ( adc_unit_t unit,
const adc_channel_t * channels,
uint8_t num_channels,
uint32_t freq = SOC_ADC_SAMPLE_FREQ_THRES_LOW,
adc_atten_t attenuation = ADC_ATTEN_DB_12,
adc_bitwidth_t bitwidth = static_cast<adc_bitwidth_t>(SOC_ADC_DIGI_MAX_BITWIDTH),
float reference_voltage = 3.3f,
size_t dma_buf_size = 256 )

Definition at line 54 of file esp_adc.cpp.

57 : unit_(unit),
58 num_channels_(num_channels),
59 attenuation_(attenuation),
60 bitwidth_(ResolveBitwidth(bitwidth)),
61 reference_voltage_(reference_voltage),
62 max_raw_((1U << static_cast<uint8_t>(bitwidth_)) - 1U)
63{
64 ASSERT(channels != nullptr);
65 ASSERT(num_channels_ > 0U);
66 ASSERT(reference_voltage_ > 0.0f);
67 ASSERT(max_raw_ != 0U);
68 ASSERT(num_channels_ <= SOC_ADC_MAX_CHANNEL_NUM);
69 if ((channels == nullptr) || (num_channels_ == 0U) || (reference_voltage_ <= 0.0f) ||
70 (max_raw_ == 0U) || (num_channels_ > SOC_ADC_MAX_CHANNEL_NUM))
71 {
72 return;
73 }
74
75 channels_ = new (std::nothrow) Channel[num_channels_];
76 channel_ids_ = new (std::nothrow) adc_channel_t[num_channels_];
77 channel_ready_ = new (std::nothrow) bool[num_channels_];
78 latest_values_ = new (std::nothrow) float[num_channels_];
79 latest_raw_ = new (std::nothrow) uint16_t[num_channels_];
80 ASSERT(channels_ != nullptr);
81 ASSERT(channel_ids_ != nullptr);
82 ASSERT(channel_ready_ != nullptr);
83 ASSERT(latest_values_ != nullptr);
84 ASSERT(latest_raw_ != nullptr);
85 if ((channels_ == nullptr) || (channel_ids_ == nullptr) ||
86 (channel_ready_ == nullptr) || (latest_values_ == nullptr) ||
87 (latest_raw_ == nullptr))
88 {
89 ASSERT(false);
90 return;
91 }
92
93 for (uint8_t i = 0; i < SOC_ADC_MAX_CHANNEL_NUM; ++i)
94 {
95 channel_idx_map_[i] = kInvalidChannelIdx;
96 cali_handles_[i] = nullptr;
97 }
98
99 for (uint8_t i = 0; i < num_channels_; ++i)
100 {
101 ASSERT(IsValidChannel(channels[i]));
102 const uint8_t ch = static_cast<uint8_t>(channels[i]);
103 ASSERT(channel_idx_map_[ch] == kInvalidChannelIdx);
104 if (!IsValidChannel(channels[i]) || (channel_idx_map_[ch] != kInvalidChannelIdx))
105 {
106 return;
107 }
108
109 channels_[i] = Channel(this, i, ch);
110 channel_ids_[i] = channels[i];
111 channel_idx_map_[ch] = i;
112 channel_ready_[i] = false;
113 latest_values_[i] = 0.0f;
114 latest_raw_[i] = 0U;
115 }
116
117#if defined(CONFIG_IDF_TARGET_ESP32) && CONFIG_IDF_TARGET_ESP32 && \
118 defined(CONFIG_ESP_WIFI_ENABLED) && CONFIG_ESP_WIFI_ENABLED
119 if (unit_ == ADC_UNIT_2)
120 {
121 wifi_mode_t wifi_mode = WIFI_MODE_NULL;
122 const esp_err_t wifi_mode_err = esp_wifi_get_mode(&wifi_mode);
123 const bool wifi_active = (wifi_mode_err == ESP_OK) && (wifi_mode != WIFI_MODE_NULL);
124 ASSERT(!wifi_active);
125 if (wifi_active)
126 {
127 return;
128 }
129 }
130#endif
131
132 (void)InitCalibration();
133
134 const ContinuousInitResult cont_ans = InitContinuous(freq, dma_buf_size);
135 if (cont_ans == ContinuousInitResult::STARTED)
136 {
137 valid_ = true;
138 return;
139 }
140
141 if (cont_ans == ContinuousInitResult::FAILED)
142 {
143 ASSERT(false);
144 return;
145 }
146
147 const bool oneshot_ok = InitOneshot();
148 ASSERT(oneshot_ok);
149 if (!oneshot_ok)
150 {
151 return;
152 }
153
154 valid_ = true;
155}

Member Function Documentation

◆ AlignUp()

uint32_t LibXR::ESP32ADC::AlignUp ( uint32_t value,
uint32_t align )
staticprivate

Definition at line 368 of file esp_adc.cpp.

369{
370 if (align == 0U)
371 {
372 return value;
373 }
374 return (value + align - 1U) / align * align;
375}

◆ ClampSampleFreq()

uint32_t LibXR::ESP32ADC::ClampSampleFreq ( uint32_t freq)
staticprivate

Definition at line 355 of file esp_adc.cpp.

356{
357 if (freq < SOC_ADC_SAMPLE_FREQ_THRES_LOW)
358 {
359 return SOC_ADC_SAMPLE_FREQ_THRES_LOW;
360 }
361 if (freq > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)
362 {
363 return SOC_ADC_SAMPLE_FREQ_THRES_HIGH;
364 }
365 return freq;
366}

◆ ConfigureAnalogPad()

void LibXR::ESP32ADC::ConfigureAnalogPad ( adc_channel_t channel) const
private

Definition at line 384 of file esp_adc.cpp.

385{
386 int io_num = -1;
387 if ((adc_channel_to_io(unit_, channel, &io_num) == ESP_OK) && (io_num >= 0))
388 {
389 (void)gpio_config_as_analog(static_cast<gpio_num_t>(io_num));
390 }
391}

◆ GetChannel()

ESP32ADC::Channel & LibXR::ESP32ADC::GetChannel ( uint8_t idx)

Definition at line 157 of file esp_adc.cpp.

158{
159 ASSERT(idx < num_channels_);
160 return channels_[idx];
161}

◆ InitCalibration()

bool LibXR::ESP32ADC::InitCalibration ( )
private

Definition at line 271 of file esp_adc.cpp.

272{
273#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
274 bool calibrated = false;
275
276 for (uint8_t i = 0; i < num_channels_; ++i)
277 {
278 adc_cali_curve_fitting_config_t config = {};
279 config.unit_id = unit_;
280 config.chan = channel_ids_[i];
281 config.atten = attenuation_;
282 config.bitwidth = bitwidth_;
283
284 adc_cali_handle_t handle = nullptr;
285 const esp_err_t err = adc_cali_create_scheme_curve_fitting(&config, &handle);
286 ASSERT((err == ESP_OK) || (err == ESP_ERR_NOT_SUPPORTED) ||
287 (err == ESP_ERR_INVALID_ARG) || (err == ESP_ERR_NO_MEM));
288 if (err != ESP_OK)
289 {
290 continue;
291 }
292
293 cali_handles_[i] = handle;
294 calibrated = true;
295 }
296
297 return calibrated;
298#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
299 adc_cali_line_fitting_config_t config = {};
300 config.unit_id = unit_;
301 config.atten = attenuation_;
302 config.bitwidth = bitwidth_;
303#if CONFIG_IDF_TARGET_ESP32
304 config.default_vref = kDefaultLineFittingVrefMv;
305#endif
306
307 adc_cali_handle_t handle = nullptr;
308 const esp_err_t err = adc_cali_create_scheme_line_fitting(&config, &handle);
309 ASSERT((err == ESP_OK) || (err == ESP_ERR_NOT_SUPPORTED) ||
310 (err == ESP_ERR_INVALID_ARG) || (err == ESP_ERR_NO_MEM));
311 if (err != ESP_OK)
312 {
313 return false;
314 }
315
316 for (uint8_t i = 0; i < num_channels_; ++i)
317 {
318 cali_handles_[i] = handle;
319 }
320
321 return true;
322#else
323 return false;
324#endif
325}

◆ InitOneshot()

bool LibXR::ESP32ADC::InitOneshot ( )
private

Definition at line 21 of file esp_adc_oneshot.cpp.

22{
23 ASSERT(oneshot_hal_ == nullptr);
24 if (oneshot_hal_ != nullptr)
25 {
26 return false;
27 }
28
29 oneshot_hal_ = new (std::nothrow) adc_oneshot_hal_ctx_t{};
30 ASSERT(oneshot_hal_ != nullptr);
31 if (oneshot_hal_ == nullptr)
32 {
33 return false;
34 }
35
36 adc_oneshot_hal_cfg_t unit_cfg = {};
37 unit_cfg.unit = unit_;
38 unit_cfg.work_mode = ADC_HAL_SINGLE_READ_MODE;
39#if SOC_ADC_RTC_CTRL_SUPPORTED
40 unit_cfg.clk_src = ADC_RTC_CLK_SRC_DEFAULT;
41#else
42 unit_cfg.clk_src = ADC_DIGI_CLK_SRC_DEFAULT;
43#endif
44 unit_cfg.clk_src_freq_hz = 0U;
45
46#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
47 if (esp_clk_tree_src_get_freq_hz(static_cast<soc_module_clk_t>(unit_cfg.clk_src),
48 ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED,
49 &unit_cfg.clk_src_freq_hz) != ESP_OK)
50 {
51 return false;
52 }
53 adc_apb_periph_claim();
54#endif
55
56 adc_oneshot_hal_init(oneshot_hal_, &unit_cfg);
57 sar_periph_ctrl_adc_oneshot_power_acquire();
58 oneshot_inited_ = true;
59
60#if SOC_ADC_CALIBRATION_V1_SUPPORTED
61 portENTER_CRITICAL(&rtc_spinlock);
62 adc_hal_calibration_init(unit_);
63 adc_set_hw_calibration_code(unit_, attenuation_);
64 portEXIT_CRITICAL(&rtc_spinlock);
65#endif
66
67 adc_oneshot_hal_chan_cfg_t chan_cfg = {};
68 chan_cfg.atten = attenuation_;
69 chan_cfg.bitwidth = bitwidth_;
70
71 for (uint8_t i = 0; i < num_channels_; ++i)
72 {
73 ASSERT(IsValidChannel(channel_ids_[i]));
74 if (!IsValidChannel(channel_ids_[i]))
75 {
76 return false;
77 }
78
79 portENTER_CRITICAL(&rtc_spinlock);
80 adc_oneshot_hal_channel_config(oneshot_hal_, &chan_cfg, channel_ids_[i]);
81 portEXIT_CRITICAL(&rtc_spinlock);
82
83 ConfigureAnalogPad(channel_ids_[i]);
84 channel_ready_[i] = false;
85 latest_values_[i] = 0.0f;
86 latest_raw_[i] = 0U;
87 }
88
89 backend_ = Backend::ONESHOT;
90 return true;
91}

◆ IsValidChannel()

bool LibXR::ESP32ADC::IsValidChannel ( adc_channel_t channel) const
private

Definition at line 377 of file esp_adc.cpp.

378{
379 const int channel_count = SOC_ADC_CHANNEL_NUM(static_cast<int>(unit_));
380 const int channel_num = static_cast<int>(channel);
381 return (channel_count > 0) && (channel_num >= 0) && (channel_num < channel_count);
382}

◆ Normalize()

float LibXR::ESP32ADC::Normalize ( float raw) const
private

Definition at line 350 of file esp_adc.cpp.

351{
352 return (raw / static_cast<float>(max_raw_)) * reference_voltage_;
353}

◆ RawToVoltage()

float LibXR::ESP32ADC::RawToVoltage ( uint8_t idx,
uint16_t raw ) const
private

Definition at line 327 of file esp_adc.cpp.

328{
329 ASSERT(idx < num_channels_);
330 if (idx >= num_channels_)
331 {
332 return 0.f;
333 }
334
335 if (cali_handles_[idx] != nullptr)
336 {
337 int voltage_mv = 0;
338 const esp_err_t err =
339 adc_cali_raw_to_voltage(cali_handles_[idx], static_cast<int>(raw), &voltage_mv);
340 ASSERT(err == ESP_OK);
341 if (err == ESP_OK)
342 {
343 return static_cast<float>(voltage_mv) / 1000.0f;
344 }
345 }
346
347 return Normalize(static_cast<float>(raw));
348}

◆ ReadChannel()

float LibXR::ESP32ADC::ReadChannel ( uint8_t idx)

Definition at line 163 of file esp_adc.cpp.

164{
165 ASSERT(valid_);
166 ASSERT(idx < num_channels_);
167 if (!valid_ || (idx >= num_channels_))
168 {
169 return 0.f;
170 }
171
172 if (backend_ == Backend::CONTINUOUS_DMA)
173 {
174#if SOC_ADC_DIG_CTRL_SUPPORTED && SOC_ADC_DMA_SUPPORTED
175 if (!channel_ready_[idx])
176 {
177 DrainContinuousFrames(continuous_prime_timeout_ms_);
178 }
179 else
180 {
181 DrainContinuousFrames(0U);
182 }
183#endif
184 ASSERT(channel_ready_[idx]);
185 return latest_values_[idx];
186 }
187
188 ASSERT(backend_ == Backend::ONESHOT);
189 ASSERT(oneshot_inited_ && (oneshot_hal_ != nullptr));
190 if (!oneshot_inited_ || (oneshot_hal_ == nullptr))
191 {
192 return 0.f;
193 }
194
195 const esp_err_t lock_err = adc_lock_try_acquire(unit_);
196 ASSERT(lock_err == ESP_OK);
197 if (lock_err != ESP_OK)
198 {
199 return 0.f;
200 }
201
202 int raw = 0;
203 bool converted = false;
204 bool clk_src_enabled = false;
205
206 portENTER_CRITICAL(&rtc_spinlock);
207
208#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
209 const esp_err_t clk_on =
210 esp_clk_tree_enable_src(static_cast<soc_module_clk_t>(oneshot_hal_->clk_src), true);
211 ASSERT(clk_on == ESP_OK);
212 clk_src_enabled = (clk_on == ESP_OK);
213#else
214 clk_src_enabled = true;
215#endif
216
217 if (clk_src_enabled)
218 {
219 ANALOG_CLOCK_ENABLE();
220 adc_oneshot_hal_setup(oneshot_hal_, channel_ids_[idx]);
221#if SOC_ADC_CALIBRATION_V1_SUPPORTED
222 adc_set_hw_calibration_code(unit_, attenuation_);
223#endif
224 converted = adc_oneshot_hal_convert(oneshot_hal_, &raw);
225 ANALOG_CLOCK_DISABLE();
226 }
227
228#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
229 if (clk_src_enabled)
230 {
231 const esp_err_t clk_off = esp_clk_tree_enable_src(
232 static_cast<soc_module_clk_t>(oneshot_hal_->clk_src), false);
233 ASSERT(clk_off == ESP_OK);
234 if (clk_off != ESP_OK)
235 {
236 converted = false;
237 }
238 }
239#endif
240
241 portEXIT_CRITICAL(&rtc_spinlock);
242
243 const esp_err_t unlock_err = adc_lock_release(unit_);
244 ASSERT(unlock_err == ESP_OK);
245 if (unlock_err != ESP_OK)
246 {
247 return 0.f;
248 }
249
250 ASSERT(converted);
251 if (!converted)
252 {
253 return 0.f;
254 }
255
256 latest_raw_[idx] = static_cast<uint16_t>(raw);
257 latest_values_[idx] = RawToVoltage(idx, latest_raw_[idx]);
258 channel_ready_[idx] = true;
259 return latest_values_[idx];
260}

◆ ResolveBitwidth()

adc_bitwidth_t LibXR::ESP32ADC::ResolveBitwidth ( adc_bitwidth_t bitwidth)
staticprivate

Definition at line 262 of file esp_adc.cpp.

263{
264 if (bitwidth == ADC_BITWIDTH_DEFAULT)
265 {
266 return static_cast<adc_bitwidth_t>(SOC_ADC_RTC_MAX_BITWIDTH);
267 }
268 return bitwidth;
269}

Field Documentation

◆ attenuation_

adc_atten_t LibXR::ESP32ADC::attenuation_
private

Definition at line 98 of file esp_adc.hpp.

◆ backend_

Backend LibXR::ESP32ADC::backend_ = Backend::NONE
private

Definition at line 104 of file esp_adc.hpp.

◆ bitwidth_

adc_bitwidth_t LibXR::ESP32ADC::bitwidth_
private

Definition at line 99 of file esp_adc.hpp.

◆ cali_handles_

adc_cali_handle_t LibXR::ESP32ADC::cali_handles_[SOC_ADC_MAX_CHANNEL_NUM] = {}
private

Definition at line 94 of file esp_adc.hpp.

94{};

◆ channel_ids_

adc_channel_t* LibXR::ESP32ADC::channel_ids_ = nullptr
private

Definition at line 88 of file esp_adc.hpp.

◆ channel_idx_map_

uint8_t LibXR::ESP32ADC::channel_idx_map_[SOC_ADC_MAX_CHANNEL_NUM] = {}
private

Definition at line 89 of file esp_adc.hpp.

89{};

◆ channel_ready_

bool* LibXR::ESP32ADC::channel_ready_ = nullptr
private

Definition at line 90 of file esp_adc.hpp.

◆ channels_

Channel* LibXR::ESP32ADC::channels_ = nullptr
private

Definition at line 87 of file esp_adc.hpp.

◆ kInvalidChannelIdx

uint8_t LibXR::ESP32ADC::kInvalidChannelIdx = 0xFFU
staticconstexprprivate

Definition at line 102 of file esp_adc.hpp.

◆ latest_raw_

uint16_t* LibXR::ESP32ADC::latest_raw_ = nullptr
private

Definition at line 92 of file esp_adc.hpp.

◆ latest_values_

float* LibXR::ESP32ADC::latest_values_ = nullptr
private

Definition at line 91 of file esp_adc.hpp.

◆ max_raw_

uint16_t LibXR::ESP32ADC::max_raw_
private

Definition at line 101 of file esp_adc.hpp.

◆ num_channels_

uint8_t LibXR::ESP32ADC::num_channels_
private

Definition at line 97 of file esp_adc.hpp.

◆ oneshot_hal_

adc_oneshot_hal_ctx_t* LibXR::ESP32ADC::oneshot_hal_ = nullptr
private

Definition at line 105 of file esp_adc.hpp.

◆ oneshot_inited_

bool LibXR::ESP32ADC::oneshot_inited_ = false
private

Definition at line 106 of file esp_adc.hpp.

◆ reference_voltage_

float LibXR::ESP32ADC::reference_voltage_
private

Definition at line 100 of file esp_adc.hpp.

◆ unit_

adc_unit_t LibXR::ESP32ADC::unit_
private

Definition at line 96 of file esp_adc.hpp.

◆ valid_

bool LibXR::ESP32ADC::valid_ = false
private

Definition at line 107 of file esp_adc.hpp.


The documentation for this class was generated from the following files: