From 33f490d69c54c3eb4ce886a930b0d1c58fbf2b82 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Thu, 12 Dec 2024 21:28:59 +0800 Subject: [PATCH 1/7] fix(i2s): fixed incorrect buf size calculation --- components/esp_driver_i2s/i2s_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index e4b63a05f3..f5f9e10bf8 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -350,7 +350,11 @@ err: uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uint32_t dma_frame_num) { uint32_t active_chan = handle->active_slot; +#if CONFIG_IDF_TARGET_ESP32 uint32_t bytes_per_sample = ((data_bit_width + 15) / 16) * 2; +#else + uint32_t bytes_per_sample = (data_bit_width + 7) / 8; +#endif // CONFIG_IDF_TARGET_ESP32 uint32_t bytes_per_frame = bytes_per_sample * active_chan; uint32_t bufsize = dma_frame_num * bytes_per_frame; #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE From 9b46827d00f26deec91d8cf8827b9b488ffaab2e Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 17 Dec 2024 14:41:02 +0800 Subject: [PATCH 2/7] fix(i2s): return error when mclk_div is smaller than 2 --- components/esp_driver_i2s/i2s_pdm.c | 8 ++++---- components/esp_driver_i2s/i2s_std.c | 6 ++++-- components/esp_driver_i2s/i2s_tdm.c | 5 +++-- components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c | 4 ++++ .../test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c | 7 +++++++ 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index 9d10058af4..8bbad00d01 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -44,8 +44,8 @@ static esp_err_t i2s_pdm_tx_calculate_clock(i2s_chan_handle_t handle, const i2s_ clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk); clk_info->mclk_div = clk_info->sclk / clk_info->mclk; - /* Check if the configuration is correct */ - ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ + ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); /* Set up sampling configuration */ i2s_ll_tx_set_pdm_fpfs(handle->controller->hal.dev, pdm_tx_clk->up_sample_fp, pdm_tx_clk->up_sample_fs); i2s_ll_tx_set_pdm_over_sample_ratio(handle->controller->hal.dev, over_sample_ratio); @@ -342,8 +342,8 @@ static esp_err_t i2s_pdm_rx_calculate_clock(i2s_chan_handle_t handle, const i2s_ clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk); clk_info->mclk_div = clk_info->sclk / clk_info->mclk; - /* Check if the configuration is correct */ - ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ + ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); /* Set down-sampling configuration */ i2s_ll_rx_set_pdm_dsr(handle->controller->hal.dev, pdm_rx_clk->dn_sample_mode); return ESP_OK; diff --git a/components/esp_driver_i2s/i2s_std.c b/components/esp_driver_i2s/i2s_std.c index 109aaa0bc5..9af481c11d 100644 --- a/components/esp_driver_i2s/i2s_std.c +++ b/components/esp_driver_i2s/i2s_std.c @@ -51,13 +51,15 @@ static esp_err_t i2s_std_calculate_clock(i2s_chan_handle_t handle, const i2s_std #if SOC_I2S_HW_VERSION_2 clk_info->sclk = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ? clk_cfg->ext_clk_freq_hz : i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk); + float min_mclk_div = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ? 0.99 : 1.99; #else clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk); + float min_mclk_div = 1.99; #endif clk_info->mclk_div = clk_info->sclk / clk_info->mclk; - /* Check if the configuration is correct */ - ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large for the current clock source"); + /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ + ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source"); return ESP_OK; } diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index 6d579105ed..37ec447d91 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -61,10 +61,11 @@ static esp_err_t i2s_tdm_calculate_clock(i2s_chan_handle_t handle, const i2s_tdm } clk_info->sclk = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ? clk_cfg->ext_clk_freq_hz : i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk); + float min_mclk_div = clk_cfg->clk_src == I2S_CLK_SRC_EXTERNAL ? 0.99 : 1.99; clk_info->mclk_div = clk_info->sclk / clk_info->mclk; - /* Check if the configuration is correct */ - ESP_RETURN_ON_FALSE(clk_info->mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large for the current clock source"); + /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ + ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source"); return ESP_OK; } diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c index 6a1f7d302d..cf39e5853b 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c @@ -904,7 +904,11 @@ TEST_CASE("I2S_package_lost_test", "[i2s]") TEST_ESP_OK(i2s_channel_register_event_callback(rx_handle, &cbs, &count)); uint32_t test_freq[] = {16000, 32000, 48000, 64000, 96000, 128000, 144000}; +#if CONFIG_IDF_TARGET_ESP32P4 + uint32_t test_num = 4; +#else uint32_t test_num = sizeof(test_freq) / sizeof(uint32_t); +#endif // CONFIG_IDF_TARGET_ESP32P4 uint8_t *data = (uint8_t *)calloc(TEST_RECV_BUF_LEN, sizeof(uint8_t)); size_t bytes_read = 0; int i; diff --git a/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c b/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c index 98700f39b8..aee30f60ad 100644 --- a/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c +++ b/components/esp_driver_i2s/test_apps/i2s_multi_dev/main/test_i2s_multi_dev.c @@ -330,6 +330,13 @@ static void test_i2s_external_clk_src(bool is_master, bool is_external) std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_EXTERNAL; std_cfg.clk_cfg.ext_clk_freq_hz = 22579200; } +#if CONFIG_IDF_TARGET_ESP32P4 + else { + // Use APLL instead. + // Because the default clock source is not sufficient for 22.58M MCLK + std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_APLL; + } +#endif TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &std_cfg)); TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg)); From 85be1550ab6b879d943344ee20a62e4f1f5b8b73 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 18 Dec 2024 11:27:11 +0800 Subject: [PATCH 3/7] docs(example): added troubleshooting for i2s_es8311 example Closes https://github.com/espressif/esp-idf/issues/15047 --- .../peripherals/i2s/i2s_codec/i2s_es8311/README.md | 10 ++++++++++ .../i2s_codec/i2s_es8311/main/Kconfig.projbuild | 7 +++++++ .../i2s/i2s_codec/i2s_es8311/main/example_config.h | 1 + .../i2s_codec/i2s_es8311/main/i2s_es8311_example.c | 14 +++++++++++++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md b/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md index 7bd46beba2..b79ae8b923 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md @@ -129,6 +129,11 @@ If you have a logic analyzer, you can use a logic analyzer to grab GPIO signal d | SDOUT |serial data out| GPIO_NUM_18/2 | | SDIN |serial data in | GPIO_NUM_19/3 | +Other pins like I2C please refer to `example_config.h`. + +Please note that the power amplifier on some development boards (like P4 EV board) are disabled by default, you might need to set the PA_CTRL pin to high to play the music via a speaker. +The PA_CTRL pin can be configured by `idf.py menuconfig`, please check if the PA_CTRL pin is correct on your board if the audio can only be played from the earphones but not the speaker. + ### Customize your own music The example have contained a piece of music in canon.pcm, if you want to play your own music, you can follow these steps: @@ -150,4 +155,9 @@ The example have contained a piece of music in canon.pcm, if you want to play yo * Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs. * The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again. +* Failed to get audio from specker + + * The PA (Power Amplifier) on some dev-kits might be disabled by default, please check the schematic to see if PA_CTRL is connected to any GPIO or something. + * Pull-up the PA_CTRL pin either by setting that GPIO to high or by connecting it to 3.3V with a jump wire should help. + For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/Kconfig.projbuild b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/Kconfig.projbuild index 4595d6e1d8..72ce831be6 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/Kconfig.projbuild +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/Kconfig.projbuild @@ -56,6 +56,13 @@ menu "Example Configuration" help Set voice volume + config EXAMPLE_PA_CTRL_IO + int "Power Amplifier control IO" + default 53 if IDF_TARGET_ESP32P4 + default -1 + help + Set GPIO number for PA control. Set -1 to disable PA control. + config EXAMPLE_BSP bool "Enable Board Support Package (BSP) support" default n diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h index 18d6e09f25..b28e49625f 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h @@ -14,6 +14,7 @@ #define EXAMPLE_MCLK_MULTIPLE (384) // If not using 24-bit data width, 256 should be enough #define EXAMPLE_MCLK_FREQ_HZ (EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE) #define EXAMPLE_VOICE_VOLUME CONFIG_EXAMPLE_VOICE_VOLUME +#define EXAMPLE_PA_CTRL_IO CONFIG_EXAMPLE_PA_CTRL_IO #if CONFIG_EXAMPLE_MODE_ECHO #define EXAMPLE_MIC_GAIN CONFIG_EXAMPLE_MIC_GAIN #endif diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c index 3abbb23efd..4b01208887 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -10,6 +10,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/i2s_std.h" +#include "driver/gpio.h" #include "esp_system.h" #include "esp_check.h" #include "es8311.h" @@ -198,6 +199,17 @@ void app_main(void) } else { ESP_LOGI(TAG, "es8311 codec init success"); } + +#if EXAMPLE_PA_CTRL_IO >= 0 + /* Enable PA by setting the PA_CTRL_IO to high, because the power amplifier on some dev-kits are disabled by default */ + gpio_config_t gpio_cfg = { + .pin_bit_mask = (1ULL << EXAMPLE_PA_CTRL_IO), + .mode = GPIO_MODE_OUTPUT, + }; + ESP_ERROR_CHECK(gpio_config(&gpio_cfg)); + ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PA_CTRL_IO, 1)); +#endif + #if CONFIG_EXAMPLE_MODE_MUSIC /* Play a piece of music in music mode */ xTaskCreate(i2s_music, "i2s_music", 4096, NULL, 5, NULL); From 75fb8bbe049a8d9133e66c7f823b3faa6795e83c Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 10 Dec 2024 16:28:42 +0800 Subject: [PATCH 4/7] refactor(i2s): refactor i2s examples common dependencies Closes https://github.com/espressif/esp-idf/issues/14751 Make the common I2S dependencies as an example common component, so that to avoid slash & backslash issue on windows when use absolute include path. --- .../peripherals/i2s/i2s_basic/i2s_pdm/main/CMakeLists.txt | 4 ++-- .../peripherals/i2s/i2s_basic/i2s_pdm/main/idf_component.yml | 3 +++ .../peripherals/i2s/i2s_basic/i2s_std/main/CMakeLists.txt | 4 ++-- .../peripherals/i2s/i2s_basic/i2s_std/main/idf_component.yml | 3 +++ .../peripherals/i2s/i2s_basic/i2s_tdm/main/CMakeLists.txt | 4 ++-- .../peripherals/i2s/i2s_basic/i2s_tdm/main/idf_component.yml | 3 +++ .../i2s/i2s_codec/i2s_es7210_tdm/main/CMakeLists.txt | 4 ++-- .../i2s/i2s_codec/i2s_es7210_tdm/main/idf_component.yml | 2 ++ .../i2s/i2s_codec/i2s_es8311/main/idf_component.yml | 2 ++ examples/peripherals/i2s/i2s_examples_common/CMakeLists.txt | 2 ++ .../i2s/{common => i2s_examples_common}/format_wav.h | 0 .../i2s/{common => i2s_examples_common}/i2s_example_pins.h | 0 examples/peripherals/i2s/i2s_recorder/main/CMakeLists.txt | 4 ++-- examples/peripherals/i2s/i2s_recorder/main/idf_component.yml | 3 +++ 14 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 examples/peripherals/i2s/i2s_basic/i2s_pdm/main/idf_component.yml create mode 100644 examples/peripherals/i2s/i2s_basic/i2s_std/main/idf_component.yml create mode 100644 examples/peripherals/i2s/i2s_basic/i2s_tdm/main/idf_component.yml create mode 100644 examples/peripherals/i2s/i2s_examples_common/CMakeLists.txt rename examples/peripherals/i2s/{common => i2s_examples_common}/format_wav.h (100%) rename examples/peripherals/i2s/{common => i2s_examples_common}/i2s_example_pins.h (100%) create mode 100644 examples/peripherals/i2s/i2s_recorder/main/idf_component.yml diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/CMakeLists.txt b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/CMakeLists.txt index 09146f7753..e7ac261921 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/CMakeLists.txt +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/CMakeLists.txt @@ -9,5 +9,5 @@ if(CONFIG_SOC_I2S_SUPPORTS_PDM_RX AND CONFIG_EXAMPLE_PDM_RX) endif() idf_component_register(SRCS "${srcs}" - PRIV_REQUIRES esp_driver_i2s esp_driver_gpio - INCLUDE_DIRS "." "$ENV{IDF_PATH}/examples/peripherals/i2s/common") + PRIV_REQUIRES esp_driver_i2s esp_driver_gpio i2s_examples_common + INCLUDE_DIRS ".") diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/idf_component.yml b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/idf_component.yml new file mode 100644 index 0000000000..804fe8e427 --- /dev/null +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + i2s_examples_common: + path: ${IDF_PATH}/examples/peripherals/i2s/i2s_examples_common diff --git a/examples/peripherals/i2s/i2s_basic/i2s_std/main/CMakeLists.txt b/examples/peripherals/i2s/i2s_basic/i2s_std/main/CMakeLists.txt index c5b175d06a..359c4a75dd 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_std/main/CMakeLists.txt +++ b/examples/peripherals/i2s/i2s_basic/i2s_std/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "i2s_std_example_main.c" - PRIV_REQUIRES esp_driver_i2s esp_driver_gpio - INCLUDE_DIRS "." "$ENV{IDF_PATH}/examples/peripherals/i2s/common") + PRIV_REQUIRES esp_driver_i2s esp_driver_gpio i2s_examples_common + INCLUDE_DIRS ".") diff --git a/examples/peripherals/i2s/i2s_basic/i2s_std/main/idf_component.yml b/examples/peripherals/i2s/i2s_basic/i2s_std/main/idf_component.yml new file mode 100644 index 0000000000..804fe8e427 --- /dev/null +++ b/examples/peripherals/i2s/i2s_basic/i2s_std/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + i2s_examples_common: + path: ${IDF_PATH}/examples/peripherals/i2s/i2s_examples_common diff --git a/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/CMakeLists.txt b/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/CMakeLists.txt index 8f5c82b463..0eee02cd78 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/CMakeLists.txt +++ b/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "i2s_tdm_example_main.c" - PRIV_REQUIRES esp_driver_i2s esp_driver_gpio - INCLUDE_DIRS "." "$ENV{IDF_PATH}/examples/peripherals/i2s/common") + PRIV_REQUIRES esp_driver_i2s esp_driver_gpio i2s_examples_common + INCLUDE_DIRS ".") diff --git a/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/idf_component.yml b/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/idf_component.yml new file mode 100644 index 0000000000..804fe8e427 --- /dev/null +++ b/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + i2s_examples_common: + path: ${IDF_PATH}/examples/peripherals/i2s/i2s_examples_common diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/CMakeLists.txt b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/CMakeLists.txt index 0241da8899..c90803d430 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/CMakeLists.txt +++ b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "i2s_es7210_record_example.c" - PRIV_REQUIRES esp_driver_i2s esp_driver_gpio fatfs - INCLUDE_DIRS "$ENV{IDF_PATH}/examples/peripherals/i2s/common" + PRIV_REQUIRES esp_driver_i2s esp_driver_gpio fatfs i2s_examples_common + INCLUDE_DIRS ) diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/idf_component.yml b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/idf_component.yml index da0e4186c8..287056bd51 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/idf_component.yml +++ b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/idf_component.yml @@ -15,3 +15,5 @@ dependencies: # # `public` flag doesn't have an effect dependencies of the `main` component. # # All dependencies of `main` are public by default. # public: true + i2s_examples_common: + path: ${IDF_PATH}/examples/peripherals/i2s/i2s_examples_common diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/idf_component.yml b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/idf_component.yml index ca449b2d62..2091fa5ddd 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/idf_component.yml +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/idf_component.yml @@ -16,3 +16,5 @@ dependencies: # version: "^1" # rules: # - if: "target in [esp32s3]" + i2s_examples_common: + path: ${IDF_PATH}/examples/peripherals/i2s/i2s_examples_common diff --git a/examples/peripherals/i2s/i2s_examples_common/CMakeLists.txt b/examples/peripherals/i2s/i2s_examples_common/CMakeLists.txt new file mode 100644 index 0000000000..404dbefdc4 --- /dev/null +++ b/examples/peripherals/i2s/i2s_examples_common/CMakeLists.txt @@ -0,0 +1,2 @@ +# register I2S common dependencies as a component +idf_component_register(INCLUDE_DIRS ".") diff --git a/examples/peripherals/i2s/common/format_wav.h b/examples/peripherals/i2s/i2s_examples_common/format_wav.h similarity index 100% rename from examples/peripherals/i2s/common/format_wav.h rename to examples/peripherals/i2s/i2s_examples_common/format_wav.h diff --git a/examples/peripherals/i2s/common/i2s_example_pins.h b/examples/peripherals/i2s/i2s_examples_common/i2s_example_pins.h similarity index 100% rename from examples/peripherals/i2s/common/i2s_example_pins.h rename to examples/peripherals/i2s/i2s_examples_common/i2s_example_pins.h diff --git a/examples/peripherals/i2s/i2s_recorder/main/CMakeLists.txt b/examples/peripherals/i2s/i2s_recorder/main/CMakeLists.txt index 805f8fee95..0776d102b5 100644 --- a/examples/peripherals/i2s/i2s_recorder/main/CMakeLists.txt +++ b/examples/peripherals/i2s/i2s_recorder/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "i2s_recorder_main.c" - PRIV_REQUIRES esp_driver_i2s fatfs - INCLUDE_DIRS "$ENV{IDF_PATH}/examples/peripherals/i2s/common") + PRIV_REQUIRES esp_driver_i2s fatfs i2s_examples_common + INCLUDE_DIRS) diff --git a/examples/peripherals/i2s/i2s_recorder/main/idf_component.yml b/examples/peripherals/i2s/i2s_recorder/main/idf_component.yml new file mode 100644 index 0000000000..804fe8e427 --- /dev/null +++ b/examples/peripherals/i2s/i2s_recorder/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + i2s_examples_common: + path: ${IDF_PATH}/examples/peripherals/i2s/i2s_examples_common From c475820f549ce968be93f8d328365c02b842c5e4 Mon Sep 17 00:00:00 2001 From: Gustavo Litovsky Date: Wed, 13 Nov 2024 11:56:44 -0600 Subject: [PATCH 5/7] change(esp32): undo forcing two slots in I2S fix(i2s): fixed the issue in PR 14879 Closes https://github.com/espressif/esp-idf/pull/14879 [Kevin: Update to only remove the limitation for PCM short format] --- components/esp_driver_i2s/i2s_tdm.c | 4 ++-- components/hal/i2s_hal.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index 37ec447d91..c7a8fa4488 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -105,8 +105,8 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c handle->active_slot = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO ? 1 : __builtin_popcount(slot_cfg->slot_mask); uint32_t max_slot_num = 32 - __builtin_clz(slot_cfg->slot_mask); handle->total_slot = slot_cfg->total_slot < max_slot_num ? max_slot_num : slot_cfg->total_slot; - handle->total_slot = handle->total_slot < 2 ? 2 : handle->total_slot; // At least two slots in a frame - + // At least two slots in a frame if not using PCM short format + handle->total_slot = ((handle->total_slot < 2) && (slot_cfg->ws_width != 1)) ? 2 : handle->total_slot; uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 274cef04b0..40613bfb62 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -318,8 +318,8 @@ void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha uint32_t msk = slot_cfg->tdm.slot_mask; /* Get the maximum slot number */ cnt = 32 - __builtin_clz(msk); - /* There should be at least 2 slots in total even for mono mode */ - cnt = cnt < 2 ? 2 : cnt; + /* Except PCM short format (ws_width = 1), there should be at least 2 slots in total even for mono mode */ + cnt = ((cnt < 2) && (slot_cfg->tdm.ws_width != 1)) ? 2 : cnt; uint32_t total_slot = slot_cfg->tdm.total_slot > cnt ? slot_cfg->tdm.total_slot : cnt; i2s_ll_tx_reset(hal->dev); i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave @@ -352,8 +352,8 @@ void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha uint32_t msk = slot_cfg->tdm.slot_mask; /* Get the maximum slot number */ cnt = 32 - __builtin_clz(msk); - /* There should be at least 2 slots in total even for mono mode */ - cnt = cnt < 2 ? 2 : cnt; + /* Except PCM short format (ws_width = 1), there should be at least 2 slots in total even for mono mode */ + cnt = ((cnt < 2) && (slot_cfg->tdm.ws_width != 1)) ? 2 : cnt; uint32_t total_slot = slot_cfg->tdm.total_slot > cnt ? slot_cfg->tdm.total_slot : cnt; i2s_ll_rx_reset(hal->dev); i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave From 01d1aecd190be1e8cb135f15e03131b5a23163b7 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 7 Aug 2024 12:41:35 +0800 Subject: [PATCH 6/7] fix(i2s): fix the es8311 example on P4 Closes https://github.com/espressif/esp-idf/issues/14297 --- .../i2s/i2s_codec/i2s_es8311/main/example_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h index b28e49625f..5c3181c4e2 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h @@ -43,8 +43,8 @@ #define I2S_MCK_IO (GPIO_NUM_13) #define I2S_BCK_IO (GPIO_NUM_12) #define I2S_WS_IO (GPIO_NUM_10) -#define I2S_DO_IO (GPIO_NUM_11) -#define I2S_DI_IO (GPIO_NUM_9) +#define I2S_DO_IO (GPIO_NUM_9) +#define I2S_DI_IO (GPIO_NUM_11) #else #define I2S_MCK_IO (GPIO_NUM_0) #define I2S_BCK_IO (GPIO_NUM_4) From fdc8275b376c49b496877cd1d933cbece3aad7ec Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 23 Dec 2024 12:22:23 +0800 Subject: [PATCH 7/7] fix(i2s): add check for the tdm frame bits num --- components/esp_driver_i2s/i2s_tdm.c | 4 ++++ components/hal/esp32c3/include/hal/i2s_ll.h | 1 + components/hal/esp32c6/include/hal/i2s_ll.h | 1 + components/hal/esp32h2/include/hal/i2s_ll.h | 2 ++ components/hal/esp32p4/include/hal/i2s_ll.h | 2 ++ components/hal/esp32s3/include/hal/i2s_ll.h | 1 + 6 files changed, 11 insertions(+) diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index c7a8fa4488..54eb34c306 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -107,6 +107,10 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c handle->total_slot = slot_cfg->total_slot < max_slot_num ? max_slot_num : slot_cfg->total_slot; // At least two slots in a frame if not using PCM short format handle->total_slot = ((handle->total_slot < 2) && (slot_cfg->ws_width != 1)) ? 2 : handle->total_slot; + uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; + ESP_RETURN_ON_FALSE(handle->total_slot * slot_bits <= I2S_LL_SLOT_FRAME_BIT_MAX, ESP_ERR_INVALID_ARG, TAG, + "total slots(%"PRIu32") * slot_bit_width(%"PRIu32") exceeds the maximum %d", + handle->total_slot, slot_bits, (int)I2S_LL_SLOT_FRAME_BIT_MAX); uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 907324fdd0..009a0d3255 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -33,6 +33,7 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width +#define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2 #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index 62db41ae52..89bd3d1f94 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -33,6 +33,7 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width +#define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2 #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 97837e0056..00f917bf1a 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -33,6 +33,8 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width +/* Add SOC_I2S_TDM_FULL_DATA_WIDTH in the soc_caps to indicate there is no limitation to support full data width (i.e., 16 slots * 32 bits) */ +#define I2S_LL_SLOT_FRAME_BIT_MAX 512 // Up-to 512 bits in one frame, determined by MAX(half_sample_bits) * 2 #define I2S_LL_PLL_F96M_CLK_FREQ (96 * 1000000) // PLL_F96M_CLK: 96MHz #define I2S_LL_PLL_F64M_CLK_FREQ (64 * 1000000) // PLL_F64M_CLK: 64MHz diff --git a/components/hal/esp32p4/include/hal/i2s_ll.h b/components/hal/esp32p4/include/hal/i2s_ll.h index db77686c32..0fca3950a7 100644 --- a/components/hal/esp32p4/include/hal/i2s_ll.h +++ b/components/hal/esp32p4/include/hal/i2s_ll.h @@ -34,6 +34,8 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width +/* Add SOC_I2S_TDM_FULL_DATA_WIDTH in the soc_caps to indicate there is no limitation to support full data width (i.e., 16 slots * 32 bits) */ +#define I2S_LL_SLOT_FRAME_BIT_MAX 512 // Up-to 512 bits in one frame, determined by MAX(half_sample_bits) * 2 #define I2S_LL_XTAL_CLK_FREQ (40 * 1000000) // XTAL_CLK: 40MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_XTAL_CLK_FREQ // No PLL clock source on P4, use XTAL as default diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 9f0ff7ec5a..82677b556d 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -34,6 +34,7 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width +#define I2S_LL_SLOT_FRAME_BIT_MAX 128 // Up-to 128 bits in one frame, determined by MAX(half_sample_bits) * 2 #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT