diff --git a/components/driver/i2s/i2s_std.c b/components/driver/i2s/i2s_std.c index 69251c4524..1a70e5852a 100644 --- a/components/driver/i2s/i2s_std.c +++ b/components/driver/i2s/i2s_std.c @@ -58,7 +58,9 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c { esp_err_t ret = ESP_OK; i2s_std_config_t *std_cfg = (i2s_std_config_t *)(handle->mode_info); - ESP_RETURN_ON_FALSE(std_cfg->slot_cfg.data_bit_width != I2S_DATA_BIT_WIDTH_24BIT || + i2s_data_bit_width_t real_slot_bit = (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; + ESP_RETURN_ON_FALSE(real_slot_bit != I2S_DATA_BIT_WIDTH_24BIT || (clk_cfg->mclk_multiple % 3 == 0), ESP_ERR_INVALID_ARG, TAG, "The 'mclk_multiple' should be the multiple of 3 while using 24-bit data width"); diff --git a/components/driver/i2s/i2s_tdm.c b/components/driver/i2s/i2s_tdm.c index a1ea349ee3..b1e89990eb 100644 --- a/components/driver/i2s/i2s_tdm.c +++ b/components/driver/i2s/i2s_tdm.c @@ -93,6 +93,7 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_config_t *slot_cfg) { + ESP_RETURN_ON_FALSE(slot_cfg->slot_mask, ESP_ERR_INVALID_ARG, TAG, "At least one channel should be enabled"); /* Update the total slot num and active slot num */ 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); diff --git a/components/driver/i2s/include/driver/i2s_std.h b/components/driver/i2s/include/driver/i2s_std.h index 1080019e96..6930e3b51a 100644 --- a/components/driver/i2s/include/driver/i2s_std.h +++ b/components/driver/i2s/include/driver/i2s_std.h @@ -145,7 +145,7 @@ extern "C" { .ws_width = bits_per_sample, \ .ws_pol = false, \ .bit_shift = true, \ - .left_align = false, \ + .left_align = true, \ .big_endian = false, \ .bit_order_lsb = false \ } @@ -164,7 +164,7 @@ extern "C" { .ws_width = 1, \ .ws_pol = true, \ .bit_shift = true, \ - .left_align = false, \ + .left_align = true, \ .big_endian = false, \ .bit_order_lsb = false \ } @@ -182,7 +182,7 @@ extern "C" { .ws_width = bits_per_sample, \ .ws_pol = false, \ .bit_shift = false, \ - .left_align = false, \ + .left_align = true, \ .big_endian = false, \ .bit_order_lsb = false \ } diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 8a5d1c708a..5b3c3f53c6 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -251,7 +251,7 @@ void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? I2S_TDM_SLOT0 : (uint32_t)slot_cfg->tdm.slot_mask); i2s_ll_tx_set_skip_mask(hal->dev, slot_cfg->tdm.skip_mask); - i2s_ll_tx_set_half_sample_bit(hal->dev, __builtin_popcount(slot_cfg->tdm.slot_mask) * slot_bit_width / 2); + i2s_ll_tx_set_half_sample_bit(hal->dev, total_slot * slot_bit_width / 2); i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->tdm.bit_order_lsb); i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->tdm.left_align); i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->tdm.big_endian); @@ -284,7 +284,7 @@ void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha /* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */ i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? I2S_TDM_SLOT0 : (uint32_t)slot_cfg->tdm.slot_mask); - i2s_ll_rx_set_half_sample_bit(hal->dev, __builtin_popcount(slot_cfg->tdm.slot_mask) * slot_bit_width / 2); + i2s_ll_rx_set_half_sample_bit(hal->dev, total_slot * slot_bit_width / 2); i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->tdm.bit_order_lsb); i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->tdm.left_align); i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->tdm.big_endian); diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index 5cdaab8152..e8a0f04319 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -367,9 +367,9 @@ Here is the table of the real data on the line with different :cpp:member:`i2s_s | | +-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | | | both | 0x0001 | 0x0001 | 0x0002 | 0x0002 | 0x0003 | 0x0003 | 0x0004 | 0x0004 | | +-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ - | | stereo | left | 0x0001 | 0x0001 | 0x0003 | 0x0003 | 0x0005 | 0x0005 | 0x0007 | 0x0007 | + | | stereo | left | 0x0001 | 0x0000 | 0x0003 | 0x0000 | 0x0005 | 0x0000 | 0x0007 | 0x0000 | | | +-----------+----------+----------+----------+----------+----------+----------+----------+----------+ - | | | right | 0x0002 | 0x0002 | 0x0004 | 0x0004 | 0x0006 | 0x0006 | 0x0008 | 0x0008 | + | | | right | 0x0000 | 0x0002 | 0x0000 | 0x0004 | 0x0000 | 0x0006 | 0x0000 | 0x0008 | | | +-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | | | both | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | +----------------+-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ diff --git a/docs/zh_CN/api-reference/peripherals/i2s.rst b/docs/zh_CN/api-reference/peripherals/i2s.rst index c373c91723..047b6e2fb3 100644 --- a/docs/zh_CN/api-reference/peripherals/i2s.rst +++ b/docs/zh_CN/api-reference/peripherals/i2s.rst @@ -111,10 +111,10 @@ I2S 通信模式 ========= ======== ======== ======== ======== ======== ========== ESP32 I2S 0/1 I2S 0 I2S 0 无 I2S 0 I2S 0 ESP32-S2 I2S 0 无 无 无 无 I2S 0 -ESP32-C3 I2S 0 I2S 0 无 I2S 0 无 无 -ESP32-C6 I2S 0 I2S 0 无 I2S 0 无 无 -ESP32-S3 I2S 0/1 I2S 0 I2S 0 I2S 0/1 无 无 -ESP32-H2 I2S 0 I2S 0 无 I2S 0 无 无 +ESP32-C3 I2S 0 I2S 0 无 I2S 0 无 无 +ESP32-C6 I2S 0 I2S 0 无 I2S 0 无 无 +ESP32-S3 I2S 0/1 I2S 0 I2S 0 I2S 0/1 无 无 +ESP32-H2 I2S 0 I2S 0 无 I2S 0 无 无 ========= ======== ======== ======== ======== ======== ========== 标准模式 @@ -367,15 +367,15 @@ STD TX 模式 | | +-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | | | 左右 | 0x0001 | 0x0001 | 0x0002 | 0x0002 | 0x0003 | 0x0003 | 0x0004 | 0x0004 | | +-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ - | | 立体声 | 左 | 0x0001 | 0x0001 | 0x0003 | 0x0003 | 0x0005 | 0x0005 | 0x0007 | 0x0007 | + | | 立体声 | 左 | 0x0001 | 0x0000 | 0x0003 | 0x0000 | 0x0005 | 0x0000 | 0x0007 | 0x0000 | | | +-----------+----------+----------+----------+----------+----------+----------+----------+----------+ - | | | 右 | 0x0002 | 0x0002 | 0x0004 | 0x0004 | 0x0006 | 0x0006 | 0x0008 | 0x0008 | + | | | 右 | 0x0000 | 0x0002 | 0x0000 | 0x0004 | 0x0000 | 0x0006 | 0x0000 | 0x0008 | | | +-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | | | 左右 | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | +----------------+-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ .. note:: - + 数据位宽为 8 位和 32 位时,缓冲区的类型最好为 ``uint8_t`` 和 ``uint32_t``。但需注意,数据位宽为 24 位时,数据缓冲区应该以 3 字节对齐,即每 3 个字节代表一个 24 位数据,另外,:cpp:member:`i2s_chan_config_t::dma_frame_num`、 :cpp:member:`i2s_std_clk_config_t::mclk_multiple` 和写缓冲区的大小应该为 ``3`` 的倍数,否则线路上的数据或采样率可能会不准确。 .. code-block:: c @@ -680,7 +680,7 @@ STD RX 模式 +-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | 立体声 | 左右 | 0x0002 | 0x0001 | 0x0004 | 0x0003 | 0x0006 | 0x0005 | 0x0008 | 0x0007 | +-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ - + .. note:: 在立体声模式下,右声道先被接收。如需切换缓冲区中的左右声道,可设置 :cpp:member:`i2s_pdm_rx_gpio_config_t::invert_flags::clk_inv` 来强制反转时钟信号。