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