arduino-audio-tools
Loading...
Searching...
No Matches
AnalogDriverESP32V1.h
Go to the documentation of this file.
1#pragma once
2
3#include "AudioToolsConfig.h"
4
5#if (defined(ESP32) && defined(USE_ANALOG) && !USE_LEGACY_I2S)
6
11
12namespace audio_tools {
13
22public:
25
28 end();
29 }
30
33 bool begin(AnalogConfigESP32V1 cfg) override {
34 TRACEI();
35 bool result = true;
36 this->cfg = cfg;
37
38 switch (cfg.rx_tx_mode) {
39 case TX_MODE:
40 if (!setup_tx()) return false;
41 // convert to 16 bits
42 if (!converter.begin(cfg, 16)) {
43 LOGE("converter");
44 return false;
45 }
46 active_tx = true;
47 break;
48 case RX_MODE:
49 if (!setup_rx()) return false;
50 active_rx = true;
51 break;
52 default:
53 LOGE( "Unsupported MODE: %d", cfg.rx_tx_mode);
54 return false;
55 }
56
57 active = true;
58 return active;
59 }
60
63 void end() override {
64 TRACEI();
65 if (active_tx) {
66 cleanup_tx();
67 }
68 if (active_rx) {
69 cleanup_rx();
70 }
71
72 converter.end();
73
74 active_tx = false;
75 active_rx = false;
76 active = false;
77 }
78
79 // Writes the data to the Digital to Analog Converter
80 // ----------------------------------------------------------
81 size_t write(const uint8_t *src, size_t size_bytes) override {
82 // TRACED();
83 // convert any format to int16_t
84 return converter.write(src, size_bytes);
85 }
86
87 // Reads data from DMA buffer of the Analog to Digital Converter
88 // ----------------------------------------------------------
89 size_t readBytes(uint8_t *dest, size_t size_bytes) override {
90 // TRACED();
91 // Use the IO16Bit class for reading
92 return io.readBytes(dest, size_bytes);
93 }
94
95 // How much data will there be available after reading ADC buffer
96 // ----------------------------------------------------------
97 int available() override {
98 if (!active_rx) return 0;
99 int buffered = availableFromFifoBytes();
100 return buffered > 0 ? buffered : configuredRxBytes();
101 }
102
103protected:
104
108 template<typename T>
109 class FIFO {
110 public:
111
112 FIFO() : size_(0), buffer_(nullptr), head_(0), tail_(0), count_(0) {}
113
114 FIFO(size_t size) : size_(size), buffer_(new T[size]), head_(0), tail_(0), count_(0) {}
115
117 delete[] buffer_;
118 //LOGD("FIFO destroyed: size: %d, count: %d", size_, count_);
119 }
120
121 bool push(const T& value) {
122 if (count_ < size_) {
123 buffer_[tail_] = value;
124 //LOGD("FIFO push - Value: %d at location: %d", value, tail_);
125 tail_ = (tail_ + 1) % size_;
126 count_++;
127 //LOGD("FIFO push updated tail: %d, count: %d", tail_, count_);
128 return true;
129 }
130 //LOGD("FIFO push failed - count %d > size %d", value, count_, size_);
131 return false; // Buffer full
132 }
133
134 bool pop(T& value) {
135 if (count_ > 0) {
136 value = buffer_[head_];
137 //LOGD("FIFO pop - Value: %d at location: %d", value, head_);
138 head_ = (head_ + 1) % size_;
139 count_--;
140 //LOGD("FIFO pop updated head: %d, count: %d", head_, count_);
141 return true;
142 }
143 //LOGD("FIFO pop failed - count %d == 0", count_);
144 return false; // Buffer empty
145 }
146
147 size_t size() const {
148 return count_;
149 }
150
151 bool empty() const {
152 return count_ == 0;
153 }
154
155 bool full() const {
156 return count_ == size_;
157 }
158
159 void clear() {
160 head_ = 0;
161 tail_ = 0;
162 count_ = 0;
163 }
164
165 private:
166 size_t size_;
167 T* buffer_;
168 size_t head_;
169 size_t tail_;
170 size_t count_;
171 };
172
173 adc_continuous_handle_t adc_handle = nullptr;
174 adc_cali_handle_t adc_cali_handle = nullptr;
177 bool active = false;
178 bool active_tx = false;
179 bool active_rx = false;
180 bool rx_started = false;
183 #ifdef HAS_ESP32_DAC
184 dac_continuous_handle_t dac_handle = nullptr;
185 #endif
186
187 // create array of FIFO buffers, one for each channel
189 adc_digi_output_data_t* rx_result_buffer = nullptr;
192
193 int configuredRxBytes() const {
194 return (cfg.buffer_size > 0) ? (int)(cfg.buffer_size * sizeof(int16_t)) : 0;
195 }
196
198 if (fifo_buffers == nullptr || cfg.channels <= 0) return 0;
199 size_t min_samples = fifo_buffers[0]->size();
200 for (int i = 1; i < cfg.channels; ++i) {
201 size_t fifo_size = fifo_buffers[i]->size();
202 if (fifo_size < min_samples) {
203 min_samples = fifo_size;
204 }
205 }
206 return (int)min_samples;
207 }
208
210 return availableFramesFromFifos() * cfg.channels * (int)sizeof(int16_t);
211 }
212
213 size_t fifoCapacityFromConvFrameBytes(size_t conv_frame_bytes) const {
214 if (cfg.channels <= 0) return 8U;
215
216 size_t fallback = 8U;
217 if (SOC_ADC_DIGI_RESULT_BYTES == 0) return fallback;
218
219 size_t frame_results = conv_frame_bytes / SOC_ADC_DIGI_RESULT_BYTES;
220 if (frame_results == 0) return fallback;
221
222 size_t frame_results_per_channel = frame_results / (size_t)cfg.channels;
223 if (frame_results_per_channel == 0) return fallback;
224
225 return frame_results_per_channel + 4U;
226 }
227
228 int getChannelIndex(ADC_CHANNEL_TYPE chan_num) const {
229 for (int j = 0; j < cfg.channels; ++j) {
230 if (cfg.adc_channels[j] == chan_num) {
231 return j;
232 }
233 }
234 return -1;
235 }
236
238 if (fifo_buffers == nullptr) return;
239 for (int i = 0; i < cfg.channels; ++i) {
240 if (fifo_buffers[i] != nullptr) {
241 fifo_buffers[i]->clear();
242 }
243 }
244 }
245
247 delete[] rx_result_buffer;
248 rx_result_buffer = nullptr;
251 }
252
253 bool isValidType2Record(const adc_digi_output_data_t& sample) const {
254 if (cfg.adc_output_type != ADC_DIGI_OUTPUT_FORMAT_TYPE2) return true;
255
256 uint32_t chan_num = sample.type2.channel;
257 if (chan_num >= SOC_ADC_CHANNEL_NUM(cfg.adc_unit)) {
258 LOGE("Invalid TYPE2 ADC channel: %u", (unsigned)chan_num);
259 return false;
260 }
261
262#ifdef ADC_CONV_SINGLE_UNIT_1
263 if (cfg.adc_conversion_mode == ADC_CONV_SINGLE_UNIT_1 &&
264 sample.type2.unit != 0) {
265 LOGE("Invalid TYPE2 ADC unit for ADC1 mode: %u",
266 (unsigned)sample.type2.unit);
267 return false;
268 }
269#endif
270#ifdef ADC_CONV_SINGLE_UNIT_2
271 if (cfg.adc_conversion_mode == ADC_CONV_SINGLE_UNIT_2 &&
272 sample.type2.unit != 1) {
273 LOGE("Invalid TYPE2 ADC unit for ADC2 mode: %u",
274 (unsigned)sample.type2.unit);
275 return false;
276 }
277#endif
278 return true;
279 }
280
281 int16_t getOutputSample(ADC_DATA_TYPE data) {
283 return static_cast<int16_t>(data);
284 }
285
286 int data_milliVolts = 0;
287 esp_err_t err = adc_cali_raw_to_voltage(adc_cali_handle, (int)data,
288 &data_milliVolts);
289 if (err != ESP_OK) {
290 LOGE("adc_cali_raw_to_voltage error: %d", err);
291 return 0;
292 }
293 return static_cast<int16_t>(data_milliVolts);
294 }
295
296 bool pushAdcChunkToReorderBuffers(const adc_digi_output_data_t* data,
297 int samples_read) {
298 if (data == nullptr) return false;
299
300 for (int i = 0; i < samples_read; ++i) {
301 const adc_digi_output_data_t* sample = &data[i];
302 if (!isValidType2Record(*sample)) {
303 LOGE("ADC reorder resync on invalid TYPE2 record at sample %d", i);
305 return false;
306 }
307
308 ADC_CHANNEL_TYPE chan_num = AUDIO_ADC_GET_CHANNEL(sample);
309 int channel_idx = getChannelIndex(chan_num);
310 if (channel_idx < 0) {
311 LOGE("ADC reorder resync on invalid channel %u at sample %d",
312 (unsigned)chan_num, i);
314 return false;
315 }
316
317 ADC_DATA_TYPE sample_value = AUDIO_ADC_GET_DATA(sample);
318 if (!fifo_buffers[channel_idx]->push(sample_value)) {
319 LOGE("ADC reorder FIFO overflow on channel index %d (channel %u)",
320 channel_idx, (unsigned)chan_num);
322 return false;
323 }
324 }
325 return true;
326 }
327
328 int emitFramesFromFifos(int16_t* dest, int max_frames) {
329 if (dest == nullptr || max_frames <= 0 || cfg.channels <= 0) return 0;
330
331 int frames_available = availableFramesFromFifos();
332 int frames_to_emit =
333 (frames_available < max_frames) ? frames_available : max_frames;
334 int frames_emitted = 0;
335
336 for (int frame = 0; frame < frames_to_emit; ++frame) {
337 ADC_DATA_TYPE frame_data[NUM_ADC_CHANNELS];
338 for (int ch = 0; ch < cfg.channels; ++ch) {
339 if (!fifo_buffers[ch]->pop(frame_data[ch])) {
340 LOGE("ADC reorder pop failed on channel index %d", ch);
342 return frames_emitted;
343 }
344 }
345
346 for (int ch = 0; ch < cfg.channels; ++ch) {
347 dest[frames_emitted * cfg.channels + ch] =
348 getOutputSample(frame_data[ch]);
349 }
350 ++frames_emitted;
351 }
352
353 return frames_emitted;
354 }
355
357 if (fifo_buffers == nullptr) return;
358 for (int i = 0; i < cfg.channels; ++i) {
359 delete fifo_buffers[i];
360 }
361 delete[] fifo_buffers;
362 fifo_buffers = nullptr;
363 }
364
366 if (!adc_cali_handle_active || adc_cali_handle == nullptr) return;
367#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
368 adc_cali_delete_scheme_curve_fitting(adc_cali_handle);
369#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
370 adc_cali_delete_scheme_line_fitting(adc_cali_handle);
371#endif
372 adc_cali_handle = nullptr;
374 }
375
376#ifdef ARDUINO
377 void cleanupAttachedRxPins() {
378 perimanSetBusDeinit(ESP32_BUS_TYPE_ADC_CONT, adcDetachBus);
379 for (int i = 0; i < rx_pins_attached; ++i) {
380 adc_channel_t adc_channel = cfg.adc_channels[i];
381 int io_pin;
382 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
383 if (perimanGetPinBusType(io_pin) == ESP32_BUS_TYPE_ADC_CONT) {
384 if (!perimanClearPinBus(io_pin)) {
385 LOGE("perimanClearPinBus failed!");
386 }
387 }
388 }
390 }
391#endif
392
393 // 16Bit Audiostream for ESP32
394 // ----------------------------------------------------------
395 class IO16Bit : public AudioStream {
396 public:
397 IO16Bit(AnalogDriverESP32V1 *driver) { self = driver; }
398
399 // Write int16_t data to the Digital to Analog Converter
400 // ----------------------------------------------------------
401 size_t write(const uint8_t *src, size_t size_bytes) override {
402 // TRACED();
403 #ifdef HAS_ESP32_DAC
404 size_t result = 0;
405 // Convert signed 16-bit to unsigned 8-bit
406 int16_t *data16 = (int16_t *)src;
407 uint8_t *data8 = (uint8_t *)src;
408 int samples = size_bytes / 2;
409
410 // Process data in batches to reduce the number of conversions and writes
411 for (int j = 0; j < samples; j++) {
412 data8[j] = (32768u + data16[j]) >> 8;
413 }
414
415 if (dac_continuous_write(self->dac_handle, data8, samples, &result, self->cfg.timeout) != ESP_OK) {
416 result = 0;
417 }
418 return result * 2;
419 #else
420 return 0;
421 #endif
422 }
423
424 // Read int16_t data from Analog to Digital Converter
425 // ----------------------------------------------------------
426 // FYI
427 // typedef struct {
428 // union {
429 // struct {
430 // uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
431 // uint16_t channel: 4; /*!<ADC channel index info. */
432 // } type1; /*!<ADC type1 */
433 // struct {
434 // uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
435 // uint16_t channel: 4; /*!<ADC channel index info. For ESP32-S2:
436 // If (channel < ADC_CHANNEL_MAX), The data is valid.
437 // If (channel > ADC_CHANNEL_MAX), The data is invalid. */
438 // uint16_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
439 // } type2; /*!<When the configured output format is 11bit.*/
440 // uint16_t val; /*!<Raw data value */
441 // };
442 // } adc_digi_output_data_t;
443
444 size_t readBytes(uint8_t *dest, size_t size_bytes) {
445 if (dest == nullptr || size_bytes == 0 || self->cfg.channels <= 0) {
446 return 0;
447 }
448 if (self->rx_result_buffer == nullptr || self->rx_result_buffer_bytes == 0) {
449 LOGE("ADC RX scratch buffer is not initialized");
450 return 0;
451 }
452
453 const size_t frame_size_bytes =
454 (size_t)self->cfg.channels * sizeof(int16_t);
455 const size_t frames_requested = size_bytes / frame_size_bytes;
456 if (frames_requested == 0) {
457 return 0;
458 }
459
460 int16_t* result16 = reinterpret_cast<int16_t*>(dest);
461 int frames_provided =
462 self->emitFramesFromFifos(result16, (int)frames_requested);
463
464 while (frames_provided < (int)frames_requested) {
465 uint32_t bytes_read = 0;
466 esp_err_t err = adc_continuous_read(
468 reinterpret_cast<uint8_t*>(self->rx_result_buffer),
469 (uint32_t)self->rx_result_buffer_bytes, &bytes_read,
470 (uint32_t)self->cfg.timeout);
471 if (err != ESP_OK) {
472 if (err != ESP_ERR_TIMEOUT) {
473 LOGE("adc_continuous_read unsuccessful: %d", err);
474 }
475 break;
476 }
477
478 int samples_read = bytes_read / sizeof(adc_digi_output_data_t);
479 if (samples_read <= 0) {
480 break;
481 }
482
484 samples_read)) {
485 break;
486 }
487
488 frames_provided += self->emitFramesFromFifos(
489 result16 + (frames_provided * self->cfg.channels),
490 (int)frames_requested - frames_provided);
491 }
492
493 size_t bytes_provided = (size_t)frames_provided * frame_size_bytes;
494 if (bytes_provided > 0 && self->cfg.is_auto_center_read) {
495 self->auto_center.convert(dest, bytes_provided);
496 }
497 return bytes_provided;
498 }
499
500 protected:
502
503 } io{this};
504
506
507 // Setup Digital to Analog
508 // ----------------------------------------------------------
509 #ifdef HAS_ESP32_DAC
510 bool setup_tx() {
511 dac_continuous_config_t cont_cfg = {
512 .chan_mask = cfg.channels == 1 ? cfg.dac_mono_channel : DAC_CHANNEL_MASK_ALL,
513 .desc_num = (uint32_t)cfg.buffer_count,
514 .buf_size = (size_t)cfg.buffer_size,
515 .freq_hz = (uint32_t)cfg.sample_rate,
516 .offset = 0,
517 .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
518 .chan_mode = cfg.channels == 1 ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER,
519 };
520 // Allocate continuous channels
521 if (dac_continuous_new_channels(&cont_cfg, &dac_handle) != ESP_OK) {
522 LOGE("new_channels");
523 return false;
524 }
525 if (dac_continuous_enable(dac_handle) != ESP_OK) {
526 LOGE("enable");
527 return false;
528 }
529 return true;
530 }
531 #else
532 bool setup_tx() {
533 LOGE("DAC not supported");
534 return false;
535 }
536 #endif
537
538 // Setup Analog to Digital Converter
539 // ----------------------------------------------------------
540 bool setup_rx() {
541 adc_channel_t adc_channel;
542 int io_pin;
543 esp_err_t err;
544
545 // Check the configuration
546 if (!checkADCChannels()) return false;
547 if (!checkADCSampleRate()) return false;
548 if (!checkADCBitWidth()) return false;
549 if (!checkADCBitsPerSample()) return false;
550
551 if (adc_handle != nullptr) {
552 LOGE("adc unit %u continuous is already initialized. Please call end() first!", cfg.adc_unit);
553 return false;
554 }
555
556 #ifdef ARDUINO
557 // Set periman deinit callback
558 // TODO, currently handled in end() method
559
560 // Set the pins/channels to INIT state
561 for (int i = 0; i < cfg.channels; i++) {
562 adc_channel = cfg.adc_channels[i];
563 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
564 if (!perimanClearPinBus(io_pin)) {
565 LOGE("perimanClearPinBus failed!");
566 return false;
567 }
568 }
569 #endif
570
571 uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
572 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
573 conv_frame_size = adcContinuousAlignFrameSize(conv_frame_size);
574 #endif
575
576 uint32_t rx_max_conv_frame_bytes = adcContinuousMaxConvFrameBytes();
577 uint32_t max_samples_per_frame = adcContinuousMaxResultsPerFrame();
578 if (conv_frame_size > rx_max_conv_frame_bytes) {
579 LOGE(
580 "buffer_size is too big for one ADC DMA frame: %u samples = %u "
581 "bytes, max %u samples / %u bytes",
582 cfg.buffer_size, (unsigned)conv_frame_size,
583 (unsigned)max_samples_per_frame,
584 (unsigned)rx_max_conv_frame_bytes);
585 return false;
586 } else {
587 LOGI(
588 "RX DMA frame: %u conversion results, %u bytes (max %u results / "
589 "%u bytes)",
590 cfg.buffer_size, (unsigned)conv_frame_size,
591 (unsigned)max_samples_per_frame,
592 (unsigned)rx_max_conv_frame_bytes);
593 }
594
595 // Create adc_continuous handle
596 adc_continuous_handle_cfg_t adc_config;
597 uint32_t rx_frame_count = cfg.buffer_count > 0 ? (uint32_t)cfg.buffer_count : 1U;
598 adc_config.max_store_buf_size = (uint32_t)conv_frame_size * rx_frame_count;
599 adc_config.conv_frame_size = (uint32_t) conv_frame_size;
600#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
601 adc_config.flags.flush_pool = true;
602#endif
603 LOGI("RX pool: %u frames, %u bytes", (unsigned)rx_frame_count,
604 (unsigned)adc_config.max_store_buf_size);
605 err = adc_continuous_new_handle(&adc_config, &adc_handle);
606 if (err != ESP_OK) {
607 LOGE("adc_continuous_new_handle failed with error: %d", err);
608 return false;
609 } else {
610 LOGI("adc_continuous_new_handle successful");
611 }
612
613 // Configure the ADC patterns
614 adc_digi_pattern_config_t adc_pattern[cfg.channels] = {};
615 for (int i = 0; i < cfg.channels; i++) {
616 uint8_t ch = cfg.adc_channels[i];
617 adc_pattern[i].atten = (uint8_t) cfg.adc_attenuation;
618 adc_pattern[i].channel = (uint8_t)ch;
619 adc_pattern[i].unit = (uint8_t) cfg.adc_unit;
620 adc_pattern[i].bit_width = (uint8_t) cfg.adc_bit_width;
621 }
622
623 // Configure the ADC
624 adc_continuous_config_t dig_cfg = {
625 .pattern_num = (uint32_t) cfg.channels,
626 .adc_pattern = adc_pattern,
627 .sample_freq_hz = (uint32_t)cfg.sample_rate * cfg.channels,
628 .conv_mode = (adc_digi_convert_mode_t) cfg.adc_conversion_mode,
629 .format = (adc_digi_output_format_t) cfg.adc_output_type,
630 };
631
632 // Log the configuration
633 LOGI("dig_cfg.sample_freq_hz: %u", (unsigned)dig_cfg.sample_freq_hz);
634 LOGI("dig_cfg.conv_mode: %u (1: unit 1, 2: unit 2, 3: both)", dig_cfg.conv_mode);
635 LOGI("dig_cfg.format: %u (0 is type1: [12bit data, 4bit channel])", (unsigned)cfg.adc_output_type);
636 for (int i = 0; i < cfg.channels; i++) {
637 LOGI("dig_cfg.adc_pattern[%d].atten: %u", i, dig_cfg.adc_pattern[i].atten);
638 LOGI("dig_cfg.adc_pattern[%d].channel: %u", i, dig_cfg.adc_pattern[i].channel);
639 LOGI("dig_cfg.adc_pattern[%d].unit: %u", i, dig_cfg.adc_pattern[i].unit);
640 LOGI("dig_cfg.adc_pattern[%d].bit_width: %u", i, dig_cfg.adc_pattern[i].bit_width);
641 }
642
643 // Initialize ADC
644 err = adc_continuous_config(adc_handle, &dig_cfg);
645 if (err != ESP_OK) {
646 LOGE("adc_continuous_config unsuccessful with error: %d", err);
647 cleanup_rx();
648 return false;
649 }
650 LOGI("adc_continuous_config successful");
651
652 // Set up optional calibration
653 if (!setupADCCalibration()) {
654 cleanup_rx();
655 return false;
656 }
657
658 // Attach the pins to the ADC unit
659#ifdef ARDUINO
660 for (int i = 0; i < cfg.channels; i++) {
661 adc_channel = cfg.adc_channels[i];
662 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
663 // perimanSetPinBus: uint8_t pin, peripheral_bus_type_t type, void * bus, int8_t bus_num, int8_t bus_channel
664 if (!perimanSetPinBus(io_pin, ESP32_BUS_TYPE_ADC_CONT, (void *)(cfg.adc_unit + 1), cfg.adc_unit, adc_channel)) {
665 LOGE("perimanSetPinBus to Continuous an ADC Unit %u failed!", cfg.adc_unit);
666 cleanup_rx();
667 return false;
668 }
669 rx_pins_attached = i + 1;
670 }
671#endif
672
673 // Start ADC
674 err = adc_continuous_start(adc_handle);
675 if (err != ESP_OK) {
676 LOGE("adc_continuous_start unsuccessful with error: %d", err);
677 cleanup_rx();
678 return false;
679 }
680 rx_started = true;
681
682 // Setup up optimal auto center which puts the avg at 0
684
686 rx_result_buffer_bytes = conv_frame_size;
688 rx_result_buffer_bytes / sizeof(adc_digi_output_data_t);
689 rx_result_buffer = new adc_digi_output_data_t[rx_result_buffer_samples];
690 if (rx_result_buffer == nullptr || rx_result_buffer_samples == 0) {
691 LOGE("Failed to allocate ADC RX scratch buffer");
692 cleanup_rx();
693 return false;
694 }
695 LOGI("ADC RX scratch buffer allocated for %u bytes / %u samples",
697
698 // Keep the reorder FIFOs small: they absorb channel skew only and are
699 // not sized for the caller's full readBytes() window.
700 size_t fifo_size = fifoCapacityFromConvFrameBytes(conv_frame_size);
701 fifo_buffers = new FIFO<ADC_DATA_TYPE>*[cfg.channels](); // Allocate an array of FIFO objects
702 for (int i = 0; i < cfg.channels; ++i) {
703 fifo_buffers[i] = new FIFO<ADC_DATA_TYPE>(fifo_size);
704 }
706 LOGI("%d FIFO buffers allocated of size %u from DMA frame %u bytes",
707 cfg.channels, (unsigned)fifo_size, (unsigned)conv_frame_size);
708
709 LOGI("Setup ADC successful");
710
711 return true;
712 }
713
715 bool cleanup_tx() {
716 bool ok = true;
717#ifdef HAS_ESP32_DAC
718 if (dac_handle==nullptr) return true;
719 if (dac_continuous_disable(dac_handle) != ESP_OK){
720 ok = false;
721 LOGE("dac_continuous_disable failed");
722 }
723 if (dac_continuous_del_channels(dac_handle) != ESP_OK){
724 ok = false;
725 LOGE("dac_continuous_del_channels failed");
726 }
727 dac_handle = nullptr;
728#endif
729 return ok;
730 }
731
732#ifdef ARDUINO
733 // dummy detach: w/o this it's failing
734 static bool adcDetachBus(void *bus) {
735 LOGD("===> adcDetachBus: %d", (int) bus);
736 return true;
737 }
738#endif
739
741 bool cleanup_rx() {
742 bool ok = true;
743 if (adc_handle != nullptr && rx_started) {
744 if (adc_continuous_stop(adc_handle) != ESP_OK) {
745 LOGE("adc_continuous_stop failed");
746 ok = false;
747 }
748 rx_started = false;
749 }
750 if (adc_handle != nullptr) {
751 if (adc_continuous_deinit(adc_handle) != ESP_OK) {
752 LOGE("adc_continuous_deinit failed");
753 ok = false;
754 }
755 adc_handle = nullptr;
756 }
757
761
762#ifdef ARDUINO
763 cleanupAttachedRxPins();
764#endif
765 return ok;
766 }
767
770 if ((cfg.adc_bit_width < SOC_ADC_DIGI_MIN_BITWIDTH) ||
771 (cfg.adc_bit_width > SOC_ADC_DIGI_MAX_BITWIDTH)) {
772 LOGE("adc bit width: %u cannot be set, range: %u to %u", cfg.adc_bit_width,
773 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
774 return false;
775 }
776 LOGI("adc bit width: %u, range: %u to %u", cfg.adc_bit_width,
777 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
778 return true;
779 }
780
783 int io_pin;
784 adc_channel_t adc_channel;
785
786 int max_channels = sizeof(cfg.adc_channels) / sizeof(adc_channel_t);
787 if (cfg.channels > max_channels) {
788 LOGE("number of channels: %d, max: %d", cfg.channels, max_channels);
789 return false;
790 }
791 LOGI("channels: %d, max: %d", cfg.channels, max_channels);
792
793 // Lets make sure the adc channels are available
794 for (int i = 0; i < cfg.channels; i++) {
795 adc_channel = cfg.adc_channels[i];
796 auto err = adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
797 if (err != ESP_OK) {
798 LOGE("ADC channel %u is not available on ADC unit %u", adc_channel, cfg.adc_unit);
799 return false;
800 } else {
801 LOGI("ADC channel %u is on pin %u", adc_channel, io_pin);
802 }
803 }
804 return true;
805 }
806
809 int sample_rate = cfg.sample_rate * cfg.channels;
810 if ((sample_rate < SOC_ADC_SAMPLE_FREQ_THRES_LOW) ||
811 (sample_rate > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)) {
812 LOGE("sample rate eff: %u can not be set, range: %u to %u", sample_rate,
814 return false;
815 }
816 LOGI("sample rate eff: %u, range: %u to %u", sample_rate,
818
819 return true;
820 }
821
824 int supported_bits = 16; // for the time being we support only 16 bits!
825
826 // calculated default value if nothing is specified
827 if (cfg.bits_per_sample == 0) {
828 cfg.bits_per_sample = supported_bits;
829 LOGI("bits per sample set to: %d", cfg.bits_per_sample);
830 }
831
832 // check bits_per_sample
833 if (cfg.bits_per_sample != supported_bits) {
834 LOGE("bits per sample: error. It should be: %d but is %d",
835 supported_bits, cfg.bits_per_sample);
836 return false;
837 }
838 LOGI("bits per sample: %d", cfg.bits_per_sample);
839 return true;
840 }
841
845 return true;
846
847 // Initialize ADC calibration handle
848 // Calibration is applied to an ADC unit (not per channel).
849
850 // setup calibration only when requested
851 esp_err_t err = ESP_OK;
852
853 if (adc_cali_handle_active && adc_cali_handle != nullptr) {
854 return true;
855 }
856
857 if (adc_cali_handle == NULL) {
858 #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
859 // curve fitting is preferred
860 adc_cali_curve_fitting_config_t cali_config;
861 cali_config.unit_id = cfg.adc_unit;
862 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
863 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
864 err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle);
865 #elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
866 // line fitting is the alternative
867 adc_cali_line_fitting_config_t cali_config;
868 cali_config.unit_id = cfg.adc_unit;
869 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
870 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
871 err = adc_cali_create_scheme_line_fitting(&cali_config, &adc_cali_handle);
872 #endif
873 if (err != ESP_OK) {
874 adc_cali_handle = nullptr;
876 LOGE("creating calibration handle failed for ADC%d with atten %d and bitwidth %d",
878 return false;
879 } else {
881 LOGI("enabled calibration for ADC%d with atten %d and bitwidth %d",
883 }
884 }
885 return true;
886 }
887
888};
889
892
893} // namespace audio_tools
894
895#endif
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW
Definition AnalogConfigESP32V1.h:18
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH
Definition AnalogConfigESP32V1.h:15
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
ESP32 specific configuration for i2s input via adc using the adc_continuous API.
Definition AnalogConfigESP32V1.h:141
int buffer_count
Definition AnalogConfigESP32V1.h:148
uint8_t adc_bit_width
Definition AnalogConfigESP32V1.h:169
RxTxMode rx_tx_mode
Definition AnalogConfigESP32V1.h:153
adc_digi_convert_mode_t adc_conversion_mode
Definition AnalogConfigESP32V1.h:166
bool is_auto_center_read
Definition AnalogConfigESP32V1.h:165
TickType_t timeout
Definition AnalogConfigESP32V1.h:154
adc_unit_t adc_unit
Definition AnalogConfigESP32V1.h:171
uint8_t adc_attenuation
Definition AnalogConfigESP32V1.h:168
adc_channel_t adc_channels[NUM_ADC_CHANNELS]
Definition AnalogConfigESP32V1.h:172
bool adc_calibration_active
Definition AnalogConfigESP32V1.h:164
adc_digi_output_format_t adc_output_type
Definition AnalogConfigESP32V1.h:167
int buffer_size
Definition AnalogConfigESP32V1.h:152
Definition AnalogDriverBase.h:9
Custom FIFO class.
Definition AnalogDriverESP32V1.h:109
bool push(const T &value)
Definition AnalogDriverESP32V1.h:121
FIFO(size_t size)
Definition AnalogDriverESP32V1.h:114
size_t size() const
Definition AnalogDriverESP32V1.h:147
bool empty() const
Definition AnalogDriverESP32V1.h:151
~FIFO()
Definition AnalogDriverESP32V1.h:116
bool pop(T &value)
Definition AnalogDriverESP32V1.h:134
bool full() const
Definition AnalogDriverESP32V1.h:155
FIFO()
Definition AnalogDriverESP32V1.h:112
void clear()
Definition AnalogDriverESP32V1.h:159
Definition AnalogDriverESP32V1.h:395
size_t write(const uint8_t *src, size_t size_bytes) override
Definition AnalogDriverESP32V1.h:401
IO16Bit(AnalogDriverESP32V1 *driver)
Definition AnalogDriverESP32V1.h:397
size_t readBytes(uint8_t *dest, size_t size_bytes)
Definition AnalogDriverESP32V1.h:444
AnalogDriverESP32V1 * self
Definition AnalogDriverESP32V1.h:501
AnalogAudioStream: A very fast DAC using DMA using the new dac_continuous API.
Definition AnalogDriverESP32V1.h:21
size_t fifoCapacityFromConvFrameBytes(size_t conv_frame_bytes) const
Definition AnalogDriverESP32V1.h:213
bool active
Definition AnalogDriverESP32V1.h:177
bool checkADCBitWidth()
Definition AnalogDriverESP32V1.h:769
virtual ~AnalogDriverESP32V1()
Destructor.
Definition AnalogDriverESP32V1.h:27
bool active_tx
Definition AnalogDriverESP32V1.h:178
int16_t getOutputSample(ADC_DATA_TYPE data)
Definition AnalogDriverESP32V1.h:281
void resetReorderState()
Definition AnalogDriverESP32V1.h:237
bool rx_started
Definition AnalogDriverESP32V1.h:180
size_t rx_result_buffer_samples
Definition AnalogDriverESP32V1.h:190
adc_cali_handle_t adc_cali_handle
Definition AnalogDriverESP32V1.h:174
bool setup_tx()
Definition AnalogDriverESP32V1.h:532
int availableFramesFromFifos() const
Definition AnalogDriverESP32V1.h:197
size_t write(const uint8_t *src, size_t size_bytes) override
Definition AnalogDriverESP32V1.h:81
bool active_rx
Definition AnalogDriverESP32V1.h:179
size_t readBytes(uint8_t *dest, size_t size_bytes) override
Definition AnalogDriverESP32V1.h:89
adc_digi_output_data_t * rx_result_buffer
Definition AnalogDriverESP32V1.h:189
adc_continuous_handle_t adc_handle
Definition AnalogDriverESP32V1.h:173
bool isValidType2Record(const adc_digi_output_data_t &sample) const
Definition AnalogDriverESP32V1.h:253
int emitFramesFromFifos(int16_t *dest, int max_frames)
Definition AnalogDriverESP32V1.h:328
bool setup_rx()
Definition AnalogDriverESP32V1.h:540
AnalogConfigESP32V1 cfg
Definition AnalogDriverESP32V1.h:176
bool checkADCChannels()
Definition AnalogDriverESP32V1.h:782
void end() override
Definition AnalogDriverESP32V1.h:63
int available() override
Definition AnalogDriverESP32V1.h:97
bool cleanup_tx()
Cleanup dac.
Definition AnalogDriverESP32V1.h:715
bool adc_cali_handle_active
Definition AnalogDriverESP32V1.h:175
bool cleanup_rx()
Cleanup Analog to Digital Converter.
Definition AnalogDriverESP32V1.h:741
int rx_pins_attached
Definition AnalogDriverESP32V1.h:181
AnalogDriverESP32V1()
Default constructor.
Definition AnalogDriverESP32V1.h:24
size_t rx_result_buffer_bytes
Definition AnalogDriverESP32V1.h:191
void cleanupFifoBuffers()
Definition AnalogDriverESP32V1.h:356
void cleanupScratchBuffer()
Definition AnalogDriverESP32V1.h:246
int getChannelIndex(ADC_CHANNEL_TYPE chan_num) const
Definition AnalogDriverESP32V1.h:228
bool setupADCCalibration()
Definition AnalogDriverESP32V1.h:843
FIFO< ADC_DATA_TYPE > ** fifo_buffers
Definition AnalogDriverESP32V1.h:188
void cleanupADCCalibration()
Definition AnalogDriverESP32V1.h:365
bool checkADCSampleRate()
Definition AnalogDriverESP32V1.h:808
NumberFormatConverterStream converter
Definition AnalogDriverESP32V1.h:505
bool checkADCBitsPerSample()
Definition AnalogDriverESP32V1.h:823
int availableFromFifoBytes() const
Definition AnalogDriverESP32V1.h:209
ConverterAutoCenter auto_center
Definition AnalogDriverESP32V1.h:182
bool pushAdcChunkToReorderBuffers(const adc_digi_output_data_t *data, int samples_read)
Definition AnalogDriverESP32V1.h:296
int configuredRxBytes() const
Definition AnalogDriverESP32V1.h:193
bool begin(AnalogConfigESP32V1 cfg) override
Definition AnalogDriverESP32V1.h:33
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
Makes sure that the avg of the signal is set to 0.
Definition BaseConverter.h:200
bool begin(AudioInfo info, bool isDynamic=false)
Definition BaseConverter.h:220
size_t convert(uint8_t *src, size_t size) override
Definition BaseConverter.h:256
Converter which converts between bits_per_sample and 16 bits. The templated NumberFormatConverterStre...
Definition AudioStreamsConverter.h:471
virtual size_t write(const uint8_t *data, size_t len) override
Definition AudioStreamsConverter.h:563
bool begin(AudioInfo info, AudioInfo to, float gain=1.0f)
Definition AudioStreamsConverter.h:493
void end() override
Definition AudioStreamsConverter.h:514
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
AnalogDriverArduino AnalogDriver
AnalogAudioStream.
Definition AnalogDriverArduino.h:48
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57