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