arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
AnalogDriverESP32V2.h
1#pragma once
2
3#include "AudioToolsConfig.h"
4
5#if defined(ESP32) && defined(USE_ANALOG) && \
6 ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) || defined(DOXYGEN)
7
8#ifdef ARDUINO
9 #ifndef perimanClearPinBus
10 #define perimanClearPinBus(p) perimanSetPinBus(p, ESP32_BUS_TYPE_INIT, NULL)
11 #endif
12#endif
13
14#include "AudioTools/CoreAudio/AudioAnalog/AnalogDriverBase.h"
15#include "AudioTools/CoreAudio/AudioAnalog/AnalogConfigESP32V1.h"
16#include "AudioTools/CoreAudio/AudioStreams.h"
17#include "AudioTools/CoreAudio/AudioStreamsConverter.h"
18
19namespace audio_tools {
20
31public:
34
37 end();
38 }
39
43 TRACEI();
44 bool result = true;
45 this->cfg = cfg;
46
47 switch (cfg.rx_tx_mode) {
48 case TX_MODE:
49 if (!setup_tx()) return false;
50 // convert to 16 bits
51 if (!converter.begin(cfg, 16)) {
52 LOGE("converter");
53 return false;
54 }
55 active_tx = true;
56 break;
57 case RX_MODE:
58 if (!setup_rx()) return false;
59 active_rx = true;
60 break;
61 default:
62 LOGE( "Unsupported MODE: %d", cfg.rx_tx_mode);
63 return false;
64 }
65
66 active = true;
67 return active;
68 }
69
72 void end() override {
73 TRACEI();
74 if (active_tx) {
75 cleanup_tx();
76 }
77 if (active_rx) {
78 cleanup_rx();
79 }
80
81 converter.end();
82
83 active_tx = false;
84 active_rx = false;
85 active = false;
86 }
87
88 // Writes the data to the Digital to Analog Converter
89 // ----------------------------------------------------------
90 size_t write(const uint8_t *src, size_t size_bytes) override {
91 // TRACED();
92 // convert any format to int16_t
93 return converter.write(src, size_bytes);
94 }
95
96 // Reads data from DMA buffer of the Analog to Digital Converter
97 // ----------------------------------------------------------
98 size_t readBytes(uint8_t *dest, size_t size_bytes) override {
99 TRACED();
100 // Use the IO16Bit class for reading
101 return io.readBytes(dest, size_bytes);
102 }
103
104 // How much data will there be available after reading ADC buffer
105 // ----------------------------------------------------------
106 int available() override {
107 return active_rx ? (uint32_t)(cfg.buffer_size * sizeof(int16_t)) : 0;
108 }
109
110protected:
111
112 adc_continuous_handle_t adc_handle = nullptr;
113 adc_cali_handle_t adc_cali_handle = nullptr;
114 AnalogConfigESP32V1 cfg;
115 bool active = false;
116 bool active_tx = false;
117 bool active_rx = false;
118 ConverterAutoCenter auto_center;
119 #ifdef HAS_ESP32_DAC
120 dac_continuous_handle_t dac_handle = nullptr;
121 #endif
122
123
124 // 16Bit Audiostream for ESP32
125 // ----------------------------------------------------------
126 class IO16Bit : public AudioStream {
127 public:
128 IO16Bit(AnalogDriverESP32V2 *driver) { self = driver; }
129
131 size_t write(const uint8_t *src, size_t size_bytes) override {
132 // TRACED();
133#ifdef HAS_ESP32_DAC
134 size_t result = 0;
135 // Convert signed 16-bit to unsigned 8-bit
136 int16_t *data16 = (int16_t *)src;
137 uint8_t *data8 = (uint8_t *)src;
138 int samples = size_bytes / 2;
139
140 // Process data in batches to reduce the number of conversions and writes
141 for (int j = 0; j < samples; j++) {
142 data8[j] = (32768u + data16[j]) >> 8;
143 }
144
145 if (dac_continuous_write(self->dac_handle, data8, samples, &result, self->cfg.timeout) != ESP_OK) {
146 result = 0;
147 }
148 return result * 2;
149#else
150 return 0;
151#endif
152 }
153
155 size_t readBytes(uint8_t *dest, size_t size_bytes) {
156 LOGD("readBytes: %d", (int) size_bytes);
157 size_t result = 0;
158 int channels = self->cfg.channels;
159 assert(channels > 0);
160 sampleIndex.resize(channels);
161 for(int ch=0;ch < channels;ch++){
162 sampleIndex[ch] = 0;
163 }
164 uint16_t *result16 = (uint16_t *)dest; // pointer to the destination buffer
165 int samples_requested = size_bytes / sizeof(int16_t);
166 int samples_requested_per_channel = samples_requested / channels;
167 int buffer_size = samples_requested * sizeof(adc_digi_output_data_t);
168 if (result_data.size() < buffer_size){
169 result_data.resize(buffer_size);
170 }
171
172 int read_size_bytes = buffer_size;
173
174 // read the requested bytes into the buffer
175 while (read_size_bytes > 0){
176 uint32_t bytes_read = 0;
177 if (adc_continuous_read(self->adc_handle, (uint8_t *)result_data.data(), (uint32_t)read_size_bytes, &bytes_read, (uint32_t)self->cfg.timeout) == ESP_OK) {
178 int samples_read = bytes_read / sizeof(adc_digi_output_data_t);
179 LOGD("adc_continuous_read -> %u bytes / %d samples of %d bytes requested", (unsigned)bytes_read, samples_read, (int)(samples_requested * sizeof(adc_digi_output_data_t)));
180
181 // Provide samples to dest
182 for (int i = 0; i < samples_read; i++) {
183 adc_digi_output_data_t *p = (adc_digi_output_data_t*) &result_data[i];
184 ADC_CHANNEL_TYPE chan_num = AUDIO_ADC_GET_CHANNEL(p);
185 ADC_DATA_TYPE sample_value = AUDIO_ADC_GET_DATA(p);
186 int channel = getChannelIdx(chan_num);
187
188 // provide data to dest
189 if (channel >=0 && channel < channels){
190 int idx = channel + (sampleIndex[channel] * channels);
191 LOGI("idx for %d: %d", channel, idx);
192 if(idx < samples_requested){
193 // Provide result in millivolts
194 if (self->cfg.adc_calibration_active) {
195 result16[idx] = getCalibratedValue(sample_value);
196 } else {
197 result16[idx] = sample_value;
198 }
199 // increase index for the actual channel
200 sampleIndex[channel]++;
201 } else {
202 LOGE("Invalid idx: %d / max %d", idx, samples_requested);
203 }
204 } else {
205 LOGE("Invalid channel: %d", channel);
206 }
207 }
209 int samples_available = getMinSamplesForAllChannels(channels);
210 result = samples_available * channels * sizeof(int16_t);
211
213 read_size_bytes = result - size_bytes;
214 if (read_size_bytes > 0)
215 LOGI("read missing samples: %d", samples_requested_per_channel - samples_available);
216 } else {
217 LOGE("adc_continuous_read error");
218 break;
219 }
220 }
221
222
223 // Centering if enabled
224 if (self->cfg.is_auto_center_read) {
225 self->auto_center.convert(dest, result);
226 }
227
228 return result;
229 }
230
231 protected:
232 AnalogDriverESP32V2 *self = nullptr;
233 Vector<uint8_t> result_data{0};
234 Vector<int> sampleIndex{0};
235
236 int getChannelIdx(ADC_CHANNEL_TYPE chan_num){
237 for (int j = 0; j < self->cfg.channels; ++j) {
238 if (self->cfg.adc_channels[j] == chan_num) {
239 return j;
240 }
241 }
242 return -1;
243 }
244
245 int16_t getCalibratedValue(ADC_DATA_TYPE sample_value){
246 int data_milliVolts = 0;
247 int16_t result = 0;
248 auto err = adc_cali_raw_to_voltage(self->adc_cali_handle, sample_value, &data_milliVolts);
249 if (err == ESP_OK) {
250 result = static_cast<int16_t>(data_milliVolts);
251 } else {
252 LOGE("adc_cali_raw_to_voltage error: %d", err);
253 }
254 return result;
255 }
256
257 int getMinSamplesForAllChannels(int channels) {
258 int result = 100000;
259 for (int ch = 0; ch < channels; ch++){
260 if (sampleIndex[ch] < result){
261 result = sampleIndex[ch];
262 }
263 }
264 return result;
265 }
266
267 } io{this};
268
269 NumberFormatConverterStream converter{io};
270
271 // Setup Digital to Analog
272 // ----------------------------------------------------------
273 #ifdef HAS_ESP32_DAC
274 bool setup_tx() {
275 dac_continuous_config_t cont_cfg = {
276 .chan_mask = cfg.channels == 1 ? cfg.dac_mono_channel : DAC_CHANNEL_MASK_ALL,
277 .desc_num = (uint32_t)cfg.buffer_count,
278 .buf_size = (size_t)cfg.buffer_size,
279 .freq_hz = (uint32_t)cfg.sample_rate,
280 .offset = 0,
281 .clk_src = cfg.use_apll ? DAC_DIGI_CLK_SRC_APLL : DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range
282 .chan_mode = cfg.channels == 1 ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER,
283 };
284 // Allocate continuous channels
285 if (dac_continuous_new_channels(&cont_cfg, &dac_handle) != ESP_OK) {
286 LOGE("new_channels");
287 return false;
288 }
289 if (dac_continuous_enable(dac_handle) != ESP_OK) {
290 LOGE("enable");
291 return false;
292 }
293 return true;
294 }
295 #else
296 bool setup_tx() {
297 LOGE("DAC not supported");
298 return false;
299 }
300 #endif
301
302 // Setup Analog to Digital Converter
303 // ----------------------------------------------------------
304 bool setup_rx() {
305 adc_channel_t adc_channel;
306 int io_pin;
307 esp_err_t err;
308
309 // Check the configuration
310 if (!checkADCChannels()) return false;
311 if (!checkADCSampleRate()) return false;
312 if (!checkADCBitWidth()) return false;
313 if (!checkADCBitsPerSample()) return false;
314
315 if (adc_handle != nullptr) {
316 LOGE("adc unit %u continuous is already initialized. Please call end() first!", cfg.adc_unit);
317 return false;
318 }
319
320 #ifdef ARDUINO
321 // Set periman deinit callback
322 // TODO, currently handled in end() method
323
324 // Set the pins/channels to INIT state
325 for (int i = 0; i < cfg.channels; i++) {
326 adc_channel = cfg.adc_channels[i];
327 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
328 if (!perimanClearPinBus(io_pin)) {
329 LOGE("perimanClearPinBus failed!");
330 return false;
331 }
332 }
333 #endif
334
335 // Determine conv_frame_size which must be multiple of SOC_ADC_DIGI_DATA_BYTES_PER_CONV
336 // Old Code
337 uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
338 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
339 uint8_t calc_multiple = conv_frame_size % SOC_ADC_DIGI_DATA_BYTES_PER_CONV;
340 if (calc_multiple != 0) {
341 conv_frame_size = (uint32_t) (conv_frame_size + calc_multiple);
342 }
343 #endif
344
345 // Proposed new Code
346 // uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
347 // #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
348 // uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_DATA_BYTES_PER_CONV
349 // #endif
350
351 // Conversion frame size buffer can't be bigger than 4092 bytes
352 if (conv_frame_size > 4092) {
353 LOGE("buffer_size is too big. Please set lower buffer_size.");
354 return false;
355 } else {
356 LOGI("buffer_size: %u samples, conv_frame_size: %u bytes", cfg.buffer_size, (unsigned)conv_frame_size);
357 }
358
359 // Create adc_continuous handle
360 adc_continuous_handle_cfg_t adc_config;
361 adc_config.max_store_buf_size = (uint32_t)conv_frame_size * 2;
362 adc_config.conv_frame_size = (uint32_t) conv_frame_size;
363#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
364 adc_config.flags.flush_pool = true;
365#endif
366 err = adc_continuous_new_handle(&adc_config, &adc_handle);
367 if (err != ESP_OK) {
368 LOGE("adc_continuous_new_handle failed with error: %d", err);
369 return false;
370 } else {
371 LOGI("adc_continuous_new_handle successful");
372 }
373
374 // Configure the ADC patterns
375 adc_digi_pattern_config_t adc_pattern[cfg.channels] = {};
376 for (int i = 0; i < cfg.channels; i++) {
377 uint8_t ch = cfg.adc_channels[i];
378 adc_pattern[i].atten = (uint8_t) cfg.adc_attenuation;
379 adc_pattern[i].channel = (uint8_t)ch;
380 adc_pattern[i].unit = (uint8_t) cfg.adc_unit;
381 adc_pattern[i].bit_width = (uint8_t) cfg.adc_bit_width;
382 }
383
384 // Configure the ADC
385 adc_continuous_config_t dig_cfg = {
386 .pattern_num = (uint32_t) cfg.channels,
387 .adc_pattern = adc_pattern,
388 .sample_freq_hz = (uint32_t)cfg.sample_rate * cfg.channels,
389 .conv_mode = (adc_digi_convert_mode_t) cfg.adc_conversion_mode,
390 .format = (adc_digi_output_format_t) cfg.adc_output_type,
391 };
392
393 // Log the configuration
394 LOGI("dig_cfg.sample_freq_hz: %u", (unsigned)dig_cfg.sample_freq_hz);
395 LOGI("dig_cfg.conv_mode: %u (1: unit 1, 2: unit 2, 3: both)", dig_cfg.conv_mode);
396 LOGI("dig_cfg.format: %u (0 is type1: [12bit data, 4bit channel])", dig_cfg.format);
397 for (int i = 0; i < cfg.channels; i++) {
398 LOGI("dig_cfg.adc_pattern[%d].atten: %u", i, dig_cfg.adc_pattern[i].atten);
399 LOGI("dig_cfg.adc_pattern[%d].channel: %u", i, dig_cfg.adc_pattern[i].channel);
400 LOGI("dig_cfg.adc_pattern[%d].unit: %u", i, dig_cfg.adc_pattern[i].unit);
401 LOGI("dig_cfg.adc_pattern[%d].bit_width: %u", i, dig_cfg.adc_pattern[i].bit_width);
402 }
403
404 // Initialize ADC
405 err = adc_continuous_config(adc_handle, &dig_cfg);
406 if (err != ESP_OK) {
407 LOGE("adc_continuous_config unsuccessful with error: %d", err);
408 return false;
409 }
410 LOGI("adc_continuous_config successful");
411
412 // Set up optional calibration
413 if (!setupADCCalibration()) {
414 return false;
415 }
416
417 // Attach the pins to the ADC unit
418#ifdef ARDUINO
419 for (int i = 0; i < cfg.channels; i++) {
420 adc_channel = cfg.adc_channels[i];
421 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
422 // perimanSetPinBus: uint8_t pin, peripheral_bus_type_t type, void * bus, int8_t bus_num, int8_t bus_channel
423 if (!perimanSetPinBus(io_pin, ESP32_BUS_TYPE_ADC_CONT, (void *)(cfg.adc_unit + 1), cfg.adc_unit, adc_channel)) {
424 LOGE("perimanSetPinBus to Continuous an ADC Unit %u failed!", cfg.adc_unit);
425 return false;
426 }
427 }
428#endif
429
430 // Start ADC
431 err = adc_continuous_start(adc_handle);
432 if (err != ESP_OK) {
433 LOGE("adc_continuous_start unsuccessful with error: %d", err);
434 return false;
435 }
436
437 // Setup up optimal auto center which puts the avg at 0
438 auto_center.begin(cfg.channels, cfg.bits_per_sample, true);
439
440 LOGI("Setup ADC successful");
441
442 return true;
443 }
444
446 bool cleanup_tx() {
447 bool ok = true;
448#ifdef HAS_ESP32_DAC
449 if (dac_handle==nullptr) return true;
450 if (dac_continuous_disable(dac_handle) != ESP_OK){
451 ok = false;
452 LOGE("dac_continuous_disable failed");
453 }
454 if (dac_continuous_del_channels(dac_handle) != ESP_OK){
455 ok = false;
456 LOGE("dac_continuous_del_channels failed");
457 }
458 dac_handle = nullptr;
459#endif
460 return ok;
461 }
462
463#ifdef ARDUINO
464 // dummy detach: w/o this it's failing
465 static bool adcDetachBus(void *bus) {
466 LOGD("===> adcDetachBus: %d", (int) bus);
467 return true;
468 }
469#endif
470
472 bool cleanup_rx() {
473 if (adc_handle==nullptr) return true;
474 adc_continuous_stop(adc_handle);
475 adc_continuous_deinit(adc_handle);
476 if (cfg.adc_calibration_active) {
477 #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
478 adc_cali_delete_scheme_curve_fitting(adc_cali_handle);
479 #elif !defined(CONFIG_IDF_TARGET_ESP32H2)
480 adc_cali_delete_scheme_line_fitting(adc_cali_handle);
481 #endif
482 }
483
484#ifdef ARDUINO
485 // Set all used pins/channels to INIT state
486 perimanSetBusDeinit(ESP32_BUS_TYPE_ADC_CONT, adcDetachBus);
487 for (int i = 0; i < cfg.channels; i++) {
488 adc_channel_t adc_channel = cfg.adc_channels[i];
489 int io_pin;
490 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
491 if (perimanGetPinBusType(io_pin) == ESP32_BUS_TYPE_ADC_CONT) {
492 if (!perimanClearPinBus(io_pin)) {
493 LOGE("perimanClearPinBus failed!");
494 }
495 }
496 }
497#endif
498 adc_handle = nullptr;
499 return true; // Return true to indicate successful cleanup
500 }
501
504 if ((cfg.adc_bit_width < SOC_ADC_DIGI_MIN_BITWIDTH) ||
505 (cfg.adc_bit_width > SOC_ADC_DIGI_MAX_BITWIDTH)) {
506 LOGE("adc bit width: %u cannot be set, range: %u to %u", cfg.adc_bit_width,
507 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
508 return false;
509 }
510 LOGI("adc bit width: %u, range: %u to %u", cfg.adc_bit_width,
511 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
512 return true;
513 }
514
517 int io_pin;
518 adc_channel_t adc_channel;
519
520 int max_channels = sizeof(cfg.adc_channels) / sizeof(adc_channel_t);
521 if (cfg.channels > max_channels) {
522 LOGE("number of channels: %d, max: %d", cfg.channels, max_channels);
523 return false;
524 }
525 LOGI("channels: %d, max: %d", cfg.channels, max_channels);
526
527 // Lets make sure the adc channels are available
528 for (int i = 0; i < cfg.channels; i++) {
529 adc_channel = cfg.adc_channels[i];
530 auto err = adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
531 if (err != ESP_OK) {
532 LOGE("ADC channel %u is not available on ADC unit %u", adc_channel, cfg.adc_unit);
533 return false;
534 } else {
535 LOGI("ADC channel %u is on pin %u", adc_channel, io_pin);
536 }
537 }
538 return true;
539 }
540
543 LOGI("sample rate (audio): %d", cfg.sample_rate);
544 int sample_rate = cfg.sample_rate * cfg.channels;
545 if ((sample_rate < SOC_ADC_SAMPLE_FREQ_THRES_LOW) ||
546 (sample_rate > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)) {
547 LOGE("sample rate eff: %u can not be set, range: %u to %u", sample_rate,
548 SOC_ADC_SAMPLE_FREQ_THRES_LOW, SOC_ADC_SAMPLE_FREQ_THRES_HIGH);
549 return false;
550 }
551 LOGI("sample rate eff: %u, range: %u to %u", sample_rate,
552 SOC_ADC_SAMPLE_FREQ_THRES_LOW, SOC_ADC_SAMPLE_FREQ_THRES_HIGH);
553
554 return true;
555 }
556
559 int supported_bits = 16; // for the time being we support only 16 bits!
560
561 // calculated default value if nothing is specified
562 if (cfg.bits_per_sample == 0) {
563 cfg.bits_per_sample = supported_bits;
564 LOGI("bits per sample set to: %d", cfg.bits_per_sample);
565 }
566
567 // check bits_per_sample
568 if (cfg.bits_per_sample != supported_bits) {
569 LOGE("bits per sample: error. It should be: %d but is %d",
570 supported_bits, cfg.bits_per_sample);
571 return false;
572 }
573 LOGI("bits per sample: %d", cfg.bits_per_sample);
574 return true;
575 }
576
579 if (!cfg.adc_calibration_active)
580 return true;
581
582 // Initialize ADC calibration handle
583 // Calibration is applied to an ADC unit (not per channel).
584
585 // setup calibration only when requested
586 if (adc_cali_handle == NULL) {
587 #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
588 // curve fitting is preferred
589 adc_cali_curve_fitting_config_t cali_config;
590 cali_config.unit_id = cfg.adc_unit;
591 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
592 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
593 auto err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle);
594 #elif !defined(CONFIG_IDF_TARGET_ESP32H2)
595 // line fitting is the alternative
596 adc_cali_line_fitting_config_t cali_config;
597 cali_config.unit_id = cfg.adc_unit;
598 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
599 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
600 auto err = adc_cali_create_scheme_line_fitting(&cali_config, &adc_cali_handle);
601 #endif
602 if (err != ESP_OK) {
603 LOGE("creating calibration handle failed for ADC%d with atten %d and bitwidth %d",
604 cfg.adc_unit, cfg.adc_attenuation, cfg.adc_bit_width);
605 return false;
606 } else {
607 LOGI("enabled calibration for ADC%d with atten %d and bitwidth %d",
608 cfg.adc_unit, cfg.adc_attenuation, cfg.adc_bit_width);
609 }
610 }
611 return true;
612 }
613
614};
615
618
619} // namespace audio_tools
620
621#endif
ESP32 specific configuration for i2s input via adc using the adc_continuous API.
Definition AnalogConfigESP32V1.h:102
Definition AnalogDriverBase.h:13
Definition AnalogDriverESP32V2.h:126
size_t write(const uint8_t *src, size_t size_bytes) override
Write int16_t data to the Digital to Analog Converter.
Definition AnalogDriverESP32V2.h:131
size_t readBytes(uint8_t *dest, size_t size_bytes)
Read int16_t data from ADC.
Definition AnalogDriverESP32V2.h:155
AnalogAudioStream: A very fast DAC using DMA using the new dac_continuous API. This implementation as...
Definition AnalogDriverESP32V2.h:30
bool checkADCBitWidth()
Definition AnalogDriverESP32V2.h:503
virtual ~AnalogDriverESP32V2()
Destructor.
Definition AnalogDriverESP32V2.h:36
bool checkADCChannels()
Definition AnalogDriverESP32V2.h:516
void end() override
Definition AnalogDriverESP32V2.h:72
bool cleanup_tx()
Cleanup dac.
Definition AnalogDriverESP32V2.h:446
bool cleanup_rx()
Cleanup Analog to Digital Converter.
Definition AnalogDriverESP32V2.h:472
bool begin(AnalogConfigESP32V1 cfg)
Definition AnalogDriverESP32V2.h:42
bool setupADCCalibration()
Definition AnalogDriverESP32V2.h:578
bool checkADCSampleRate()
Definition AnalogDriverESP32V2.h:542
bool checkADCBitsPerSample()
Definition AnalogDriverESP32V2.h:558
AnalogDriverESP32V2()=default
Default constructor.
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:119
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
AnalogDriverArduino AnalogDriver
AnalogAudioStream.
Definition AnalogDriverArduino.h:48
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57