44 switch (cfg.rx_tx_mode) {
46 if (!setup_tx())
return false;
48 if (!converter.begin(cfg, 16)) {
55 if (!setup_rx())
return false;
59 LOGE(
"Unsupported MODE: %d", cfg.rx_tx_mode);
87 size_t write(
const uint8_t *src,
size_t size_bytes)
override {
90 return converter.write(src, size_bytes);
95 size_t readBytes(uint8_t *dest,
size_t size_bytes)
override {
98 return io.readBytes(dest, size_bytes);
103 int available()
override {
104 if (!active_rx)
return 0;
105 int buffered = availableFromFifoBytes();
106 return buffered > 0 ? buffered : configuredRxBytes();
118 FIFO() : size_(0), buffer_(
nullptr), head_(0), tail_(0), count_(0) {}
120 FIFO(
size_t size) : size_(size), buffer_(
new T[size]), head_(0), tail_(0), count_(0) {}
127 bool push(
const T& value) {
128 if (count_ < size_) {
129 buffer_[tail_] = value;
131 tail_ = (tail_ + 1) % size_;
142 value = buffer_[head_];
144 head_ = (head_ + 1) % size_;
153 size_t size()
const {
162 return count_ == size_;
179 adc_continuous_handle_t adc_handle =
nullptr;
180 adc_cali_handle_t adc_cali_handle =
nullptr;
181 bool adc_cali_handle_active =
false;
184 bool active_tx =
false;
185 bool active_rx =
false;
186 bool rx_started =
false;
187 int rx_pins_attached = 0;
190 dac_continuous_handle_t dac_handle =
nullptr;
196 int configuredRxBytes()
const {
197 return (cfg.buffer_size > 0) ? (int)(cfg.buffer_size *
sizeof(int16_t)) : 0;
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();
208 return (
int)(min_samples * cfg.
channels *
sizeof(int16_t));
211 void cleanupFifoBuffers() {
212 if (fifo_buffers ==
nullptr)
return;
213 for (
int i = 0; i < cfg.
channels; ++i) {
214 delete fifo_buffers[i];
216 delete[] fifo_buffers;
217 fifo_buffers =
nullptr;
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);
227 adc_cali_handle =
nullptr;
228 adc_cali_handle_active =
false;
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];
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!");
244 rx_pins_attached = 0;
256 size_t write(
const uint8_t *src,
size_t size_bytes)
override {
261 int16_t *data16 = (int16_t *)src;
262 uint8_t *data8 = (uint8_t *)src;
263 int samples = size_bytes / 2;
266 for (
int j = 0; j < samples; j++) {
267 data8[j] = (32768u + data16[j]) >> 8;
270 if (dac_continuous_write(self->dac_handle, data8, samples, &result, self->cfg.timeout) != ESP_OK) {
299 size_t readBytes(uint8_t *dest,
size_t size_bytes) {
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;
309 int samples_provided_per_channel = 0;
310 int data_milliVolts = 0;
312 int samples_requested = size_bytes /
sizeof(int16_t);
313 int samples_requested_per_channel = samples_requested/self->cfg.
channels;
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");
320 memset(result_data, 0, samples_requested *
sizeof(adc_digi_output_data_t));
324 uint16_t *result16 = (uint16_t *)dest;
325 uint16_t *
end = (uint16_t *)(dest + size_bytes);
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)));
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);
341 for (
int j = 0; j < self->cfg.
channels; ++j) {
342 if (self->cfg.adc_channels[j] == chan_num) {
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);
352 LOGE(
"Sample %d, FIFO buffer is full, ch %u, d %u", i, (
unsigned)chan_num, (
unsigned)data);
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]);
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;
373 while (samples_requested_per_channel > min_samples_in_fifo_per_channel) {
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");
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);
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);
393 for (
int j = 0; j < self->cfg.
channels; ++j) {
394 if (self->cfg.adc_channels[j] == chan_num) {
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);
404 LOGE(
"Top Off Sample %d, FIFO buffer is full, ch %u, d %u", i, (
unsigned)chan_num, (
unsigned)data);
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]);
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;
422 if (fifo_size > max_samples_in_fifo_per_channel) {
423 max_samples_in_fifo_per_channel = fifo_size;
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);
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;
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;
439 for (
int i = 0; i < samples_provided_per_channel; i++) {
440 for (
int j = 0; j < self->cfg.
channels; j++) {
442 self->fifo_buffers[j]->pop(data);
443 if (result16 <
end) {
444 if (self->cfg.adc_calibration_active) {
446 auto err = adc_cali_raw_to_voltage(self->adc_cali_handle, (
int)data, &data_milliVolts);
448 *result16 =
static_cast<int16_t
>(data_milliVolts);
450 LOGE(
"adc_cali_raw_to_voltage error: %d", err);
458 LOGE(
"Buffer write overflow, skipping data");
463 bytes_provided = samples_provided_per_channel * self->cfg.
channels *
sizeof(int16_t);
466 if (self->cfg.is_auto_center_read) {
467 self->auto_center.convert(dest, bytes_provided);
471 LOGE(
"adc_continuous_read unsuccessful");
475 return bytes_provided;
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,
495 .clk_src = cfg.use_apll ? DAC_DIGI_CLK_SRC_APLL : DAC_DIGI_CLK_SRC_DEFAULT,
496 .chan_mode = cfg.channels == 1 ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER,
499 if (dac_continuous_new_channels(&cont_cfg, &dac_handle) != ESP_OK) {
500 LOGE(
"new_channels");
503 if (dac_continuous_enable(dac_handle) != ESP_OK) {
511 LOGE(
"DAC not supported");
519 adc_channel_t adc_channel;
529 if (adc_handle !=
nullptr) {
530 LOGE(
"adc unit %u continuous is already initialized. Please call end() first!", cfg.adc_unit);
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!");
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);
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) {
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);
566 "RX DMA frame: %u conversion results, %u bytes (max %u results / "
568 cfg.buffer_size, (
unsigned)conv_frame_size,
569 (
unsigned)max_samples_per_frame,
570 (
unsigned)rx_max_conv_frame_bytes);
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;
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);
585 LOGE(
"adc_continuous_new_handle failed with error: %d", err);
588 LOGI(
"adc_continuous_new_handle successful");
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;
602 adc_continuous_config_t dig_cfg = {
603 .pattern_num = (uint32_t) cfg.
channels,
604 .adc_pattern = adc_pattern,
606 .conv_mode = (adc_digi_convert_mode_t) cfg.adc_conversion_mode,
607 .format = (adc_digi_output_format_t) cfg.adc_output_type,
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);
622 err = adc_continuous_config(adc_handle, &dig_cfg);
624 LOGE(
"adc_continuous_config unsuccessful with error: %d", err);
628 LOGI(
"adc_continuous_config successful");
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);
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);
647 rx_pins_attached = i + 1;
652 err = adc_continuous_start(adc_handle);
654 LOGE(
"adc_continuous_start unsuccessful with error: %d", err);
664 size_t fifo_size = (cfg.buffer_size / cfg.
channels) + 8;
665 fifo_buffers =
new FIFO<ADC_DATA_TYPE>*[cfg.
channels]();
666 for (
int i = 0; i < cfg.
channels; ++i) {
667 fifo_buffers[i] =
new FIFO<ADC_DATA_TYPE>(fifo_size);
669 LOGI(
"%d FIFO buffers allocated of size %d", cfg.
channels, fifo_size);
671 LOGI(
"Setup ADC successful");
680 if (dac_handle==
nullptr)
return true;
681 if (dac_continuous_disable(dac_handle) != ESP_OK){
683 LOGE(
"dac_continuous_disable failed");
685 if (dac_continuous_del_channels(dac_handle) != ESP_OK){
687 LOGE(
"dac_continuous_del_channels failed");
689 dac_handle =
nullptr;
696 static bool adcDetachBus(
void *bus) {
697 LOGD(
"===> adcDetachBus: %d", (
int) bus);
705 if (adc_handle !=
nullptr && rx_started) {
706 if (adc_continuous_stop(adc_handle) != ESP_OK) {
707 LOGE(
"adc_continuous_stop failed");
712 if (adc_handle !=
nullptr) {
713 if (adc_continuous_deinit(adc_handle) != ESP_OK) {
714 LOGE(
"adc_continuous_deinit failed");
717 adc_handle =
nullptr;
720 cleanupADCCalibration();
721 cleanupFifoBuffers();
724 cleanupAttachedRxPins();
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);
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);
745 adc_channel_t adc_channel;
747 int max_channels =
sizeof(cfg.adc_channels) /
sizeof(adc_channel_t);
749 LOGE(
"number of channels: %d, max: %d", cfg.
channels, max_channels);
752 LOGI(
"channels: %d, max: %d", cfg.
channels, max_channels);
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);
759 LOGE(
"ADC channel %u is not available on ADC unit %u", adc_channel, cfg.adc_unit);
762 LOGI(
"ADC channel %u is on pin %u", adc_channel, io_pin);
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);
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);
785 int supported_bits = 16;
795 LOGE(
"bits per sample: error. It should be: %d but is %d",
805 if (!cfg.adc_calibration_active)
812 esp_err_t err = ESP_OK;
814 if (adc_cali_handle_active && adc_cali_handle !=
nullptr) {
818 if (adc_cali_handle == NULL) {
819 #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
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)
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);
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);
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);