diff --git a/components/driver/i2s.c b/components/driver/i2s.c index c7dd573a72..2bb7d74b88 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -403,7 +403,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b //Rate as given to this function is the intended sample rate; //According to the TRM, WS clk equals to the sample rate, and bclk is double the speed of WS uint32_t b_clk = rate * I2S_AD_BCK_FACTOR; - fi2s_clk /= 2; + fi2s_clk /= I2S_AD_BCK_FACTOR; int factor2 = 60; mclk = b_clk * factor2; clkmdiv = ((double) I2S_BASE_CLK) / mclk; @@ -1043,6 +1043,8 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num) adc1_i2s_mode_acquire(); _i2s_adc_mode_recover(); + i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal)); + i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal)); return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } @@ -1052,6 +1054,7 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE); I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE); + i2s_hal_stop_rx(&(p_i2s_obj[i2s_num]->hal)); adc1_lock_release(); return ESP_OK; } diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index 1b8a44eea9..2853ba974c 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -2,6 +2,7 @@ * I2S test environment UT_T1_I2S: * We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed. * connect GPIO18 and GPIO19, GPIO25(ESP32)/GPIO17(ESP32-S2) and GPIO26, GPIO21 and GPIO22(ESP32)/GPIO20(ESP32-S2) + * Please do not connect GPIO32(ESP32)/GPIO5(ESP32-S2) any pull-up resistors externally, it will be used to test i2s adc function. */ #include @@ -22,9 +23,11 @@ #if CONFIG_IDF_TARGET_ESP32 #define MASTER_WS_IO 25 #define DATA_OUT_IO 22 +#define ADC1_CHANNEL_4_IO 32 #elif CONFIG_IDF_TARGET_ESP32S2 #define MASTER_WS_IO 28 #define DATA_OUT_IO 20 +#define ADC1_CHANNEL_4_IO 5 #endif #define PERCENT_DIFF 0.0001 @@ -201,6 +204,61 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") } #if !DISABLED_FOR_TARGETS(ESP32S2) +TEST_CASE("I2S adc test", "[i2s][test_env=UT_T1_I2S]") +{ + // init I2S ADC + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, + .sample_rate = SAMPLE_RATE, + .bits_per_sample = SAMPLE_BITS, + .communication_format = I2S_COMM_FORMAT_PCM, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .intr_alloc_flags = 0, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = 0, + }; + // install and start I2S driver + i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); + // init ADC pad + i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_4); + // enable adc sampling, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11 hard-coded in adc_i2s_mode_init + i2s_adc_enable(I2S_NUM_0); + // init read buffer + uint16_t* i2sReadBuffer = (uint16_t*)calloc(1024, sizeof(uint16_t)); + size_t bytesRead; + + for (int loop = 0; loop < 10; loop++) { + for (int level = 0; level <= 1; level++) { + if (level == 0) { + gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLDOWN_ONLY); + } else { + gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLUP_ONLY); + } + vTaskDelay(200 / portTICK_RATE_MS); + // read data from adc, will block until buffer is full + i2s_read(I2S_NUM_0, (void*)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY); + + // calc average + int64_t adcSumValue = 0; + for (size_t i = 0; i < 1024; i++) { + adcSumValue += i2sReadBuffer[i] & 0xfff; + } + int adcAvgValue = adcSumValue / 1024; + printf("adc average val: %d\n", adcAvgValue); + + if (level == 0) { + TEST_ASSERT_LESS_THAN(100, adcAvgValue); + } else { + TEST_ASSERT_GREATER_THAN(4000, adcAvgValue); + } + } + } + i2s_adc_disable(I2S_NUM_0); + free(i2sReadBuffer); + i2s_driver_uninstall(I2S_NUM_0); +} + /* ESP32S2BETA has only single I2S port and hence following test cases are not applicable */ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_T1_I2S]") { diff --git a/components/soc/soc/esp32/include/soc/i2s_caps.h b/components/soc/soc/esp32/include/soc/i2s_caps.h index 038ac0bc8f..5c111790c9 100644 --- a/components/soc/soc/esp32/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32/include/soc/i2s_caps.h @@ -26,9 +26,10 @@ extern "C" { #define I2S_BASE_CLK (2*APB_CLK_FREQ) // ESP32 have 2 I2S -#define SOC_I2S_NUM (2) +#define SOC_I2S_NUM (2) -#define I2S_SUPPORTS_PDM (1) //ESP32 support PDM +#define I2S_SUPPORTS_PDM (1) // ESP32 support PDM +#define I2S_SUPPORTS_DMA_EQUAL (0) // ESP32 don't support dma equal #ifdef __cplusplus } diff --git a/components/soc/soc/esp32s2/include/soc/i2s_caps.h b/components/soc/soc/esp32s2/include/soc/i2s_caps.h index 95f4ed294d..2432c3a603 100644 --- a/components/soc/soc/esp32s2/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32s2/include/soc/i2s_caps.h @@ -17,12 +17,13 @@ #define APLL_MIN_FREQ (250000000) #define APLL_MAX_FREQ (500000000) #define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware -#define I2S_AD_BCK_FACTOR (1) +#define I2S_AD_BCK_FACTOR (2) #define I2S_PDM_BCK_FACTOR (64) #define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated #define I2S_BASE_CLK (2*APB_CLK_FREQ) // ESP32-S2 have 2 I2S -#define SOC_I2S_NUM (1) +#define SOC_I2S_NUM (1) -#define I2S_SUPPORTS_PDM (0) // ESP32-S2 do not support PDM +#define I2S_SUPPORTS_PDM (0) // ESP32-S2 don't support PDM +#define I2S_SUPPORTS_DMA_EQUAL (1) // ESP32-S2 need dma equal diff --git a/components/soc/src/esp32/include/hal/adc_ll.h b/components/soc/src/esp32/include/hal/adc_ll.h index 019d4164d6..222d4598b4 100644 --- a/components/soc/src/esp32/include/hal/adc_ll.h +++ b/components/soc/src/esp32/include/hal/adc_ll.h @@ -203,18 +203,16 @@ static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t pat */ static inline void adc_ll_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_ll_pattern_table_t pattern) { - uint32_t tab; - uint8_t *arg; + const uint32_t patt_tab_idx = pattern_index / 4; + const uint32_t patt_shift = (3 - (pattern_index % 4)) * 8; + const uint32_t patt_mask = 0xFF << patt_shift; + if (adc_n == ADC_NUM_1) { - tab = SYSCON.saradc_sar1_patt_tab[pattern_index / 4]; - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - SYSCON.saradc_sar1_patt_tab[pattern_index / 4] = tab; + SYSCON.saradc_sar1_patt_tab[patt_tab_idx] &= ~patt_mask; + SYSCON.saradc_sar1_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; } else { // adc_n == ADC_NUM_2 - tab = SYSCON.saradc_sar2_patt_tab[pattern_index / 4]; - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - SYSCON.saradc_sar2_patt_tab[pattern_index / 4] = tab; + SYSCON.saradc_sar2_patt_tab[patt_tab_idx] &= ~patt_mask; + SYSCON.saradc_sar2_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; } } diff --git a/components/soc/src/esp32s2/include/hal/adc_ll.h b/components/soc/src/esp32s2/include/hal/adc_ll.h index 5ad1bd5d56..bf409c89d4 100644 --- a/components/soc/src/esp32s2/include/hal/adc_ll.h +++ b/components/soc/src/esp32s2/include/hal/adc_ll.h @@ -2,7 +2,7 @@ #include "soc/adc_periph.h" #include "hal/adc_types.h" -#include "soc/apb_ctrl_struct.h" +#include "soc/apb_saradc_struct.h" #include #ifdef __cplusplus @@ -83,11 +83,11 @@ typedef enum { static inline void adc_ll_dig_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_CTRL.saradc_fsm_wait.rstb_wait = rst_wait; + APB_SARADC.fsm_wait.rstb_wait = rst_wait; // Internal FSM start wait time - APB_CTRL.saradc_fsm_wait.xpd_wait = start_wait; + APB_SARADC.fsm_wait.xpd_wait = start_wait; // Internal FSM standby wait time - APB_CTRL.saradc_fsm_wait.standby_wait = standby_wait; + APB_SARADC.fsm_wait.standby_wait = standby_wait; } /** @@ -99,7 +99,7 @@ static inline void adc_ll_dig_set_fsm_time(uint32_t rst_wait, uint32_t start_wai */ static inline void adc_ll_dig_set_sample_cycle(uint32_t sample_cycle) { - APB_CTRL.saradc_fsm.sample_cycle = sample_cycle; + APB_SARADC.fsm.sample_cycle = sample_cycle; } /** @@ -109,7 +109,7 @@ static inline void adc_ll_dig_set_sample_cycle(uint32_t sample_cycle) */ static inline void adc_ll_dig_set_output_format(adc_ll_dig_output_format_t format) { - APB_CTRL.saradc_ctrl.data_sar_sel = format; + APB_SARADC.ctrl.data_sar_sel = format; } /** @@ -120,7 +120,7 @@ static inline void adc_ll_dig_set_output_format(adc_ll_dig_output_format_t forma */ static inline void adc_ll_dig_set_convert_limit_num(uint32_t meas_num) { - APB_CTRL.saradc_ctrl2.max_meas_num = meas_num; + APB_SARADC.ctrl2.max_meas_num = meas_num; } /** @@ -129,7 +129,7 @@ static inline void adc_ll_dig_set_convert_limit_num(uint32_t meas_num) */ static inline void adc_ll_dig_convert_limit_enable(void) { - APB_CTRL.saradc_ctrl2.meas_num_limit = 1; + APB_SARADC.ctrl2.meas_num_limit = 1; } /** @@ -138,7 +138,7 @@ static inline void adc_ll_dig_convert_limit_enable(void) */ static inline void adc_ll_dig_convert_limit_disable(void) { - APB_CTRL.saradc_ctrl2.meas_num_limit = 0; + APB_SARADC.ctrl2.meas_num_limit = 0; } /** @@ -151,15 +151,15 @@ static inline void adc_ll_dig_convert_limit_disable(void) static inline void adc_ll_dig_set_convert_mode(adc_ll_convert_mode_t mode) { if (mode == ADC_CONV_SINGLE_UNIT_1) { - APB_CTRL.saradc_ctrl.work_mode = 0; - APB_CTRL.saradc_ctrl.sar_sel = 0; + APB_SARADC.ctrl.work_mode = 0; + APB_SARADC.ctrl.sar_sel = 0; } else if (mode == ADC_CONV_SINGLE_UNIT_2) { - APB_CTRL.saradc_ctrl.work_mode = 0; - APB_CTRL.saradc_ctrl.sar_sel = 1; + APB_SARADC.ctrl.work_mode = 0; + APB_SARADC.ctrl.sar_sel = 1; } else if (mode == ADC_CONV_BOTH_UNIT) { - APB_CTRL.saradc_ctrl.work_mode = 1; + APB_SARADC.ctrl.work_mode = 1; } else if (mode == ADC_CONV_ALTER_UNIT) { - APB_CTRL.saradc_ctrl.work_mode = 2; + APB_SARADC.ctrl.work_mode = 2; } } @@ -171,7 +171,7 @@ static inline void adc_ll_dig_set_convert_mode(adc_ll_convert_mode_t mode) static inline void adc_ll_dig_set_data_source(adc_i2s_source_t src) { /* 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix */ - APB_CTRL.saradc_ctrl.data_to_i2s = src; + APB_SARADC.ctrl.data_to_i2s = src; } /** @@ -186,9 +186,9 @@ static inline void adc_ll_dig_set_data_source(adc_i2s_source_t src) static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t patt_len) { if (adc_n == ADC_NUM_1) { - APB_CTRL.saradc_ctrl.sar1_patt_len = patt_len - 1; + APB_SARADC.ctrl.sar1_patt_len = patt_len - 1; } else { // adc_n == ADC_NUM_2 - APB_CTRL.saradc_ctrl.sar2_patt_len = patt_len - 1; + APB_SARADC.ctrl.sar2_patt_len = patt_len - 1; } } @@ -204,18 +204,17 @@ static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t pat */ static inline void adc_ll_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_ll_pattern_table_t pattern) { - uint32_t tab; - uint8_t *arg; + const uint32_t patt_tab_idx = pattern_index / 4; + const uint32_t patt_shift = (3 - (pattern_index % 4)) * 8; + const uint32_t patt_mask = 0xFF << patt_shift; + if (adc_n == ADC_NUM_1) { - tab = *(uint32_t *)(&APB_CTRL.saradc_sar1_patt_tab1 + pattern_index / 4); - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - *(uint32_t *)(&APB_CTRL.saradc_sar1_patt_tab1 + pattern_index / 4) = tab; - } else { // adc_n == ADC_NUM_2 - tab = *(uint32_t *)(&APB_CTRL.saradc_sar2_patt_tab1 + pattern_index / 4); - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - *(uint32_t *)(&APB_CTRL.saradc_sar2_patt_tab1 + pattern_index / 4) = tab; + APB_SARADC.sar1_patt_tab[patt_tab_idx] &= ~patt_mask; + APB_SARADC.sar1_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; + } + else { // adc_n == ADC_NUM_2 + APB_SARADC.sar2_patt_tab[patt_tab_idx] &= ~patt_mask; + APB_SARADC.sar2_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; } } @@ -390,7 +389,7 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) static inline void adc_ll_set_clk_div(uint32_t div) { /* ADC clock devided from APB clk, e.g. 80 / 2 = 40Mhz, */ - APB_CTRL.saradc_ctrl.sar_clk_div = div; + APB_SARADC.ctrl.sar_clk_div = div; } /** @@ -457,9 +456,9 @@ static inline void adc_ll_rtc_output_invert(adc_ll_num_t adc_n, bool inv_en) static inline void adc_ll_dig_output_invert(adc_ll_num_t adc_n, bool inv_en) { if (adc_n == ADC_NUM_1) { - APB_CTRL.saradc_ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert + APB_SARADC.ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert } else { // adc_n == ADC_NUM_2 - APB_CTRL.saradc_ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert + APB_SARADC.ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert } } diff --git a/components/soc/src/esp32s2/include/hal/i2s_ll.h b/components/soc/src/esp32s2/include/hal/i2s_ll.h index 4156a6c80d..b4f63f1e98 100644 --- a/components/soc/src/esp32s2/include/hal/i2s_ll.h +++ b/components/soc/src/esp32s2/include/hal/i2s_ll.h @@ -353,6 +353,28 @@ static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) hw->conf_chan.rx_chan_mod = val; } +/** + * @brief Set I2S tx dma equal + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx dma equal + */ +static inline void i2s_ll_set_tx_dma_equal(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_dma_equal = val; +} + +/** + * @brief Set I2S rx dma equal + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx dma equal + */ +static inline void i2s_ll_set_rx_dma_equal(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_dma_equal = val; +} + /** * @brief Set I2S out link address * diff --git a/components/soc/src/hal/adc_hal.c b/components/soc/src/hal/adc_hal.c index 9867ed26e8..562e3b7880 100644 --- a/components/soc/src/hal/adc_hal.c +++ b/components/soc/src/hal/adc_hal.c @@ -16,7 +16,6 @@ void adc_hal_init(void) { - adc_ll_set_power_manage(ADC_POWER_BY_FSM); // Set internal FSM wait time, fixed value. adc_ll_dig_set_fsm_time(SOC_ADC_FSM_RSTB_WAIT_DEFAULT, SOC_ADC_FSM_START_WAIT_DEFAULT, SOC_ADC_FSM_STANDBY_WAIT_DEFAULT); diff --git a/components/soc/src/hal/i2s_hal.c b/components/soc/src/hal/i2s_hal.c index 9efec774c7..ca8e725ab7 100644 --- a/components/soc/src/hal/i2s_hal.c +++ b/components/soc/src/hal/i2s_hal.c @@ -32,6 +32,9 @@ void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); } i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#if I2S_SUPPORTS_DMA_EQUAL + i2s_ll_set_tx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#endif } void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits) @@ -42,6 +45,9 @@ void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); } i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#if I2S_SUPPORTS_DMA_EQUAL + i2s_ll_set_rx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#endif } void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t addr) diff --git a/examples/peripherals/i2s_adc_dac/main/app_main.c b/examples/peripherals/i2s_adc_dac/main/app_main.c index a964cde243..075e81e6ff 100644 --- a/examples/peripherals/i2s_adc_dac/main/app_main.c +++ b/examples/peripherals/i2s_adc_dac/main/app_main.c @@ -60,24 +60,24 @@ static const char* TAG = "ad/da"; */ void example_i2s_init(void) { - int i2s_num = EXAMPLE_I2S_NUM; - i2s_config_t i2s_config = { + int i2s_num = EXAMPLE_I2S_NUM; + i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, .sample_rate = EXAMPLE_I2S_SAMPLE_RATE, .bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS, - .communication_format = I2S_COMM_FORMAT_PCM, - .channel_format = EXAMPLE_I2S_FORMAT, - .intr_alloc_flags = 0, - .dma_buf_count = 4, - .dma_buf_len = 1024, - .use_apll = 1, - }; - //install and start i2s driver - i2s_driver_install(i2s_num, &i2s_config, 0, NULL); - //init DAC pad - i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); - //init ADC pad - i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL); + .communication_format = I2S_COMM_FORMAT_PCM, + .channel_format = EXAMPLE_I2S_FORMAT, + .intr_alloc_flags = 0, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = 1, + }; + //install and start i2s driver + i2s_driver_install(i2s_num, &i2s_config, 0, NULL); + //init DAC pad + i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); + //init ADC pad + i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL); } /*