arduino-audio-tools
AnalogDriverESP32V2.h
1 #pragma once
2 
3 #include "AudioConfig.h"
4 
5 #if defined(ESP32) && defined(USE_ANALOG) && \
6  ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) || 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 
14 #include "AudioTools/CoreAudio/AudioAnalog/AnalogDriverBase.h"
15 #include "AudioTools/CoreAudio/AudioAnalog/AnalogConfigESP32V1.h"
16 #include "AudioTools/CoreAudio/AudioStreams.h"
17 #include "AudioTools/CoreAudio/AudioStreamsConverter.h"
18 
19 namespace audio_tools {
20 
28 class AnalogDriverESP32V1 : public AnalogDriverBase {
29 public:
31  AnalogDriverESP32V1() = default;
32 
34  virtual ~AnalogDriverESP32V1() {
35  end();
36  }
37 
41  TRACEI();
42  bool result = true;
43  this->cfg = cfg;
44 
45  switch (cfg.rx_tx_mode) {
46  case TX_MODE:
47  if (!setup_tx()) return false;
48  // convert to 16 bits
49  if (!converter.begin(cfg, 16)) {
50  LOGE("converter");
51  return false;
52  }
53  active_tx = true;
54  break;
55  case RX_MODE:
56  if (!setup_rx()) return false;
57  active_rx = true;
58  break;
59  default:
60  LOGE("mode");
61  return false;
62  }
63 
64  active = true;
65  return active;
66  }
67 
70  void end() override {
71  TRACEI();
72  if (active_tx) {
73  cleanup_tx();
74  }
75  if (active_rx) {
76  cleanup_rx();
77  }
78 
79  converter.end();
80 
81  active_tx = false;
82  active_rx = false;
83  active = false;
84  }
85 
86  // Writes the data to the Digital to Analog Converter
87  // ----------------------------------------------------------
88  size_t write(const uint8_t *src, size_t size_bytes) override {
89  // TRACED();
90  // convert any format to int16_t
91  return converter.write(src, size_bytes);
92  }
93 
94  // Reads data from DMA buffer of the Analog to Digital Converter
95  // ----------------------------------------------------------
96  size_t readBytes(uint8_t *dest, size_t size_bytes) override {
97  TRACED();
98  // Use the IO16Bit class for reading
99  return io.readBytes(dest, size_bytes);
100  }
101 
102  // How much data will there be available after reading ADC buffer
103  // ----------------------------------------------------------
104  int available() override {
105  return active_rx ? (uint32_t)(cfg.buffer_size * sizeof(int16_t)) : 0;
106  }
107 
108 protected:
109 
110  adc_continuous_handle_t adc_handle = nullptr;
111  adc_cali_handle_t adc_cali_handle = nullptr;
112  AnalogConfigESP32V1 cfg;
113  bool active = false;
114  bool active_tx = false;
115  bool active_rx = false;
116  ConverterAutoCenter auto_center;
117  #ifdef HAS_ESP32_DAC
118  dac_continuous_handle_t dac_handle = nullptr;
119  #endif
120 
121 
122  // 16Bit Audiostream for ESP32
123  // ----------------------------------------------------------
124  class IO16Bit : public AudioStream {
125  public:
126  IO16Bit(AnalogDriverESP32V1 *driver) { self = driver; }
127 
129  size_t write(const uint8_t *src, size_t size_bytes) override {
130  // TRACED();
131 #ifdef HAS_ESP32_DAC
132  size_t result = 0;
133  // Convert signed 16-bit to unsigned 8-bit
134  int16_t *data16 = (int16_t *)src;
135  uint8_t *data8 = (uint8_t *)src;
136  int samples = size_bytes / 2;
137 
138  // Process data in batches to reduce the number of conversions and writes
139  for (int j = 0; j < samples; j++) {
140  data8[j] = (32768u + data16[j]) >> 8;
141  }
142 
143  if (dac_continuous_write(self->dac_handle, data8, samples, &result, self->cfg.timeout) != ESP_OK) {
144  result = 0;
145  }
146  return result * 2;
147 #else
148  return 0;
149 #endif
150  }
151 
153  size_t readBytes(uint8_t *dest, size_t size_bytes) {
154  LOGD("readBytes: %d", (int) size_bytes);
155  size_t result = 0;
156  int channels = self->cfg.channels;
157  assert(channels > 0);
158  sampleIndex.resize(channels);
159  for(int ch=0;ch < channels;ch++){
160  sampleIndex[ch] = 0;
161  }
162  uint16_t *result16 = (uint16_t *)dest; // pointer to the destination buffer
163  int samples_requested = size_bytes / sizeof(int16_t);
164  int samples_requested_per_channel = samples_requested / channels;
165  int buffer_size = samples_requested * sizeof(adc_digi_output_data_t);
166  if (result_data.size() < buffer_size){
167  result_data.resize(buffer_size);
168  }
169 
170  int read_size_bytes = buffer_size;
171 
172  // read the requested bytes into the buffer
173  while (read_size_bytes > 0){
174  uint32_t bytes_read = 0;
175  if (adc_continuous_read(self->adc_handle, (uint8_t *)result_data.data(), (uint32_t)read_size_bytes, &bytes_read, (uint32_t)self->cfg.timeout) == ESP_OK) {
176  int samples_read = bytes_read / sizeof(adc_digi_output_data_t);
177  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)));
178 
179  // Provide samples to dest
180  for (int i = 0; i < samples_read; i++) {
181  adc_digi_output_data_t *p = (adc_digi_output_data_t*) &result_data[i];
182  ADC_CHANNEL_TYPE chan_num = AUDIO_ADC_GET_CHANNEL(p);
183  ADC_DATA_TYPE sample_value = AUDIO_ADC_GET_DATA(p);
184  int channel = getChannelIdx(chan_num);
185 
186  // provide data to dest
187  if (channel >=0 && channel < channels){
188  int idx = channel + (sampleIndex[channel] * channels);
189  LOGI("idx for %d: %d", channel, idx);
190  if(idx < samples_requested){
191  // Provide result in millivolts
192  if (self->cfg.adc_calibration_active) {
193  result16[idx] = getCalibratedValue(sample_value);
194  } else {
195  result16[idx] = sample_value;
196  }
197  // increase index for the actual channel
198  sampleIndex[channel]++;
199  } else {
200  LOGE("Invalid idx: %d / max %d", idx, samples_requested);
201  }
202  } else {
203  LOGE("Invalid channel: %d", channel);
204  }
205  }
207  int samples_available = getMinSamplesForAllChannels(channels);
208  result = samples_available * channels * sizeof(int16_t);
209 
211  read_size_bytes = result - size_bytes;
212  if (read_size_bytes > 0)
213  LOGI("read missing samples: %d", samples_requested_per_channel - samples_available);
214  } else {
215  LOGE("adc_continuous_read error");
216  break;
217  }
218  }
219 
220 
221  // Centering if enabled
222  if (self->cfg.is_auto_center_read) {
223  self->auto_center.convert(dest, result);
224  }
225 
226  return result;
227  }
228 
229  protected:
230  AnalogDriverESP32V1 *self = nullptr;
231  Vector<uint8_t> result_data{0};
232  Vector<int> sampleIndex{0};
233 
234  int getChannelIdx(ADC_CHANNEL_TYPE chan_num){
235  for (int j = 0; j < self->cfg.channels; ++j) {
236  if (self->cfg.adc_channels[j] == chan_num) {
237  return j;
238  }
239  }
240  return -1;
241  }
242 
243  int16_t getCalibratedValue(ADC_DATA_TYPE sample_value){
244  int data_milliVolts = 0;
245  int16_t result = 0;
246  auto err = adc_cali_raw_to_voltage(self->adc_cali_handle, sample_value, &data_milliVolts);
247  if (err == ESP_OK) {
248  result = static_cast<int16_t>(data_milliVolts);
249  } else {
250  LOGE("adc_cali_raw_to_voltage error: %d", err);
251  }
252  return result;
253  }
254 
255  int getMinSamplesForAllChannels(int channels) {
256  int result = 100000;
257  for (int ch = 0; ch < channels; ch++){
258  if (sampleIndex[ch] < result){
259  result = sampleIndex[ch];
260  }
261  }
262  return result;
263  }
264 
265  } io{this};
266 
267  NumberFormatConverterStream converter{io};
268 
269  // Setup Digital to Analog
270  // ----------------------------------------------------------
271  #ifdef HAS_ESP32_DAC
272  bool setup_tx() {
273  dac_continuous_config_t cont_cfg = {
274  .chan_mask = cfg.channels == 1 ? cfg.dac_mono_channel : DAC_CHANNEL_MASK_ALL,
275  .desc_num = (uint32_t)cfg.buffer_count,
276  .buf_size = (size_t)cfg.buffer_size,
277  .freq_hz = (uint32_t)cfg.sample_rate,
278  .offset = 0,
279  .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
280  .chan_mode = DAC_CHANNEL_MODE_ALTER,
281  };
282  // Allocate continuous channels
283  if (dac_continuous_new_channels(&cont_cfg, &dac_handle) != ESP_OK) {
284  LOGE("new_channels");
285  return false;
286  }
287  if (dac_continuous_enable(dac_handle) != ESP_OK) {
288  LOGE("enable");
289  return false;
290  }
291  return true;
292  }
293  #else
294  bool setup_tx() {
295  LOGE("DAC not supported");
296  return false;
297  }
298  #endif
299 
300  // Setup Analog to Digital Converter
301  // ----------------------------------------------------------
302  bool setup_rx() {
303  adc_channel_t adc_channel;
304  int io_pin;
305  esp_err_t err;
306 
307  // Check the configuration
308  if (!checkADCChannels()) return false;
309  if (!checkADCSampleRate()) return false;
310  if (!checkADCBitWidth()) return false;
311  if (!checkADCBitsPerSample()) return false;
312 
313  if (adc_handle != nullptr) {
314  LOGE("adc unit %u continuous is already initialized. Please call end() first!", ADC_UNIT);
315  return false;
316  }
317 
318  #ifdef ARDUINO
319  // Set periman deinit callback
320  // TODO, currently handled in end() method
321 
322  // Set the pins/channels to INIT state
323  for (int i = 0; i < cfg.channels; i++) {
324  adc_channel = cfg.adc_channels[i];
325  adc_continuous_channel_to_io(ADC_UNIT, adc_channel, &io_pin);
326  if (!perimanClearPinBus(io_pin)) {
327  LOGE("perimanClearPinBus failed!");
328  return false;
329  }
330  }
331  #endif
332 
333  // Determine conv_frame_size which must be multiple of SOC_ADC_DIGI_DATA_BYTES_PER_CONV
334  // Old Code
335  uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
336  #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
337  uint8_t calc_multiple = conv_frame_size % SOC_ADC_DIGI_DATA_BYTES_PER_CONV;
338  if (calc_multiple != 0) {
339  conv_frame_size = (uint32_t) (conv_frame_size + calc_multiple);
340  }
341  #endif
342 
343  // Proposed new Code
344  // uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_RESULT_BYTES;
345  // #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
346  // uint32_t conv_frame_size = (uint32_t)cfg.buffer_size * SOC_ADC_DIGI_DATA_BYTES_PER_CONV
347  // #endif
348 
349  // Conversion frame size buffer can't be bigger than 4092 bytes
350  if (conv_frame_size > 4092) {
351  LOGE("buffer_size is too big. Please set lower buffer_size.");
352  return false;
353  } else {
354  LOGI("buffer_size: %u samples, conv_frame_size: %u bytes", cfg.buffer_size, (unsigned)conv_frame_size);
355  }
356 
357  // Create adc_continuous handle
358  adc_continuous_handle_cfg_t adc_config;
359  adc_config.max_store_buf_size = (uint32_t)conv_frame_size * 2;
360  adc_config.conv_frame_size = (uint32_t) conv_frame_size;
361 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
362  adc_config.flags.flush_pool = true;
363 #endif
364  err = adc_continuous_new_handle(&adc_config, &adc_handle);
365  if (err != ESP_OK) {
366  LOGE("adc_continuous_new_handle failed with error: %d", err);
367  return false;
368  } else {
369  LOGI("adc_continuous_new_handle successful");
370  }
371 
372  // Configure the ADC patterns
373  adc_digi_pattern_config_t adc_pattern[cfg.channels] = {};
374  for (int i = 0; i < cfg.channels; i++) {
375  uint8_t ch = cfg.adc_channels[i];
376  adc_pattern[i].atten = (uint8_t) cfg.adc_attenuation;
377  adc_pattern[i].channel = (uint8_t)ch;
378  adc_pattern[i].unit = (uint8_t) ADC_UNIT;
379  adc_pattern[i].bit_width = (uint8_t) cfg.adc_bit_width;
380  }
381 
382  // Configure the ADC
383  adc_continuous_config_t dig_cfg = {
384  .pattern_num = (uint32_t) cfg.channels,
385  .adc_pattern = adc_pattern,
386  .sample_freq_hz = (uint32_t)cfg.sample_rate * cfg.channels,
387  .conv_mode = (adc_digi_convert_mode_t) cfg.adc_conversion_mode,
388  .format = (adc_digi_output_format_t) cfg.adc_output_type,
389  };
390 
391  // Log the configuration
392  LOGI("dig_cfg.sample_freq_hz: %u", (unsigned)dig_cfg.sample_freq_hz);
393  LOGI("dig_cfg.conv_mode: %u (1: unit 1, 2: unit 2, 3: both)", dig_cfg.conv_mode);
394  LOGI("dig_cfg.format: %u (0 is type1: [12bit data, 4bit channel])", dig_cfg.format);
395  for (int i = 0; i < cfg.channels; i++) {
396  LOGI("dig_cfg.adc_pattern[%d].atten: %u", i, dig_cfg.adc_pattern[i].atten);
397  LOGI("dig_cfg.adc_pattern[%d].channel: %u", i, dig_cfg.adc_pattern[i].channel);
398  LOGI("dig_cfg.adc_pattern[%d].unit: %u", i, dig_cfg.adc_pattern[i].unit);
399  LOGI("dig_cfg.adc_pattern[%d].bit_width: %u", i, dig_cfg.adc_pattern[i].bit_width);
400  }
401 
402  // Initialize ADC
403  err = adc_continuous_config(adc_handle, &dig_cfg);
404  if (err != ESP_OK) {
405  LOGE("adc_continuous_config unsuccessful with error: %d", err);
406  return false;
407  }
408  LOGI("adc_continuous_config successful");
409 
410  // Set up optional calibration
411  if (!setupADCCalibration()) {
412  return false;
413  }
414 
415  // Attach the pins to the ADC unit
416 #ifdef ARDUINO
417  for (int i = 0; i < cfg.channels; i++) {
418  adc_channel = cfg.adc_channels[i];
419  adc_continuous_channel_to_io(ADC_UNIT, adc_channel, &io_pin);
420  // perimanSetPinBus: uint8_t pin, peripheral_bus_type_t type, void * bus, int8_t bus_num, int8_t bus_channel
421  if (!perimanSetPinBus(io_pin, ESP32_BUS_TYPE_ADC_CONT, (void *)(ADC_UNIT + 1), ADC_UNIT, adc_channel)) {
422  LOGE("perimanSetPinBus to Continuous an ADC Unit %u failed!", ADC_UNIT);
423  return false;
424  }
425  }
426 #endif
427 
428  // Start ADC
429  err = adc_continuous_start(adc_handle);
430  if (err != ESP_OK) {
431  LOGE("adc_continuous_start unsuccessful with error: %d", err);
432  return false;
433  }
434 
435  // Setup up optimal auto center which puts the avg at 0
436  auto_center.begin(cfg.channels, cfg.bits_per_sample, true);
437 
438  LOGI("Setup ADC successful");
439 
440  return true;
441  }
442 
444  bool cleanup_tx() {
445  bool ok = true;
446 #ifdef HAS_ESP32_DAC
447  if (dac_handle==nullptr) return true;
448  if (dac_continuous_disable(dac_handle) != ESP_OK){
449  ok = false;
450  LOGE("dac_continuous_disable failed");
451  }
452  if (dac_continuous_del_channels(dac_handle) != ESP_OK){
453  ok = false;
454  LOGE("dac_continuous_del_channels failed");
455  }
456  dac_handle = nullptr;
457 #endif
458  return ok;
459  }
460 
461 #ifdef ARDUINO
462  // dummy detach: w/o this it's failing
463  static bool adcDetachBus(void *bus) {
464  LOGD("===> adcDetachBus: %d", (int) bus);
465  return true;
466  }
467 #endif
468 
470  bool cleanup_rx() {
471  if (adc_handle==nullptr) return true;
472  adc_continuous_stop(adc_handle);
473  adc_continuous_deinit(adc_handle);
474  if (cfg.adc_calibration_active) {
475  #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
476  adc_cali_delete_scheme_curve_fitting(adc_cali_handle);
477  #elif !defined(CONFIG_IDF_TARGET_ESP32H2)
478  adc_cali_delete_scheme_line_fitting(adc_cali_handle);
479  #endif
480  }
481 
482 #ifdef ARDUINO
483  // Set all used pins/channels to INIT state
484  perimanSetBusDeinit(ESP32_BUS_TYPE_ADC_CONT, adcDetachBus);
485  for (int i = 0; i < cfg.channels; i++) {
486  adc_channel_t adc_channel = cfg.adc_channels[i];
487  int io_pin;
488  adc_continuous_channel_to_io(ADC_UNIT, adc_channel, &io_pin);
489  if (perimanGetPinBusType(io_pin) == ESP32_BUS_TYPE_ADC_CONT) {
490  if (!perimanClearPinBus(io_pin)) {
491  LOGE("perimanClearPinBus failed!");
492  }
493  }
494  }
495 #endif
496  adc_handle = nullptr;
497  return true; // Return true to indicate successful cleanup
498  }
499 
502  if ((cfg.adc_bit_width < SOC_ADC_DIGI_MIN_BITWIDTH) ||
503  (cfg.adc_bit_width > SOC_ADC_DIGI_MAX_BITWIDTH)) {
504  LOGE("adc bit width: %u cannot be set, range: %u to %u", cfg.adc_bit_width,
505  (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
506  return false;
507  }
508  LOGI("adc bit width: %u, range: %u to %u", cfg.adc_bit_width,
509  (unsigned)SOC_ADC_DIGI_MIN_BITWIDTH, (unsigned)SOC_ADC_DIGI_MAX_BITWIDTH);
510  return true;
511  }
512 
515  int io_pin;
516  adc_channel_t adc_channel;
517 
518  int max_channels = sizeof(cfg.adc_channels) / sizeof(adc_channel_t);
519  if (cfg.channels > max_channels) {
520  LOGE("number of channels: %d, max: %d", cfg.channels, max_channels);
521  return false;
522  }
523  LOGI("channels: %d, max: %d", cfg.channels, max_channels);
524 
525  // Lets make sure the adc channels are available
526  for (int i = 0; i < cfg.channels; i++) {
527  adc_channel = cfg.adc_channels[i];
528  auto err = adc_continuous_channel_to_io(ADC_UNIT, adc_channel, &io_pin);
529  if (err != ESP_OK) {
530  LOGE("ADC channel %u is not available on ADC unit %u", adc_channel, ADC_UNIT);
531  return false;
532  } else {
533  LOGI("ADC channel %u is on pin %u", adc_channel, io_pin);
534  }
535  }
536  return true;
537  }
538 
541  LOGI("sample rate (audio): %d", cfg.sample_rate);
542  int sample_rate = cfg.sample_rate * cfg.channels;
543  if ((sample_rate < SOC_ADC_SAMPLE_FREQ_THRES_LOW) ||
544  (sample_rate > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)) {
545  LOGE("sample rate eff: %u can not be set, range: %u to %u", sample_rate,
546  SOC_ADC_SAMPLE_FREQ_THRES_LOW, SOC_ADC_SAMPLE_FREQ_THRES_HIGH);
547  return false;
548  }
549  LOGI("sample rate eff: %u, range: %u to %u", sample_rate,
550  SOC_ADC_SAMPLE_FREQ_THRES_LOW, SOC_ADC_SAMPLE_FREQ_THRES_HIGH);
551 
552  return true;
553  }
554 
557  int supported_bits = 16; // for the time being we support only 16 bits!
558 
559  // calculated default value if nothing is specified
560  if (cfg.bits_per_sample == 0) {
561  cfg.bits_per_sample = supported_bits;
562  LOGI("bits per sample set to: %d", cfg.bits_per_sample);
563  }
564 
565  // check bits_per_sample
566  if (cfg.bits_per_sample != supported_bits) {
567  LOGE("bits per sample: error. It should be: %d but is %d",
568  supported_bits, cfg.bits_per_sample);
569  return false;
570  }
571  LOGI("bits per sample: %d", cfg.bits_per_sample);
572  return true;
573  }
574 
577  if (!cfg.adc_calibration_active)
578  return true;
579 
580  // Initialize ADC calibration handle
581  // Calibration is applied to an ADC unit (not per channel).
582 
583  // setup calibration only when requested
584  if (adc_cali_handle == NULL) {
585  #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
586  // curve fitting is preferred
587  adc_cali_curve_fitting_config_t cali_config;
588  cali_config.unit_id = ADC_UNIT;
589  cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
590  cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
591  auto err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle);
592  #elif !defined(CONFIG_IDF_TARGET_ESP32H2)
593  // line fitting is the alternative
594  adc_cali_line_fitting_config_t cali_config;
595  cali_config.unit_id = ADC_UNIT;
596  cali_config.atten = (adc_atten_t)cfg.adc_attenuation;
597  cali_config.bitwidth = (adc_bitwidth_t)cfg.adc_bit_width;
598  auto err = adc_cali_create_scheme_line_fitting(&cali_config, &adc_cali_handle);
599  #endif
600  if (err != ESP_OK) {
601  LOGE("creating calibration handle failed for ADC%d with atten %d and bitwidth %d",
602  ADC_UNIT, cfg.adc_attenuation, cfg.adc_bit_width);
603  return false;
604  } else {
605  LOGI("enabled calibration for ADC%d with atten %d and bitwidth %d",
606  ADC_UNIT, cfg.adc_attenuation, cfg.adc_bit_width);
607  }
608  }
609  return true;
610  }
611 
612 };
613 
615 using AnalogDriver = AnalogDriverESP32V1;
616 
617 } // namespace audio_tools
618 
619 #endif
ESP32 specific configuration for i2s input via adc using the adc_continuous API.
Definition: AnalogConfigESP32V1.h:100
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:129
size_t readBytes(uint8_t *dest, size_t size_bytes)
Read int16_t data from ADC.
Definition: AnalogDriverESP32V2.h:153
AnalogAudioStream: A very fast DAC using DMA using the new dac_continuous API.
Definition: AnalogDriverESP32V1.h:28
bool checkADCBitWidth()
Definition: AnalogDriverESP32V1.h:678
virtual ~AnalogDriverESP32V1()
Destructor.
Definition: AnalogDriverESP32V2.h:34
bool checkADCChannels()
Definition: AnalogDriverESP32V1.h:691
void end() override
Definition: AnalogDriverESP32V1.h:70
bool cleanup_tx()
Cleanup dac.
Definition: AnalogDriverESP32V1.h:612
bool cleanup_rx()
Cleanup Analog to Digital Converter.
Definition: AnalogDriverESP32V1.h:638
bool begin(AnalogConfigESP32V1 cfg)
Definition: AnalogDriverESP32V2.h:40
AnalogDriverESP32V1()=default
Default constructor.
AnalogDriverESP32V1()
Default constructor.
Definition: AnalogDriverESP32V1.h:31
bool setupADCCalibration()
Definition: AnalogDriverESP32V1.h:752
bool checkADCSampleRate()
Definition: AnalogDriverESP32V1.h:717
bool checkADCBitsPerSample()
Definition: AnalogDriverESP32V1.h:732
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:872
AnalogDriverArduino AnalogDriver
AnalogAudioStream.
Definition: AnalogDriverArduino.h:48