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 if (bytes_provided > 0 && self->cfg.is_scale_to_16bit &&
501 scaleTo16Bits(dest, bytes_provided, self->cfg.adc_bit_width,
503 }
504 return bytes_provided;
505 }
506
507 protected:
509
510 } io{this};
511
513
514 // Setup Digital to Analog
515 // ----------------------------------------------------------
516 #ifdef HAS_ESP32_DAC
517 bool setup_tx() {
518 dac_continuous_config_t cont_cfg = {
519 .chan_mask = (dac_channel_mask_t)(cfg.channels == 1 ? cfg.dac_mono_channel : DAC_CHANNEL_MASK_ALL),
520 .desc_num = (uint32_t)cfg.buffer_count,
521 .buf_size = (size_t)cfg.buffer_size,
522 .freq_hz = (uint32_t)cfg.sample_rate,
523 .offset = 0,
524 .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
525 .chan_mode = cfg.channels == 1 ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER,
526 };
527 // Allocate continuous channels
528 if (dac_continuous_new_channels(&cont_cfg, &dac_handle) != ESP_OK) {
529 LOGE("new_channels");
530 return false;
531 }
532 if (dac_continuous_enable(dac_handle) != ESP_OK) {
533 LOGE("enable");
534 return false;
535 }
536 return true;
537 }
538 #else
539 bool setup_tx() {
540 LOGE("DAC not supported");
541 return false;
542 }
543 #endif
544
545 // Setup Analog to Digital Converter
546 // ----------------------------------------------------------
547 bool setup_rx() {
548 adc_channel_t adc_channel;
549 int io_pin;
550 esp_err_t err;
551
552 // Check the configuration
553 if (!checkADCChannels()) return false;
554 if (!checkADCSampleRate()) return false;
555 if (!checkADCBitWidth()) return false;
556 if (!checkADCBitsPerSample()) return false;
557
558 if (adc_handle != nullptr) {
559 LOGE("adc unit %u continuous is already initialized. Please call end() first!", cfg.adc_unit);
560 return false;
561 }
562
563 #ifdef ARDUINO
564 // Set periman deinit callback
565 // TODO, currently handled in end() method
566
567 // Set the pins/channels to INIT state
568 for (int i = 0; i < cfg.channels; i++) {
569 adc_channel = cfg.adc_channels[i];
570 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
571 if (!perimanClearPinBus(io_pin)) {
572 LOGE("perimanClearPinBus failed!");
573 return false;
574 }
575 }
576 #endif
577
578 uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
579 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
580 conv_frame_size = adcContinuousAlignFrameSize(conv_frame_size);
581 #endif
582
583 uint32_t rx_max_conv_frame_bytes = adcContinuousMaxConvFrameBytes();
584 uint32_t max_samples_per_frame = adcContinuousMaxResultsPerFrame();
585 if (conv_frame_size > rx_max_conv_frame_bytes) {
586 LOGE(
587 "buffer_size is too big for one ADC DMA frame: %u samples = %u "
588 "bytes, max %u samples / %u bytes",
589 cfg.buffer_size, (unsigned)conv_frame_size,
590 (unsigned)max_samples_per_frame,
591 (unsigned)rx_max_conv_frame_bytes);
592 return false;
593 } else {
594 LOGI(
595 "RX DMA frame: %u conversion results, %u bytes (max %u results / "
596 "%u bytes)",
597 cfg.buffer_size, (unsigned)conv_frame_size,
598 (unsigned)max_samples_per_frame,
599 (unsigned)rx_max_conv_frame_bytes);
600 }
601
602 // Create adc_continuous handle
603 adc_continuous_handle_cfg_t adc_config;
604 uint32_t rx_frame_count = cfg.buffer_count > 0 ? (uint32_t)cfg.buffer_count : 1U;
605 adc_config.max_store_buf_size = (uint32_t)conv_frame_size * rx_frame_count;
606 adc_config.conv_frame_size = (uint32_t) conv_frame_size;
607#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
608 adc_config.flags.flush_pool = true;
609#endif
610 LOGI("RX pool: %u frames, %u bytes", (unsigned)rx_frame_count,
611 (unsigned)adc_config.max_store_buf_size);
612 err = adc_continuous_new_handle(&adc_config, &adc_handle);
613 if (err != ESP_OK) {
614 LOGE("adc_continuous_new_handle failed with error: %d", err);
615 return false;
616 } else {
617 LOGI("adc_continuous_new_handle successful");
618 }
619
620 // Configure the ADC patterns
621 adc_digi_pattern_config_t adc_pattern[cfg.channels] = {};
622 for (int i = 0; i < cfg.channels; i++) {
623 uint8_t ch = cfg.adc_channels[i];
624 adc_pattern[i].atten = (uint8_t) cfg.adc_attenuation;
625 adc_pattern[i].channel = (uint8_t)ch;
626 adc_pattern[i].unit = (uint8_t) cfg.adc_unit;
627 adc_pattern[i].bit_width = (uint8_t) cfg.adc_bit_width;
628 }
629
630 // Configure the ADC
631 adc_continuous_config_t dig_cfg = {
632 .pattern_num = (uint32_t) cfg.channels,
633 .adc_pattern = adc_pattern,
634 .sample_freq_hz = (uint32_t)cfg.sample_rate * cfg.channels,
635 .conv_mode = (adc_digi_convert_mode_t) cfg.adc_conversion_mode,
636 .format = (adc_digi_output_format_t) cfg.adc_output_type,
637 };
638
639 // Log the configuration
640 LOGI("dig_cfg.sample_freq_hz: %u", (unsigned)dig_cfg.sample_freq_hz);
641 LOGI("dig_cfg.conv_mode: %u (1: unit 1, 2: unit 2, 3: both)", dig_cfg.conv_mode);
642 LOGI("dig_cfg.format: %u (0 is type1: [12bit data, 4bit channel])", (unsigned)cfg.adc_output_type);
643 for (int i = 0; i < cfg.channels; i++) {
644 LOGI("dig_cfg.adc_pattern[%d].atten: %u", i, dig_cfg.adc_pattern[i].atten);
645 LOGI("dig_cfg.adc_pattern[%d].channel: %u", i, dig_cfg.adc_pattern[i].channel);
646 LOGI("dig_cfg.adc_pattern[%d].unit: %u", i, dig_cfg.adc_pattern[i].unit);
647 LOGI("dig_cfg.adc_pattern[%d].bit_width: %u", i, dig_cfg.adc_pattern[i].bit_width);
648 }
649
650 // Initialize ADC
651 err = adc_continuous_config(adc_handle, &dig_cfg);
652 if (err != ESP_OK) {
653 LOGE("adc_continuous_config unsuccessful with error: %d", err);
654 cleanup_rx();
655 return false;
656 }
657 LOGI("adc_continuous_config successful");
658
659 // Set up optional calibration
660 if (!setupADCCalibration()) {
661 cleanup_rx();
662 return false;
663 }
664
665 // Attach the pins to the ADC unit
666#ifdef ARDUINO
667 for (int i = 0; i < cfg.channels; i++) {
668 adc_channel = cfg.adc_channels[i];
669 adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
670 // perimanSetPinBus: uint8_t pin, peripheral_bus_type_t type, void * bus, int8_t bus_num, int8_t bus_channel
671 if (!perimanSetPinBus(io_pin, ESP32_BUS_TYPE_ADC_CONT, (void *)(cfg.adc_unit + 1), cfg.adc_unit, adc_channel)) {
672 LOGE("perimanSetPinBus to Continuous an ADC Unit %u failed!", cfg.adc_unit);
673 cleanup_rx();
674 return false;
675 }
676 rx_pins_attached = i + 1;
677 }
678#endif
679
680 // Start ADC
681 err = adc_continuous_start(adc_handle);
682 if (err != ESP_OK) {
683 LOGE("adc_continuous_start unsuccessful with error: %d", err);
684 cleanup_rx();
685 return false;
686 }
687 rx_started = true;
688
689 // Setup up optimal auto center which puts the avg at 0
692 LOGW("is_scale_to_16bit ignored: calibrated values are in mV");
693 }
694
696 rx_result_buffer_bytes = conv_frame_size;
698 rx_result_buffer_bytes / sizeof(adc_digi_output_data_t);
699 rx_result_buffer = new adc_digi_output_data_t[rx_result_buffer_samples];
700 if (rx_result_buffer == nullptr || rx_result_buffer_samples == 0) {
701 LOGE("Failed to allocate ADC RX scratch buffer");
702 cleanup_rx();
703 return false;
704 }
705 LOGI("ADC RX scratch buffer allocated for %u bytes / %u samples",
707
708 // Keep the reorder FIFOs small: they absorb channel skew only and are
709 // not sized for the caller's full readBytes() window.
710 size_t fifo_size = fifoCapacityFromConvFrameBytes(conv_frame_size);
711 fifo_buffers = new FIFO<ADC_DATA_TYPE>*[cfg.channels](); // Allocate an array of FIFO objects
712 for (int i = 0; i < cfg.channels; ++i) {
713 fifo_buffers[i] = new FIFO<ADC_DATA_TYPE>(fifo_size);
714 }
716 LOGI("%d FIFO buffers allocated of size %u from DMA frame %u bytes",
717 cfg.channels, (unsigned)fifo_size, (unsigned)conv_frame_size);
718
719 LOGI("Setup ADC successful");
720
721 return true;
722 }
723
725 bool cleanup_tx() {
726 bool ok = true;
727#ifdef HAS_ESP32_DAC
728 if (dac_handle==nullptr) return true;
729 if (dac_continuous_disable(dac_handle) != ESP_OK){
730 ok = false;
731 LOGE("dac_continuous_disable failed");
732 }
733 if (dac_continuous_del_channels(dac_handle) != ESP_OK){
734 ok = false;
735 LOGE("dac_continuous_del_channels failed");
736 }
737 dac_handle = nullptr;
738#endif
739 return ok;
740 }
741
742#ifdef ARDUINO
743 // dummy detach: w/o this it's failing
744 static bool adcDetachBus(void *bus) {
745 LOGD("===> adcDetachBus: %d", (int) bus);
746 return true;
747 }
748#endif
749
751 bool cleanup_rx() {
752 bool ok = true;
753 if (adc_handle != nullptr && rx_started) {
754 if (adc_continuous_stop(adc_handle) != ESP_OK) {
755 LOGE("adc_continuous_stop failed");
756 ok = false;
757 }
758 rx_started = false;
759 }
760 if (adc_handle != nullptr) {
761 if (adc_continuous_deinit(adc_handle) != ESP_OK) {
762 LOGE("adc_continuous_deinit failed");
763 ok = false;
764 }
765 adc_handle = nullptr;
766 }
767
771
772#ifdef ARDUINO
773 cleanupAttachedRxPins();
774#endif
775 return ok;
776 }
777
780 if ((cfg.adc_bit_width < SOC_ADC_DIGI_MIN_BITWIDTH) ||
781 (cfg.adc_bit_width > SOC_ADC_DIGI_MAX_BITWIDTH)) {
782 LOGE("adc bit width: %u cannot be set, range: %u to %u", cfg.adc_bit_width,
783 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
784 return false;
785 }
786 LOGI("adc bit width: %u, range: %u to %u", cfg.adc_bit_width,
787 (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
788 return true;
789 }
790
793 int io_pin;
794 adc_channel_t adc_channel;
795
796 int max_channels = sizeof(cfg.adc_channels) / sizeof(adc_channel_t);
797 if (cfg.channels > max_channels) {
798 LOGE("number of channels: %d, max: %d", cfg.channels, max_channels);
799 return false;
800 }
801 LOGI("channels: %d, max: %d", cfg.channels, max_channels);
802
803 // Lets make sure the adc channels are available
804 for (int i = 0; i < cfg.channels; i++) {
805 adc_channel = cfg.adc_channels[i];
806 auto err = adc_continuous_channel_to_io(cfg.adc_unit, adc_channel, &io_pin);
807 if (err != ESP_OK) {
808 LOGE("ADC channel %u is not available on ADC unit %u", adc_channel, cfg.adc_unit);
809 return false;
810 } else {
811 LOGI("ADC channel %u is on pin %u", adc_channel, io_pin);
812 }
813 }
814 return true;
815 }
816
819 int sample_rate = cfg.sample_rate * cfg.channels;
820 if ((sample_rate < SOC_ADC_SAMPLE_FREQ_THRES_LOW) ||
821 (sample_rate > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)) {
822 LOGE("sample rate eff: %u can not be set, range: %u to %u", sample_rate,
824 return false;
825 }
826 LOGI("sample rate eff: %u, range: %u to %u", sample_rate,
828
829 return true;
830 }
831
834 int supported_bits = 16; // for the time being we support only 16 bits!
835
836 // calculated default value if nothing is specified
837 if (cfg.bits_per_sample == 0) {
838 cfg.bits_per_sample = supported_bits;
839 LOGI("bits per sample set to: %d", cfg.bits_per_sample);
840 }
841
842 // check bits_per_sample
843 if (cfg.bits_per_sample != supported_bits) {
844 LOGE("bits per sample: error. It should be: %d but is %d",
845 supported_bits, cfg.bits_per_sample);
846 return false;
847 }
848 LOGI("bits per sample: %d", cfg.bits_per_sample);
849 return true;
850 }
851
855 return true;
856
857 // Initialize ADC calibration handle
858 // Calibration is applied to an ADC unit (not per channel).
859
860 // setup calibration only when requested
861 esp_err_t err = ESP_OK;
862
863 if (adc_cali_handle_active && adc_cali_handle != nullptr) {
864 return true;
865 }
866
867 if (adc_cali_handle == NULL) {
868 #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
869 // curve fitting is preferred
870 adc_cali_curve_fitting_config_t cali_config;
871 cali_config.unit_id = cfg.adc_unit;
872 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
873 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
874 err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle);
875 #elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
876 // line fitting is the alternative
877 adc_cali_line_fitting_config_t cali_config;
878 cali_config.unit_id = cfg.adc_unit;
879 cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
880 cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
881 err = adc_cali_create_scheme_line_fitting(&cali_config, &adc_cali_handle);
882 #endif
883 if (err != ESP_OK) {
884 adc_cali_handle = nullptr;
886 LOGE("creating calibration handle failed for ADC%d with atten %d and bitwidth %d",
888 return false;
889 } else {
891 LOGI("enabled calibration for ADC%d with atten %d and bitwidth %d",
893 }
894 }
895 return true;
896 }
897
898};
899
902
903} // namespace audio_tools
904
905#endif
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW
Definition AnalogConfigESP32V1.h:18
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH
Definition AnalogConfigESP32V1.h:15
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#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:172
RxTxMode rx_tx_mode
Definition AnalogConfigESP32V1.h:153
adc_digi_convert_mode_t adc_conversion_mode
Definition AnalogConfigESP32V1.h:169
bool is_auto_center_read
Definition AnalogConfigESP32V1.h:165
TickType_t timeout
Definition AnalogConfigESP32V1.h:154
adc_unit_t adc_unit
Definition AnalogConfigESP32V1.h:174
bool is_scale_to_16bit
Definition AnalogConfigESP32V1.h:168
uint8_t adc_attenuation
Definition AnalogConfigESP32V1.h:171
adc_channel_t adc_channels[NUM_ADC_CHANNELS]
Definition AnalogConfigESP32V1.h:175
bool adc_calibration_active
Definition AnalogConfigESP32V1.h:164
adc_digi_output_format_t adc_output_type
Definition AnalogConfigESP32V1.h:170
int buffer_size
Definition AnalogConfigESP32V1.h:152
Definition AnalogDriverBase.h:9
static void scaleTo16Bits(uint8_t *data, size_t size_bytes, int adc_bits, bool is_centered)
Definition AnalogDriverBase.h:22
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:508
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:779
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:539
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:547
AnalogConfigESP32V1 cfg
Definition AnalogDriverESP32V1.h:176
bool checkADCChannels()
Definition AnalogDriverESP32V1.h:792
void end() override
Definition AnalogDriverESP32V1.h:63
int available() override
Definition AnalogDriverESP32V1.h:97
bool cleanup_tx()
Cleanup dac.
Definition AnalogDriverESP32V1.h:725
bool adc_cali_handle_active
Definition AnalogDriverESP32V1.h:175
bool cleanup_rx()
Cleanup Analog to Digital Converter.
Definition AnalogDriverESP32V1.h:751
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:853
FIFO< ADC_DATA_TYPE > ** fifo_buffers
Definition AnalogDriverESP32V1.h:188
void cleanupADCCalibration()
Definition AnalogDriverESP32V1.h:367
bool checkADCSampleRate()
Definition AnalogDriverESP32V1.h:818
NumberFormatConverterStream converter
Definition AnalogDriverESP32V1.h:512
bool checkADCBitsPerSample()
Definition AnalogDriverESP32V1.h:833
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