diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 44399e6641..85bcc8c8ee 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -335,9 +335,16 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b } i2s_stop(i2s_num); - - i2s_hal_set_tx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); +#if SOC_I2S_SUPPORTS_ADC_DAC + /* I2S-ADC only support single channel format. */ + if (!(p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN)) { + i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); + } +#else i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); +#endif + i2s_hal_set_tx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); + if (p_i2s_obj[i2s_num]->channel_num != ch) { p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1; } diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 2a35a21503..01bc1472bc 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -299,6 +299,7 @@ float i2s_get_clk(i2s_port_t i2s_num); /** * @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad, * and set ADC parameters. + * @note In this mode, the ADC maximum sampling rate is 150KHz. Set the sampling rate through ``i2s_config_t``. * @param adc_unit SAR ADC unit index * @param adc_channel ADC channel index * @return diff --git a/components/driver/test/adc_dma_test/test_esp32.c b/components/driver/test/adc_dma_test/test_esp32.c index 27bf9183af..926c54ee62 100644 --- a/components/driver/test/adc_dma_test/test_esp32.c +++ b/components/driver/test/adc_dma_test/test_esp32.c @@ -35,32 +35,25 @@ * ADC DMA testcase */ #include "driver/i2s.h" +#include "test/test_common_adc.h" //i2s number #define EXAMPLE_I2S_NUM (0) //i2s sample rate -#define EXAMPLE_I2S_SAMPLE_RATE (16000) +#define EXAMPLE_I2S_SAMPLE_RATE (150000) //i2s data bits #define EXAMPLE_I2S_SAMPLE_BITS (16) //enable display buffer for debug #define EXAMPLE_I2S_BUF_DEBUG (0) //I2S read buffer length #define EXAMPLE_I2S_READ_LEN (16 * 1024) -//I2S data format -#define EXAMPLE_I2S_FORMAT (I2S_CHANNEL_FMT_RIGHT_LEFT) -//I2S channel number -#define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1)) +//I2S data format, ADC-I2S only support mono. +#define EXAMPLE_I2S_FORMAT I2S_CHANNEL_FMT_ONLY_RIGHT //I2S built-in ADC unit #define I2S_ADC_UNIT ADC_UNIT_1 //I2S built-in ADC channel #define I2S_ADC_CHANNEL ADC1_CHANNEL_4 -//flash record size, for recording 5 seconds' data -#define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5) -#define FLASH_ERASE_SIZE (FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE == 0) ? FLASH_RECORD_SIZE : FLASH_RECORD_SIZE + (FLASH_SECTOR_SIZE - FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE) -//sector size of flash -#define FLASH_SECTOR_SIZE (0x1000) - /** * @brief I2S ADC/DAC mode init. */ @@ -68,15 +61,16 @@ static void example_i2s_init(void) { 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, + .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, .sample_rate = EXAMPLE_I2S_SAMPLE_RATE, .bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS, .channel_format = EXAMPLE_I2S_FORMAT, .intr_alloc_flags = 0, .dma_buf_count = 2, .dma_buf_len = 1024, - .use_apll = 1, + .use_apll = 0, }; + //install and start i2s driver TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) ); //init ADC pad @@ -93,34 +87,73 @@ static void example_i2s_deinit(void) */ static void example_disp_buf(uint8_t *buf, int length) { - printf("======\n"); - for (int i = 0; i < length; i++) { - printf("%02x ", buf[i]); - if ((i + 1) % 8 == 0) { - printf("\n"); + printf("\n======"); + for (int i = 0; i < length; i += 2) { + uint16_t data = ((uint16_t)buf[i+1] << 8) | (uint16_t)buf[i]; + adc_digi_output_data_t *p = (adc_digi_output_data_t *)&data; + if ((i) % 16 == 0) printf("\n"); + printf("[%d_%d] ", p->type1.channel, p->type1.data); + } + printf("\n======\n"); +} + +static esp_err_t adc_dma_data_check(uint8_t *buf, int length, int ideal_level) +{ + for (int i = 0; i < length; i += 2) { + uint16_t data = ((uint16_t)buf[i+1] << 8) | (uint16_t)buf[i]; + adc_digi_output_data_t *p = (adc_digi_output_data_t *)&data; + if (p->type1.channel != I2S_ADC_CHANNEL) { + TEST_FAIL_MESSAGE("I2S-DMA data channel error!"); + } + if (ideal_level == 1) { // high level 3.3v + TEST_ASSERT_EQUAL( 0xFFF, p->type1.data ); + } else if (ideal_level == 0) { // low level 0v + TEST_ASSERT_LESS_THAN( 10, p->type1.data ); + } else if (ideal_level == 2) { // middle level 1.4v + TEST_ASSERT_INT_WITHIN( 128, 1666, p->type1.data ); + } else if (ideal_level == 3) { // normal level + } else { // no check } } - printf("======\n"); + return ESP_OK; +} + +static void adc_dma_read(uint8_t *buf, int length) +{ + size_t bytes_read = 0; + int flash_wr_size = 0; + + vTaskDelay(pdTICKS_TO_MS(100)); + while (flash_wr_size < length) { + //read data from I2S bus, in this case, from ADC. + TEST_ESP_OK( i2s_read(EXAMPLE_I2S_NUM, (void *) buf + flash_wr_size, length - flash_wr_size, &bytes_read, portMAX_DELAY) ); + flash_wr_size += bytes_read; + example_disp_buf((uint8_t *) buf, 128); + } } TEST_CASE("ADC DMA read", "[adc dma]") { - example_i2s_init(); - int i2s_read_len = EXAMPLE_I2S_READ_LEN; - int flash_wr_size = 0; - size_t bytes_read; - char *i2s_read_buff = (char *) calloc(i2s_read_len, sizeof(char)); + + example_i2s_init(); TEST_ESP_OK( i2s_adc_enable(EXAMPLE_I2S_NUM) ); - while (flash_wr_size < FLASH_RECORD_SIZE) { - //read data from I2S bus, in this case, from ADC. - TEST_ESP_OK( i2s_read(EXAMPLE_I2S_NUM, (void *) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY) ); - example_disp_buf((uint8_t *) i2s_read_buff, 64); - //save original data from I2S(ADC) into flash. - flash_wr_size += i2s_read_len; - esp_rom_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE); - } + + adc_fake_tie_low(I2S_ADC_UNIT, I2S_ADC_CHANNEL); + adc_dma_read((uint8_t *)i2s_read_buff, i2s_read_len); + adc_dma_data_check((uint8_t *)i2s_read_buff, i2s_read_len, 0); + + adc_fake_tie_middle(I2S_ADC_UNIT, I2S_ADC_CHANNEL); + adc_dma_read((uint8_t *)i2s_read_buff, i2s_read_len); + adc_dma_data_check((uint8_t *)i2s_read_buff, i2s_read_len, 2); + + adc_fake_tie_high(I2S_ADC_UNIT, I2S_ADC_CHANNEL); + adc_dma_read((uint8_t *)i2s_read_buff, i2s_read_len); + adc_dma_data_check((uint8_t *)i2s_read_buff, i2s_read_len, 1); + + adc_io_normal(I2S_ADC_UNIT, I2S_ADC_CHANNEL); + TEST_ESP_OK( i2s_adc_disable(EXAMPLE_I2S_NUM) ); if (i2s_read_buff) { free(i2s_read_buff); diff --git a/components/driver/test/dac_dma_test/test_esp32.c b/components/driver/test/dac_dma_test/test_esp32.c index 7a02da9281..cecf3f4a0e 100644 --- a/components/driver/test/dac_dma_test/test_esp32.c +++ b/components/driver/test/dac_dma_test/test_esp32.c @@ -57,14 +57,6 @@ //I2S channel number #define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1)) -//flash record size, for recording 5 seconds' data -#define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5) -#define FLASH_ERASE_SIZE (FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE == 0) ? FLASH_RECORD_SIZE : FLASH_RECORD_SIZE + (FLASH_SECTOR_SIZE - FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE) -//sector size of flash -#define FLASH_SECTOR_SIZE (0x1000) -//flash read / write address -#define FLASH_ADDR (0x200000) - /** * @brief I2S ADC/DAC mode init. */ @@ -72,23 +64,24 @@ static void example_i2s_init(void) { 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, + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, .sample_rate = EXAMPLE_I2S_SAMPLE_RATE, .bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS, .channel_format = EXAMPLE_I2S_FORMAT, .intr_alloc_flags = 0, .dma_buf_count = 2, .dma_buf_len = 1024, - .use_apll = 1, + .use_apll = 0, }; //install and start i2s driver TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) ); //init DAC pad - TEST_ESP_OK( i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN) ); + TEST_ESP_OK( i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN) ); } static void example_i2s_deinit(void) { + TEST_ESP_OK( i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE) ); TEST_ESP_OK( i2s_driver_uninstall(EXAMPLE_I2S_NUM) ); } @@ -149,15 +142,16 @@ static void example_reset_play_mode(void) TEST_CASE("DAC DMA output", "[dac]") { - example_i2s_init(); - size_t bytes_written; int i2s_read_len = EXAMPLE_I2S_READ_LEN; uint8_t *i2s_write_buff = (uint8_t *) calloc(i2s_read_len, sizeof(char)); - printf("Playing file example: \n"); int offset = 0; int tot_size = sizeof(audio_table); + printf("Playing file example: \n"); + + example_i2s_init(); example_set_file_play_mode(); + while (offset < tot_size) { int play_len = ((tot_size - offset) > (4 * 1024)) ? (4 * 1024) : (tot_size - offset); int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, (uint8_t *)(audio_table + offset), play_len); @@ -165,7 +159,7 @@ TEST_CASE("DAC DMA output", "[dac]") offset += play_len; example_disp_buf((uint8_t *) i2s_write_buff, 32); } - vTaskDelay(100 / portTICK_PERIOD_MS); + example_reset_play_mode(); free(i2s_write_buff); diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 149b5f195f..2f2b29dacd 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -242,6 +242,9 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config } if (i2s_config->mode & I2S_MODE_ADC_BUILT_IN) { i2s_ll_build_in_adc_ena(hal->dev); + i2s_ll_set_rx_chan_mod(hal->dev, 1); + i2s_ll_set_rx_fifo_mod(hal->dev, 1); + i2s_ll_set_rx_mono(hal->dev, 0); } // Buildin ADC and DAC have nothing to do with communication format configuration. return; diff --git a/components/soc/soc/esp32/include/soc/adc_caps.h b/components/soc/soc/esp32/include/soc/adc_caps.h index e7af39c4fe..66f5d6bb76 100644 --- a/components/soc/soc/esp32/include/soc/adc_caps.h +++ b/components/soc/soc/esp32/include/soc/adc_caps.h @@ -12,7 +12,7 @@ #define SOC_ADC_DIGI_DATA_INVERT_DEFAULT(PERIPH_NUM) (1) #define SOC_ADC_FSM_RSTB_WAIT_DEFAULT (8) -#define SOC_ADC_FSM_START_WAIT_DEFAULT (5) +#define SOC_ADC_FSM_START_WAIT_DEFAULT (SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT * 2) #define SOC_ADC_FSM_STANDBY_WAIT_DEFAULT (100) #define ADC_FSM_SAMPLE_CYCLE_DEFAULT (2) @@ -28,4 +28,4 @@ #define SOC_ADC_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (2) -#define SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT (2) \ No newline at end of file +#define SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT (16) \ No newline at end of file