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