From 2ac4a881ba4bdc5dc7597a98436f5594f09047a1 Mon Sep 17 00:00:00 2001 From: Urs Utzinger Date: Thu, 9 Nov 2023 11:18:17 -0700 Subject: [PATCH] Error handling, boundary check, type fixes, adc-serial (#1045) Merged my changes to data types in ESP32V1: added more log information when setting up continuous ADC, added setting of bits_per_sample based on adc_sample_width, updated base-adc-serial.ino to include custom settings --- .../base-adc-serial/base-adc-serial.ino | 29 ++++++- src/AudioAnalog/AnalogAudioESP32V1.h | 76 +++++++++++++++---- src/AudioAnalog/AnalogConfigESP32V1.h | 18 +++-- src/AudioTools/AudioTypes.h | 15 ++-- 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/examples/examples-basic-api/base-adc-serial/base-adc-serial.ino b/examples/examples-basic-api/base-adc-serial/base-adc-serial.ino index 5d6f6473b0..9f00654d04 100644 --- a/examples/examples-basic-api/base-adc-serial/base-adc-serial.ino +++ b/examples/examples-basic-api/base-adc-serial/base-adc-serial.ino @@ -23,12 +23,33 @@ ConverterScaler scaler(1.0, -26427, 32700 ); // Arduino Setup void setup(void) { + delay(3000); // Give time to boot Serial.begin(115200); + // Include logging to serial + AudioLogger::instance().begin(Serial, AudioLogger::Info); //Warning, Info + Serial.println("starting ADC..."); + auto adcConfig = adc.defaultConfig(RX_MODE); + adcConfig.sample_rate = 44100; + // do not set bits_per_sample as that is configured based on adc_bit_with + adcConfig.adc_bit_width = 12; // this will result in 16 bits_per_sample + adc.begin(adcConfig); - // start i2s input with default configuration - Serial.println("starting I2S-ADC..."); - adc.begin(adc.defaultConfig(RX_MODE)); - + // delay(100); + // if (adcConfig.rx_tx_mode == RX_MODE){ + // Serial.println("Using RX Mode (ADC)"); + // } + // else if (adcConfig.rx_tx_mode == TX_MODE) { + // Serial.println("Using TX Mode (DAC)"); + // } + // Serial.printf("sample_rate is: %u\n", adcConfig.sample_rate); + // Serial.printf("bits_per_sample is: %u\n", adcConfig.bits_per_sample); + // Serial.printf("adc_attenuation is: %u\n", adcConfig.adc_attenuation); + // Serial.printf("adc_bit_width is: %u\n", adcConfig.adc_bit_width); + // Serial.printf("adc mode is: %u\n", adcConfig.adc_conversion_mode); + // Serial.printf("adc format is: %u\n", adcConfig.adc_output_type); + // for(int i=0; i max_channels ){ LOGE("channels: %d, max: %d", cfg.channels, max_channels); return false; - } + } else { + LOGI("channels: %d, max: %d", cfg.channels, max_channels); + } adc_continuous_handle_cfg_t adc_config = { .max_store_buf_size = (uint32_t)cfg.buffer_size * cfg.buffer_count, .conv_frame_size = (uint32_t)cfg.buffer_size / SOC_ADC_DIGI_DATA_BYTES_PER_CONV * SOC_ADC_DIGI_DATA_BYTES_PER_CONV, }; - adc_continuous_new_handle(&adc_config, &adc_handle); + esp_err_t err = adc_continuous_new_handle(&adc_config, &adc_handle); + if (err != ESP_OK){ + LOGE("adc_continuous_new_handle failed with error: %d", err); + return false; + } else { + LOGI("adc_continuous_new_handle successful"); + } + + if ((cfg.sample_rate < SOC_ADC_SAMPLE_FREQ_THRES_LOW) || (cfg.sample_rate > SOC_ADC_SAMPLE_FREQ_THRES_HIGH)){ + LOGE("sample rate: %u can not be set, range: %u to %u", SOC_ADC_SAMPLE_FREQ_THRES_LOW, SOC_ADC_SAMPLE_FREQ_THRES_HIGH); + return false; + } else { + LOGI("sample rate: %u, range: %u to %u",cfg.sample_rate, SOC_ADC_SAMPLE_FREQ_THRES_LOW, SOC_ADC_SAMPLE_FREQ_THRES_HIGH); + } + + if ((cfg.adc_bit_width < SOC_ADC_DIGI_MIN_BITWIDTH) || (cfg.adc_bit_width > SOC_ADC_DIGI_MAX_BITWIDTH)){ + LOGE("adc bit width: %u cannot be set, range: %u to %u", SOC_ADC_DIGI_MIN_BITWIDTH, SOC_ADC_DIGI_MAX_BITWIDTH); + return false; + } else { + LOGI("adc bit width: %u, range: %u to %u", cfg.adc_bit_width, SOC_ADC_DIGI_MIN_BITWIDTH, SOC_ADC_DIGI_MAX_BITWIDTH); + } + + // adjust bits per sample based on adc bit width setting (multiple of 8) + if (cfg.adc_bit_width <= 8) { + cfg.bits_per_sample = 8; + } else if (cfg.adc_bit_width <= 16) { + cfg.bits_per_sample = 16; + } else if(cfg.adc_bit_width <= 24) { + cfg.bits_per_sample = 24; + } else if(cfg.adc_bit_width <= 32) { + cfg.bits_per_sample = 32; + } else { + cfg.bits_per_sample = 16; + } + LOGI("bits per sample: %d", cfg.bits_per_sample); adc_continuous_config_t dig_cfg = { - .sample_freq_hz = (uint32_t)cfg.sample_rate, - .conv_mode = (adc_digi_convert_mode_t)cfg.adc_conversion_mode, - .format = (adc_digi_output_format_t)cfg.adc_output_type, + .sample_freq_hz = cfg.sample_rate, + .conv_mode = cfg.adc_conversion_mode, + .format = cfg.adc_output_type, }; adc_digi_pattern_config_t adc_pattern[cfg.channels] = {0}; dig_cfg.pattern_num = cfg.channels; @@ -222,22 +257,33 @@ class AnalogDriverESP32V1 : public AnalogDriverBase { adc_pattern[i].channel = ch; adc_pattern[i].unit = unit; adc_pattern[i].bit_width = cfg.adc_bit_width; - - LOGI("adc_pattern[%d].atten is :%x", i, adc_pattern[i].atten); - LOGI("adc_pattern[%d].channel is :%x", i, adc_pattern[i].channel); - LOGI("adc_pattern[%d].unit is :%x", i, adc_pattern[i].unit); } dig_cfg.adc_pattern = adc_pattern; - if (adc_continuous_config(adc_handle, &dig_cfg)!=ESP_OK){ - LOGE("adc_continuous_config"); + + LOGI("dig_cfg.sample_freq_hz: %u", dig_cfg.sample_freq_hz); + LOGI("dig_cfg.conv_mode: %u", dig_cfg.conv_mode); + LOGI("dig_cfg.format: %u", dig_cfg.format); + for (int i = 0; i < cfg.channels; i++) { + LOGI("dig_cfg.adc_pattern[%d].atten: %u", i, dig_cfg.adc_pattern[i].atten); + LOGI("dig_cfg.adc_pattern[%d].channel: %u", i, dig_cfg.adc_pattern[i].channel); + LOGI("dig_cfg.adc_pattern[%d].unit: %u", i, dig_cfg.adc_pattern[i].unit); + LOGI("dig_cfg.adc_pattern[%d].bit_width: %u", i, dig_cfg.adc_pattern[i].bit_width); + } + + err = adc_continuous_config(adc_handle, &dig_cfg); + if (err != ESP_OK){ + LOGE("adc_continuous_config unsuccessful with error: %d", err); return false; } + LOGI("adc_continuous_config successful"); - if (adc_continuous_start(adc_handle)!=ESP_OK){ - LOGE("adc_continuous_start"); + err = adc_continuous_start(adc_handle); + if(err != ESP_OK){ + LOGE("adc_continuous_start unsuccessful with error: %d", err); return false; } + LOGI("adc_continuous_start successful"); return true; } diff --git a/src/AudioAnalog/AnalogConfigESP32V1.h b/src/AudioAnalog/AnalogConfigESP32V1.h index 44e4e5980b..ea312a8e99 100644 --- a/src/AudioAnalog/AnalogConfigESP32V1.h +++ b/src/AudioAnalog/AnalogConfigESP32V1.h @@ -11,7 +11,7 @@ #define ADC_CHANNELS {ADC_CHANNEL_6, ADC_CHANNEL_7} #define HAS_ESP32_DAC #elif CONFIG_IDF_TARGET_ESP32S2 -#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT +#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT // might only work with single unit #define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 #define ADC_CHANNELS {ADC_CHANNEL_2, ADC_CHANNEL_3} #define HAS_ESP32_DAC @@ -20,7 +20,7 @@ #define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 #define ADC_CHANNELS {ADC_CHANNEL_2, ADC_CHANNEL_3} #elif CONFIG_IDF_TARGET_ESP32S3 -#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT +#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT // might only work with single unit #define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 #define ADC_CHANNELS {ADC_CHANNEL_2, ADC_CHANNEL_3} #endif @@ -52,12 +52,16 @@ class AnalogConfigESP32V1 : public AudioInfo { bool use_apll = false; // public config parameters - int adc_conversion_mode = ADC_CONV_MODE; - int adc_output_type = ADC_OUTPUT_TYPE; - int adc_attenuation = ADC_ATTEN_DB_0; - int adc_bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; + adc_digi_convert_mode_t adc_conversion_mode = ADC_CONV_MODE; + adc_digi_output_format_t adc_output_type = ADC_OUTPUT_TYPE; + uint8_t adc_attenuation = ADC_ATTEN_DB_0; + uint8_t adc_bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; + uint32_t sample_rate = SOC_ADC_SAMPLE_FREQ_THRES_LOW; /// ESP32: ADC_CHANNEL_6, ADC_CHANNEL_7; others ADC_CHANNEL_2, ADC_CHANNEL_3 adc_channel_t adc_channels[2] = ADC_CHANNELS; + uint32_t channels = 2; + int bits_per_sample = 16; + #ifdef HAS_ESP32_DAC /// ESP32: DAC_CHANNEL_MASK_CH0 or DAC_CHANNEL_MASK_CH1 dac_channel_mask_t dac_mono_channel = DAC_CHANNEL_MASK_CH0; @@ -65,7 +69,7 @@ class AnalogConfigESP32V1 : public AudioInfo { /// Default constructor AnalogConfigESP32V1(RxTxMode rxtxMode=TX_MODE) { sample_rate = 44100; - bits_per_sample = 16; + adc_bit_width = 12; channels = 2; rx_tx_mode = rxtxMode; if (rx_tx_mode == RX_MODE) { diff --git a/src/AudioTools/AudioTypes.h b/src/AudioTools/AudioTypes.h index b354296b08..150cf9d2be 100644 --- a/src/AudioTools/AudioTypes.h +++ b/src/AudioTools/AudioTypes.h @@ -46,6 +46,14 @@ INLINE_VAR const char* TimeUnitStr[] {"MS","US","HZ"}; * @ingroup basic */ struct AudioInfo { + + /// Sample Rate: e.g 44100 + int sample_rate = DEFAULT_SAMPLE_RATE; + /// Number of channels: 2=stereo, 1=mono + int channels = DEFAULT_CHANNELS; + /// Number of bits per sample (int16_t = 16 bits) + int bits_per_sample = DEFAULT_BITS_PER_SAMPLE; + /// Default constructor AudioInfo() = default; @@ -100,13 +108,6 @@ struct AudioInfo { //} } - /// Sample Rate: e.g 44100 - int sample_rate = DEFAULT_SAMPLE_RATE; - /// Number of channels: 2=stereo, 1=mono - int channels = DEFAULT_CHANNELS; - /// Number of bits per sample (int16_t = 16 bits) - int bits_per_sample = DEFAULT_BITS_PER_SAMPLE; - }; /**