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#ifdef SOC_ADC_CHANNEL_NUM
258 if (chan_num >= SOC_ADC_CHANNEL_NUM(cfg.adc_unit)) {
259 LOGE("Invalid TYPE2 ADC channel: %u", (unsigned)chan_num);
260 return false;
261 }
262#endif
263
264#ifdef ADC_CONV_SINGLE_UNIT_1
265 if (cfg.adc_conversion_mode == ADC_CONV_SINGLE_UNIT_1 &&
266 sample.type2.unit != 0) {
267 LOGE("Invalid TYPE2 ADC unit for ADC1 mode: %u",
268 (unsigned)sample.type2.unit);
269 return false;
270 }
271#endif
272#ifdef ADC_CONV_SINGLE_UNIT_2
273 if (cfg.adc_conversion_mode == ADC_CONV_SINGLE_UNIT_2 &&
274 sample.type2.unit != 1) {
275 LOGE("Invalid TYPE2 ADC unit for ADC2 mode: %u",
276 (unsigned)sample.type2.unit);
277 return false;
278 }
279#endif
280 return true;
281 }
282
283 int16_t getOutputSample(ADC_DATA_TYPE data) {
285 return static_cast<int16_t>(data);
286 }
287
288 int data_milliVolts = 0;
289 esp_err_t err = adc_cali_raw_to_voltage(adc_cali_handle, (int)data,
290 &data_milliVolts);
291 if (err != ESP_OK) {
292 LOGE("adc_cali_raw_to_voltage error: %d", err);
293 return 0;
294 }
295 return static_cast<int16_t>(data_milliVolts);
296 }
297
298 bool pushAdcChunkToReorderBuffers(const adc_digi_output_data_t* data,
299 int samples_read) {
300 if (data == nullptr) return false;
301
302 for (int i = 0; i < samples_read; ++i) {
303 const adc_digi_output_data_t* sample = &data[i];
304 if (!isValidType2Record(*sample)) {
305 LOGE("ADC reorder resync on invalid TYPE2 record at sample %d", i);
307 return false;
308 }
309
310 ADC_CHANNEL_TYPE chan_num = AUDIO_ADC_GET_CHANNEL(sample);
311 int channel_idx = getChannelIndex(chan_num);
312 if (channel_idx < 0) {
313 LOGE("ADC reorder resync on invalid channel %u at sample %d",
314 (unsigned)chan_num, i);
316 return false;
317 }
318
319 ADC_DATA_TYPE sample_value = AUDIO_ADC_GET_DATA(sample);
320 if (!fifo_buffers[channel_idx]->push(sample_value)) {
321 LOGE("ADC reorder FIFO overflow on channel index %d (channel %u)",
322 channel_idx, (unsigned)chan_num);
324 return false;
325 }
326 }
327 return true;
328 }
329
330 int emitFramesFromFifos(int16_t* dest, int max_frames) {
331 if (dest == nullptr || max_frames <= 0 || cfg.channels <= 0) return 0;
332
333 int frames_available = availableFramesFromFifos();
334 int frames_to_emit =
335 (frames_available < max_frames) ? frames_available : max_frames;
336 int frames_emitted = 0;
337
338 for (int frame = 0; frame < frames_to_emit; ++frame) {
339 ADC_DATA_TYPE frame_data[NUM_ADC_CHANNELS];
340 for (int ch = 0; ch < cfg.channels; ++ch) {
341 if (!fifo_buffers[ch]->pop(frame_data[ch])) {
342 LOGE("ADC reorder pop failed on channel index %d", ch);
344 return frames_emitted;
345 }
346 }
347
348 for (int ch = 0; ch < cfg.channels; ++ch) {
349 dest[frames_emitted * cfg.channels + ch] =
350 getOutputSample(frame_data[ch]);
351 }
352 ++frames_emitted;
353 }
354
355 return frames_emitted;
356 }
357
359 if (fifo_buffers == nullptr) return;
360 for (int i = 0; i < cfg.channels; ++i) {
361 delete fifo_buffers[i];
362 }
363 delete[] fifo_buffers;
364 fifo_buffers = nullptr;
365 }
366
368 if (!adc_cali_handle_active || adc_cali_handle == nullptr) return;
369#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
370 adc_cali_delete_scheme_curve_fitting(adc_cali_handle);
371#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
372 adc_cali_delete_scheme_line_fitting(adc_cali_handle);
373#endif
374 adc_cali_handle = nullptr;
376 }
377
378#ifdef ARDUINO
379 void cleanupAttachedRxPins() {
380 perimanSetBusDeinit(ESP32_BUS_TYPE_ADC_CONT, adcDetachBus);
381 for (int i = 0; i < rx_pins_attached; ++i) {
382 adc_channel_t adc_channel = cfg.adc_channels[i];
383 int io_pin;
384 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
385 if (perimanGetPinBusType(io_pin) == ESP32_BUS_TYPE_ADC_CONT) {
386 if (!perimanClearPinBus(io_pin)) {
387 LOGE("perimanClearPinBus failed!");
388 }
389 }
390 }
392 }
393#endif
394
395 // 16Bit Audiostream for ESP32
396 // ----------------------------------------------------------
397 class IO16Bit : public AudioStream {
398 public:
399 IO16Bit(AnalogDriverESP32V1 *driver) { self = driver; }
400
401 // Write int16_t data to the Digital to Analog Converter
402 // ----------------------------------------------------------
403 size_t write(const uint8_t *src, size_t size_bytes) override {
404 // TRACED();
405 #ifdef HAS_ESP32_DAC
406 size_t result = 0;
407 // Convert signed 16-bit to unsigned 8-bit
408 int16_t *data16 = (int16_t *)src;
409 uint8_t *data8 = (uint8_t *)src;
410 int samples = size_bytes / 2;
411
412 // Process data in batches to reduce the number of conversions and writes
413 for (int j = 0; j < samples; j++) {
414 data8[j] = (32768u + data16[j]) >> 8;
415 }
416
417 if (dac_continuous_write(self->dac_handle, data8, samples, &result, self->cfg.timeout) != ESP_OK) {
418 result = 0;
419 }
420 return result * 2;
421 #else
422 return 0;
423 #endif
424 }
425
426 // Read int16_t data from Analog to Digital Converter
427 // ----------------------------------------------------------
428 // FYI
429 // typedef struct {
430 // union {
431 // struct {
432 // uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
433 // uint16_t channel: 4; /*!<ADC channel index info. */
434 // } type1; /*!<ADC type1 */
435 // struct {
436 // uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
437 // uint16_t channel: 4; /*!<ADC channel index info. For ESP32-S2:
438 // If (channel < ADC_CHANNEL_MAX), The data is valid.
439 // If (channel > ADC_CHANNEL_MAX), The data is invalid. */
440 // uint16_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
441 // } type2; /*!<When the configured output format is 11bit.*/
442 // uint16_t val; /*!<Raw data value */
443 // };
444 // } adc_digi_output_data_t;
445
446 size_t readBytes(uint8_t *dest, size_t size_bytes) {
447 if (dest == nullptr || size_bytes == 0 || self->cfg.channels <= 0) {
448 return 0;
449 }
450 if (self->rx_result_buffer == nullptr || self->rx_result_buffer_bytes == 0) {
451 LOGE("ADC RX scratch buffer is not initialized");
452 return 0;
453 }
454
455 const size_t frame_size_bytes =
456 (size_t)self->cfg.channels * sizeof(int16_t);
457 const size_t frames_requested = size_bytes / frame_size_bytes;
458 if (frames_requested == 0) {
459 return 0;
460 }
461
462 int16_t* result16 = reinterpret_cast<int16_t*>(dest);
463 int frames_provided =
464 self->emitFramesFromFifos(result16, (int)frames_requested);
465
466 while (frames_provided < (int)frames_requested) {
467 uint32_t bytes_read = 0;
468 esp_err_t err = adc_continuous_read(
470 reinterpret_cast<uint8_t*>(self->rx_result_buffer),
471 (uint32_t)self->rx_result_buffer_bytes, &bytes_read,
472 (uint32_t)self->cfg.timeout);
473 if (err != ESP_OK) {
474 if (err != ESP_ERR_TIMEOUT) {
475 LOGE("adc_continuous_read unsuccessful: %d", err);
476 }
477 break;
478 }
479
480 int samples_read = bytes_read / sizeof(adc_digi_output_data_t);
481 if (samples_read <= 0) {
482 break;
483 }
484
486 samples_read)) {
487 break;
488 }
489
490 frames_provided += self->emitFramesFromFifos(
491 result16 + (frames_provided * self->cfg.channels),
492 (int)frames_requested - frames_provided);
493 }
494
495 size_t bytes_provided = (size_t)frames_provided * frame_size_bytes;
496 if (bytes_provided > 0 && self->cfg.is_auto_center_read) {
497 self->auto_center.convert(dest, bytes_provided);
498 }
499 return bytes_provided;
500 }
501
502 protected:
504
505 } io{this};
506
508
509 // Setup Digital to Analog
510 // ----------------------------------------------------------
511 #ifdef HAS_ESP32_DAC
512 bool setup_tx() {
513 dac_continuous_config_t cont_cfg = {
514 .chan_mask = (dac_channel_mask_t)(cfg.channels == 1 ? cfg.dac_mono_channel : DAC_CHANNEL_MASK_ALL),
515 .desc_num = (uint32_t)cfg.buffer_count,
516 .buf_size = (size_t)cfg.buffer_size,
517 .freq_hz = (uint32_t)cfg.sample_rate,
518 .offset = 0,
519 .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
520 .chan_mode = cfg.channels == 1 ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER,
521 };
522 // Allocate continuous channels
523 if (dac_continuous_new_channels(&cont_cfg, &dac_handle) != ESP_OK) {
524 LOGE("new_channels");
525 return false;
526 }
527 if (dac_continuous_enable(dac_handle) != ESP_OK) {
528 LOGE("enable");
529 return false;
530 }
531 return true;
532 }
533 #else
534 bool setup_tx() {
535 LOGE("DAC not supported");
536 return false;
537 }
538 #endif
539
540 // Setup Analog to Digital Converter
541 // ----------------------------------------------------------
542 bool setup_rx() {
543 adc_channel_t adc_channel;
544 int io_pin;
545 esp_err_t err;
546
547 // Check the configuration
548 if (!checkADCChannels()) return false;
549 if (!checkADCSampleRate()) return false;
550 if (!checkADCBitWidth()) return false;
551 if (!checkADCBitsPerSample()) return false;
552
553 if (adc_handle != nullptr) {
554 LOGE("adc unit %u continuous is already initialized. Please call end() first!", cfg.adc_unit);
555 return false;
556 }
557
558 #ifdef ARDUINO
559 // Set periman deinit callback
560 // TODO, currently handled in end() method
561
562 // Set the pins/channels to INIT state
563 for (int i = 0; i < cfg.channels; i++) {
564 adc_channel = cfg.adc_channels[i];
565 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
566 if (!perimanClearPinBus(io_pin)) {
567 LOGE("perimanClearPinBus failed!");
568 return false;
569 }
570 }
571 #endif
572
573 uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
574 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
575 conv_frame_size = adcContinuousAlignFrameSize(conv_frame_size);
576 #endif
577
578 uint32_t rx_max_conv_frame_bytes = adcContinuousMaxConvFrameBytes();
579 uint32_t max_samples_per_frame = adcContinuousMaxResultsPerFrame();
580 if (conv_frame_size > rx_max_conv_frame_bytes) {
581 LOGE(
582 "buffer_size is too big for one ADC DMA frame: %u samples = %u "
583 "bytes, max %u samples / %u bytes",
584 cfg.buffer_size, (unsigned)conv_frame_size,
585 (unsigned)max_samples_per_frame,
586 (unsigned)rx_max_conv_frame_bytes);
587 return false;
588 } else {
589 LOGI(
590 "RX DMA frame: %u conversion results, %u bytes (max %u results / "
591 "%u bytes)",
592 cfg.buffer_size, (unsigned)conv_frame_size,
593 (unsigned)max_samples_per_frame,
594 (unsigned)rx_max_conv_frame_bytes);
595 }
596
597 // Create adc_continuous handle
598 adc_continuous_handle_cfg_t adc_config;
599 uint32_t rx_frame_count = cfg.buffer_count > 0 ? (uint32_t)cfg.buffer_count : 1U;
600 adc_config.max_store_buf_size = (uint32_t)conv_frame_size * rx_frame_count;
601 adc_config.conv_frame_size = (uint32_t) conv_frame_size;
602#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
603 adc_config.flags.flush_pool = true;
604#endif
605 LOGI("RX pool: %u frames, %u bytes", (unsigned)rx_frame_count,
606 (unsigned)adc_config.max_store_buf_size);
607 err = adc_continuous_new_handle(&adc_config, &adc_handle);
608 if (err != ESP_OK) {
609 LOGE("adc_continuous_new_handle failed with error: %d", err);
610 return false;
611 } else {
612 LOGI("adc_continuous_new_handle successful");
613 }
614
615 // Configure the ADC patterns
616 adc_digi_pattern_config_t adc_pattern[cfg.channels] = {};
617 for (int i = 0; i < cfg.channels; i++) {
618 uint8_t ch = cfg.adc_channels[i];
619 adc_pattern[i].atten = (uint8_t) cfg.adc_attenuation;
620 adc_pattern[i].channel = (uint8_t)ch;
621 adc_pattern[i].unit = (uint8_t) cfg.adc_unit;
622 adc_pattern[i].bit_width = (uint8_t) cfg.adc_bit_width;
623 }
624
625 // Configure the ADC
626 adc_continuous_config_t dig_cfg = {
627 .pattern_num = (uint32_t) cfg.channels,
628 .adc_pattern = adc_pattern,
629 .sample_freq_hz = (uint32_t)cfg.sample_rate * cfg.channels,
630 .conv_mode = (adc_digi_convert_mode_t) cfg.adc_conversion_mode,
631 .format = (adc_digi_output_format_t) cfg.adc_output_type,
632 };
633
634 // Log the configuration
635 LOGI("dig_cfg.sample_freq_hz: %u", (unsigned)dig_cfg.sample_freq_hz);
636 LOGI("dig_cfg.conv_mode: %u (1: unit 1, 2: unit 2, 3: both)", dig_cfg.conv_mode);
637 LOGI("dig_cfg.format: %u (0 is type1: [12bit data, 4bit channel])", (unsigned)cfg.adc_output_type);
638 for (int i = 0; i < cfg.channels; i++) {
639 LOGI("dig_cfg.adc_pattern[%d].atten: %u", i, dig_cfg.adc_pattern[i].atten);
640 LOGI("dig_cfg.adc_pattern[%d].channel: %u", i, dig_cfg.adc_pattern[i].channel);
641 LOGI("dig_cfg.adc_pattern[%d].unit: %u", i, dig_cfg.adc_pattern[i].unit);
642 LOGI("dig_cfg.adc_pattern[%d].bit_width: %u", i, dig_cfg.adc_pattern[i].bit_width);
643 }
644
645 // Initialize ADC
646 err = adc_continuous_config(adc_handle, &dig_cfg);
647 if (err != ESP_OK) {
648 LOGE("adc_continuous_config unsuccessful with error: %d", err);
649 cleanup_rx();
650 return false;
651 }
652 LOGI("adc_continuous_config successful");
653
654 // Set up optional calibration
655 if (!setupADCCalibration()) {
656 cleanup_rx();
657 return false;
658 }
659
660 // Attach the pins to the ADC unit
661#ifdef ARDUINO
662 for (int i = 0; i < cfg.channels; i++) {
663 adc_channel = cfg.adc_channels[i];
664 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
665 // perimanSetPinBus: uint8_t pin, peripheral_bus_type_t type, void * bus, int8_t bus_num, int8_t bus_channel
666 if (!perimanSetPinBus(io_pin, ESP32_BUS_TYPE_ADC_CONT, (void *)(cfg.adc_unit + 1), cfg.adc_unit, adc_channel)) {
667 LOGE("perimanSetPinBus to Continuous an ADC Unit %u failed!", cfg.adc_unit);
668 cleanup_rx();
669 return false;
670 }
671 rx_pins_attached = i + 1;
672 }
673#endif
674
675 // Start ADC
676 err = adc_continuous_start(adc_handle);
677 if (err != ESP_OK) {
678 LOGE("adc_continuous_start unsuccessful with error: %d", err);
679 cleanup_rx();
680 return false;
681 }
682 rx_started = true;
683
684 // Setup up optimal auto center which puts the avg at 0
686
688 rx_result_buffer_bytes = conv_frame_size;
690 rx_result_buffer_bytes / sizeof(adc_digi_output_data_t);
691 rx_result_buffer = new adc_digi_output_data_t[rx_result_buffer_samples];
692 if (rx_result_buffer == nullptr || rx_result_buffer_samples == 0) {
693 LOGE("Failed to allocate ADC RX scratch buffer");
694 cleanup_rx();
695 return false;
696 }
697 LOGI("ADC RX scratch buffer allocated for %u bytes / %u samples",
699
700 // Keep the reorder FIFOs small: they absorb channel skew only and are
701 // not sized for the caller's full readBytes() window.
702 size_t fifo_size = fifoCapacityFromConvFrameBytes(conv_frame_size);
703 fifo_buffers = new FIFO<ADC_DATA_TYPE>*[cfg.channels](); // Allocate an array of FIFO objects
704 for (int i = 0; i < cfg.channels; ++i) {
705 fifo_buffers[i] = new FIFO<ADC_DATA_TYPE>(fifo_size);
706 }
708 LOGI("%d FIFO buffers allocated of size %u from DMA frame %u bytes",
709 cfg.channels, (unsigned)fifo_size, (unsigned)conv_frame_size);
710
711 LOGI("Setup ADC successful");
712
713 return true;
714 }
715
717 bool cleanup_tx() {
718 bool ok = true;
719#ifdef HAS_ESP32_DAC
720 if (dac_handle==nullptr) return true;
721 if (dac_continuous_disable(dac_handle) != ESP_OK){
722 ok = false;
723 LOGE("dac_continuous_disable failed");
724 }
725 if (dac_continuous_del_channels(dac_handle) != ESP_OK){
726 ok = false;
727 LOGE("dac_continuous_del_channels failed");
728 }
729 dac_handle = nullptr;
730#endif
731 return ok;
732 }
733
734#ifdef ARDUINO
735 // dummy detach: w/o this it's failing
736 static bool adcDetachBus(void *bus) {
737 LOGD("===> adcDetachBus: %d", (int) bus);
738 return true;
739 }
740#endif
741
743 bool cleanup_rx() {
744 bool ok = true;
745 if (adc_handle != nullptr && rx_started) {
746 if (adc_continuous_stop(adc_handle) != ESP_OK) {
747 LOGE("adc_continuous_stop failed");
748 ok = false;
749 }
750 rx_started = false;
751 }
752 if (adc_handle != nullptr) {
753 if (adc_continuous_deinit(adc_handle) != ESP_OK) {
754 LOGE("adc_continuous_deinit failed");
755 ok = false;
756 }
757 adc_handle = nullptr;
758 }
759
763
764#ifdef ARDUINO
765 cleanupAttachedRxPins();
766#endif
767 return ok;
768 }
769
772 if ((cfg.adc_bit_width < SOC_ADC_DIGI_MIN_BITWIDTH) ||
773 (cfg.adc_bit_width > SOC_ADC_DIGI_MAX_BITWIDTH)) {
774 LOGE("adc bit width: %u cannot be set, range: %u to %u", cfg.adc_bit_width,
775 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
776 return false;
777 }
778 LOGI("adc bit width: %u, range: %u to %u", cfg.adc_bit_width,
779 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
780 return true;
781 }
782
785 int io_pin;
786 adc_channel_t adc_channel;
787
788 int max_channels = sizeof(cfg.adc_channels) / sizeof(adc_channel_t);
789 if (cfg.channels > max_channels) {
790 LOGE("number of channels: %d, max: %d", cfg.channels, max_channels);
791 return false;
792 }
793 LOGI("channels: %d, max: %d", cfg.channels, max_channels);
794
795 // Lets make sure the adc channels are available
796 for (int i = 0; i < cfg.channels; i++) {
797 adc_channel = cfg.adc_channels[i];
798 auto err = adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
799 if (err != ESP_OK) {
800 LOGE("ADC channel %u is not available on ADC unit %u", adc_channel, cfg.adc_unit);
801 return false;
802 } else {
803 LOGI("ADC channel %u is on pin %u", adc_channel, io_pin);
804 }
805 }
806 return true;
807 }
808
811 int sample_rate = cfg.sample_rate * cfg.channels;
812 if ((sample_rate < SOC_ADC_SAMPLE_FREQ_THRES_LOW) ||
813 (sample_rate > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)) {
814 LOGE("sample rate eff: %u can not be set, range: %u to %u", sample_rate,
816 return false;
817 }
818 LOGI("sample rate eff: %u, range: %u to %u", sample_rate,
820
821 return true;
822 }
823
826 int supported_bits = 16; // for the time being we support only 16 bits!
827
828 // calculated default value if nothing is specified
829 if (cfg.bits_per_sample == 0) {
830 cfg.bits_per_sample = supported_bits;
831 LOGI("bits per sample set to: %d", cfg.bits_per_sample);
832 }
833
834 // check bits_per_sample
835 if (cfg.bits_per_sample != supported_bits) {
836 LOGE("bits per sample: error. It should be: %d but is %d",
837 supported_bits, cfg.bits_per_sample);
838 return false;
839 }
840 LOGI("bits per sample: %d", cfg.bits_per_sample);
841 return true;
842 }
843
847 return true;
848
849 // Initialize ADC calibration handle
850 // Calibration is applied to an ADC unit (not per channel).
851
852 // setup calibration only when requested
853 esp_err_t err = ESP_OK;
854
855 if (adc_cali_handle_active && adc_cali_handle != nullptr) {
856 return true;
857 }
858
859 if (adc_cali_handle == NULL) {
860 #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
861 // curve fitting is preferred
862 adc_cali_curve_fitting_config_t cali_config;
863 cali_config.unit_id = cfg.adc_unit;
864 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
865 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
866 err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle);
867 #elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
868 // line fitting is the alternative
869 adc_cali_line_fitting_config_t cali_config;
870 cali_config.unit_id = cfg.adc_unit;
871 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
872 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
873 err = adc_cali_create_scheme_line_fitting(&cali_config, &adc_cali_handle);
874 #endif
875 if (err != ESP_OK) {
876 adc_cali_handle = nullptr;
878 LOGE("creating calibration handle failed for ADC%d with atten %d and bitwidth %d",
880 return false;
881 } else {
883 LOGI("enabled calibration for ADC%d with atten %d and bitwidth %d",
885 }
886 }
887 return true;
888 }
889
890};
891
894
895} // namespace audio_tools
896
897#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:397
size_t write(const uint8_t *src, size_t size_bytes) override
Definition AnalogDriverESP32V1.h:403
IO16Bit(AnalogDriverESP32V1 *driver)
Definition AnalogDriverESP32V1.h:399
size_t readBytes(uint8_t *dest, size_t size_bytes)
Definition AnalogDriverESP32V1.h:446
AnalogDriverESP32V1 * self
Definition AnalogDriverESP32V1.h:503
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:771
virtual ~AnalogDriverESP32V1()
Destructor.
Definition AnalogDriverESP32V1.h:27
bool active_tx
Definition AnalogDriverESP32V1.h:178
int16_t getOutputSample(ADC_DATA_TYPE data)
Definition AnalogDriverESP32V1.h:283
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:534
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:330
bool setup_rx()
Definition AnalogDriverESP32V1.h:542
AnalogConfigESP32V1 cfg
Definition AnalogDriverESP32V1.h:176
bool checkADCChannels()
Definition AnalogDriverESP32V1.h:784
void end() override
Definition AnalogDriverESP32V1.h:63
int available() override
Definition AnalogDriverESP32V1.h:97
bool cleanup_tx()
Cleanup dac.
Definition AnalogDriverESP32V1.h:717
bool adc_cali_handle_active
Definition AnalogDriverESP32V1.h:175
bool cleanup_rx()
Cleanup Analog to Digital Converter.
Definition AnalogDriverESP32V1.h:743
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:358
void cleanupScratchBuffer()
Definition AnalogDriverESP32V1.h:246
int getChannelIndex(ADC_CHANNEL_TYPE chan_num) const
Definition AnalogDriverESP32V1.h:228
bool setupADCCalibration()
Definition AnalogDriverESP32V1.h:845
FIFO< ADC_DATA_TYPE > ** fifo_buffers
Definition AnalogDriverESP32V1.h:188
void cleanupADCCalibration()
Definition AnalogDriverESP32V1.h:367
bool checkADCSampleRate()
Definition AnalogDriverESP32V1.h:810
NumberFormatConverterStream converter
Definition AnalogDriverESP32V1.h:507
bool checkADCBitsPerSample()
Definition AnalogDriverESP32V1.h:825
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:298
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:239
bool begin(AudioInfo info, bool isDynamic=false)
Definition BaseConverter.h:259
size_t convert(uint8_t *src, size_t size) override
Definition BaseConverter.h:295
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:58
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:60
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:62