diff --git a/components/driver/i2s/i2s_pdm.c b/components/driver/i2s/i2s_pdm.c index 26b03a1279..4383c36d3f 100644 --- a/components/driver/i2s/i2s_pdm.c +++ b/components/driver/i2s/i2s_pdm.c @@ -106,6 +106,9 @@ static esp_err_t i2s_pdm_tx_set_slot(i2s_chan_handle_t handle, const i2s_pdm_tx_ /* Update the mode info: slot configuration */ i2s_pdm_tx_config_t *pdm_tx_cfg = (i2s_pdm_tx_config_t *)handle->mode_info; memcpy(&(pdm_tx_cfg->slot_cfg), slot_cfg, sizeof(i2s_pdm_tx_slot_config_t)); + /* Update the slot bit width to the actual slot bit width */ + pdm_tx_cfg->slot_cfg.slot_bit_width = (int)pdm_tx_cfg->slot_cfg.slot_bit_width < (int)pdm_tx_cfg->slot_cfg.data_bit_width ? + pdm_tx_cfg->slot_cfg.data_bit_width : pdm_tx_cfg->slot_cfg.slot_bit_width; portENTER_CRITICAL(&g_i2s.spinlock); /* Configure the hardware to apply PDM format */ @@ -285,7 +288,7 @@ esp_err_t i2s_channel_reconfig_pdm_tx_slot(i2s_chan_handle_t handle, const i2s_p /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; - if (pdm_tx_cfg->slot_cfg.slot_bit_width == slot_bits) { + if (pdm_tx_cfg->slot_cfg.slot_bit_width != slot_bits) { ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_clock(handle, &pdm_tx_cfg->clk_cfg), err, TAG, "update clock failed"); } @@ -392,6 +395,9 @@ static esp_err_t i2s_pdm_rx_set_slot(i2s_chan_handle_t handle, const i2s_pdm_rx_ /* Update the mode info: slot configuration */ i2s_pdm_rx_config_t *pdm_rx_cfg = (i2s_pdm_rx_config_t *)handle->mode_info; memcpy(&(pdm_rx_cfg->slot_cfg), slot_cfg, sizeof(i2s_pdm_rx_slot_config_t)); + /* Update the slot bit width to the actual slot bit width */ + pdm_rx_cfg->slot_cfg.slot_bit_width = (int)pdm_rx_cfg->slot_cfg.slot_bit_width < (int)pdm_rx_cfg->slot_cfg.data_bit_width ? + pdm_rx_cfg->slot_cfg.data_bit_width : pdm_rx_cfg->slot_cfg.slot_bit_width; portENTER_CRITICAL(&g_i2s.spinlock); /* Configure the hardware to apply PDM format */ @@ -569,7 +575,7 @@ esp_err_t i2s_channel_reconfig_pdm_rx_slot(i2s_chan_handle_t handle, const i2s_p /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; - if (pdm_rx_cfg->slot_cfg.slot_bit_width == slot_bits) { + if (pdm_rx_cfg->slot_cfg.slot_bit_width != slot_bits) { ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_clock(handle, &pdm_rx_cfg->clk_cfg), err, TAG, "update clock failed"); } diff --git a/components/driver/i2s/i2s_std.c b/components/driver/i2s/i2s_std.c index d3468622c6..4634041e1e 100644 --- a/components/driver/i2s/i2s_std.c +++ b/components/driver/i2s/i2s_std.c @@ -133,6 +133,9 @@ static esp_err_t i2s_std_set_slot(i2s_chan_handle_t handle, const i2s_std_slot_c /* Update the mode info: slot configuration */ i2s_std_config_t *std_cfg = (i2s_std_config_t *)(handle->mode_info); memcpy(&(std_cfg->slot_cfg), slot_cfg, sizeof(i2s_std_slot_config_t)); + /* Update the slot bit width to the actual slot bit width */ + std_cfg->slot_cfg.slot_bit_width = (int)std_cfg->slot_cfg.slot_bit_width < (int)std_cfg->slot_cfg.data_bit_width ? + std_cfg->slot_cfg.data_bit_width : std_cfg->slot_cfg.slot_bit_width; return ESP_OK; } @@ -325,7 +328,7 @@ esp_err_t i2s_channel_reconfig_std_slot(i2s_chan_handle_t handle, const i2s_std_ /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; - if (std_cfg->slot_cfg.slot_bit_width == slot_bits) { + if (std_cfg->slot_cfg.slot_bit_width != slot_bits) { ESP_GOTO_ON_ERROR(i2s_std_set_clock(handle, &std_cfg->clk_cfg), err, TAG, "update clock failed"); } diff --git a/components/driver/i2s/i2s_tdm.c b/components/driver/i2s/i2s_tdm.c index f10d7a60fe..3db1de5303 100644 --- a/components/driver/i2s/i2s_tdm.c +++ b/components/driver/i2s/i2s_tdm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -141,6 +141,9 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c /* Update the mode info: slot configuration */ i2s_tdm_config_t *tdm_cfg = (i2s_tdm_config_t *)(handle->mode_info); memcpy(&(tdm_cfg->slot_cfg), slot_cfg, sizeof(i2s_tdm_slot_config_t)); + /* Update the slot bit width to the actual slot bit width */ + tdm_cfg->slot_cfg.slot_bit_width = (int)tdm_cfg->slot_cfg.slot_bit_width < (int)tdm_cfg->slot_cfg.data_bit_width ? + tdm_cfg->slot_cfg.data_bit_width : tdm_cfg->slot_cfg.slot_bit_width; return ESP_OK; } @@ -333,7 +336,7 @@ esp_err_t i2s_channel_reconfig_tdm_slot(i2s_chan_handle_t handle, const i2s_tdm_ /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; - if (tdm_cfg->slot_cfg.slot_bit_width == slot_bits) { + if (tdm_cfg->slot_cfg.slot_bit_width != slot_bits) { ESP_GOTO_ON_ERROR(i2s_tdm_set_clock(handle, &tdm_cfg->clk_cfg), err, TAG, "update clock failed"); } diff --git a/components/driver/i2s/include/driver/i2s_pdm.h b/components/driver/i2s/include/driver/i2s_pdm.h index 26efd8c06f..e8280d6fdf 100644 --- a/components/driver/i2s/include/driver/i2s_pdm.h +++ b/components/driver/i2s/include/driver/i2s_pdm.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/driver/i2s/include/driver/i2s_std.h b/components/driver/i2s/include/driver/i2s_std.h index 263b69b7d4..038ff2825a 100644 --- a/components/driver/i2s/include/driver/i2s_std.h +++ b/components/driver/i2s/include/driver/i2s_std.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -193,6 +193,7 @@ extern "C" { I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) // Alias /** @endcond */ +#if SOC_I2S_HW_VERSION_1 /** * @brief I2S default standard clock configuration * @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while using 24 bits data width @@ -204,6 +205,20 @@ extern "C" { .clk_src = I2S_CLK_SRC_DEFAULT, \ .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ } +#else +/** + * @brief I2S default standard clock configuration + * @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while using 24 bits data width + * Otherwise the sample rate might be imprecise since the BCLK division is not a integer + * @param rate sample rate + */ +#define I2S_STD_CLK_DEFAULT_CONFIG(rate) { \ + .sample_rate_hz = rate, \ + .clk_src = I2S_CLK_SRC_DEFAULT, \ + .ext_clk_freq_hz = 0, \ + .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ +} +#endif /** * @brief I2S slot configuration for standard mode diff --git a/components/driver/i2s/include/driver/i2s_tdm.h b/components/driver/i2s/include/driver/i2s_tdm.h index b71f3be79d..48b78fcef9 100644 --- a/components/driver/i2s/include/driver/i2s_tdm.h +++ b/components/driver/i2s/include/driver/i2s_tdm.h @@ -123,6 +123,7 @@ extern "C" { #define I2S_TDM_CLK_DEFAULT_CONFIG(rate) { \ .sample_rate_hz = rate, \ .clk_src = I2S_CLK_SRC_DEFAULT, \ + .ext_clk_freq_hz = 0, \ .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ .bclk_div = 8, \ } diff --git a/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt b/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt index 59cbf3f832..6352c97b6f 100644 --- a/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt +++ b/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt @@ -6,6 +6,10 @@ if(CONFIG_SOC_I2C_SUPPORTED) list(APPEND srcs test_i2c_lcd.cpp) endif() +if(CONFIG_SOC_I2S_SUPPORTED) + list(APPEND srcs test_i2s.cpp) +endif() + idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "." PRIV_REQUIRES driver esp_lcd diff --git a/tools/test_apps/system/cxx_build_test/main/test_i2s.cpp b/tools/test_apps/system/cxx_build_test/main/test_i2s.cpp new file mode 100644 index 0000000000..018b84936d --- /dev/null +++ b/tools/test_apps/system/cxx_build_test/main/test_i2s.cpp @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "soc/soc_caps.h" +#include "driver/i2s_std.h" +#if SOC_I2S_SUPPORTS_TDM +#include "driver/i2s_tdm.h" +#endif +#if SOC_I2S_SUPPORTS_PDM +#include "driver/i2s_pdm.h" +#endif + +/** + * Check that C-style designated initializers are valid in C++ file. + */ +void test_i2s_initializers(void) +{ + i2s_std_clk_config_t std_clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000); + i2s_std_slot_config_t std_philips_slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + i2s_std_slot_config_t std_msb_slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + i2s_std_slot_config_t std_pcm_slot_cfg = I2S_STD_PCM_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + (void) std_clk_cfg; + (void) std_philips_slot_cfg; + (void) std_msb_slot_cfg; + (void) std_pcm_slot_cfg; +#if SOC_I2S_SUPPORTS_TDM + i2s_tdm_clk_config_t tdm_clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(16000); + i2s_tdm_slot_config_t tdm_philips_slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, (i2s_tdm_slot_mask_t)0x03); + i2s_tdm_slot_config_t tdm_msb_slot_cfg = I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, (i2s_tdm_slot_mask_t)0x03); + i2s_tdm_slot_config_t tdm_pcm_s_slot_cfg = I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, (i2s_tdm_slot_mask_t)0x03); + i2s_tdm_slot_config_t tdm_pcm_l_slot_cfg = I2S_TDM_PCM_LONG_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, (i2s_tdm_slot_mask_t)0x03); + (void) tdm_clk_cfg; + (void) tdm_philips_slot_cfg; + (void) tdm_msb_slot_cfg; + (void) tdm_pcm_s_slot_cfg; + (void) tdm_pcm_l_slot_cfg; +#endif +#if SOC_I2S_SUPPORTS_PDM_RX + i2s_pdm_rx_clk_config_t pdm_rx_clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(16000); + i2s_pdm_rx_slot_config_t pdm_rx_pcm_slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + (void) pdm_rx_clk_cfg; + (void) pdm_rx_pcm_slot_cfg; +#endif +#if SOC_I2S_SUPPORTS_PDM_TX + i2s_pdm_tx_clk_config_t pdm_tx_clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG(16000); + i2s_pdm_tx_clk_config_t pdm_tx_dac_clk_cfg = I2S_PDM_TX_CLK_DAC_DEFAULT_CONFIG(16000); + i2s_pdm_tx_slot_config_t pdm_tx_pcm_slot_cfg = I2S_PDM_TX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + (void) pdm_tx_clk_cfg; + (void) pdm_tx_dac_clk_cfg; + (void) pdm_tx_pcm_slot_cfg; +#if SOC_I2S_HW_VERSION_2 + i2s_pdm_tx_slot_config_t pdm_tx_pcm_dac_slot_cfg = I2S_PDM_TX_SLOT_DAC_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); + (void) pdm_tx_pcm_dac_slot_cfg; +#endif +#endif +}