From b99ced08a2b492c5a3f90c952e416ae51bce3629 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 5 Apr 2022 15:47:16 +0800 Subject: [PATCH] i2s: fix only right case Closes: https://github.com/espressif/esp-idf/issues/8538 --- components/driver/i2s.c | 21 ++++--- components/esp_lcd/src/esp_lcd_panel_io_i2s.c | 2 +- components/hal/esp32/include/hal/i2s_ll.h | 43 +++++++++++++- components/hal/esp32c3/include/hal/i2s_ll.h | 57 ++++++++++++++++++ components/hal/esp32h2/include/hal/i2s_ll.h | 58 +++++++++++++++++++ components/hal/esp32s2/include/hal/i2s_ll.h | 44 +++++++++++++- components/hal/esp32s3/include/hal/i2s_ll.h | 57 ++++++++++++++++++ components/hal/i2s_hal.c | 12 +--- components/hal/include/hal/i2s_std.h | 13 +++++ components/hal/include/hal/i2s_types_priv.h | 9 +++ 10 files changed, 290 insertions(+), 26 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 7730f2b69a..21f73b6e19 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -811,7 +811,7 @@ static void i2s_dac_set_slot_legacy(void) i2s_ll_tx_reset(dev); i2s_ll_tx_set_slave_mod(dev, false); i2s_ll_tx_set_sample_bit(dev, slot_cfg->slot_bit_width, slot_cfg->data_bit_width); - i2s_ll_tx_enable_mono_mode(dev, false); // DAC not work in mono mode + i2s_ll_tx_enable_mono_mode(dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO); i2s_ll_tx_enable_msb_shift(dev, false); i2s_ll_tx_set_ws_width(dev, slot_cfg->slot_bit_width); i2s_ll_tx_enable_msb_right(dev, false); @@ -1215,6 +1215,8 @@ static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s slot_cfg.data_bit_width = i2s_config->bits_per_sample; slot_cfg.slot_bit_width = (int)i2s_config->bits_per_chan < (int)i2s_config->bits_per_sample ? i2s_config->bits_per_sample : i2s_config->bits_per_chan; + slot_cfg.slot_mode = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? + I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO; i2s_clk_config_t clk_cfg = {}; clk_cfg.sample_rate_hz = i2s_config->sample_rate; clk_cfg.mclk_multiple = i2s_config->mclk_multiple == 0 ? I2S_MCLK_MULTIPLE_256 : i2s_config->mclk_multiple; @@ -1232,10 +1234,16 @@ static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s i2s_std_slot_config_t *std_slot = (i2s_std_slot_config_t *)calloc(1, sizeof(i2s_std_slot_config_t)); ESP_RETURN_ON_FALSE(std_slot, ESP_ERR_NO_MEM, TAG, "no memory for slot configuration struct"); memcpy(std_slot, &slot_cfg, sizeof(i2s_slot_config_t)); - std_slot->slot_mode = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? - I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO; std_slot->ws_width = i2s_config->bits_per_sample; std_slot->ws_pol = false; + if (i2s_config->channel_format == I2S_CHANNEL_FMT_RIGHT_LEFT) { + std_slot->slot_sel = I2S_STD_SLOT_LEFT_RIGHT; + } else if (i2s_config->channel_format == I2S_CHANNEL_FMT_ALL_LEFT || + i2s_config->channel_format == I2S_CHANNEL_FMT_ONLY_LEFT) { + std_slot->slot_sel = I2S_STD_SLOT_ONLY_LEFT; + } else { + std_slot->slot_sel = I2S_STD_SLOT_ONLY_RIGHT; + } if (i2s_config->communication_format == I2S_COMM_FORMAT_STAND_I2S) { std_slot->bit_shift = true; } @@ -1268,8 +1276,6 @@ static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s i2s_pdm_tx_slot_config_t *pdm_tx_slot = (i2s_pdm_tx_slot_config_t *)calloc(1, sizeof(i2s_pdm_tx_slot_config_t)); ESP_RETURN_ON_FALSE(pdm_tx_slot, ESP_ERR_NO_MEM, TAG, "no memory for slot configuration struct"); memcpy(pdm_tx_slot, &slot_cfg, sizeof(i2s_slot_config_t)); - pdm_tx_slot->slot_mode = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? - I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO; pdm_tx_slot->sd_prescale = 0; pdm_tx_slot->sd_scale = I2S_PDM_SIG_SCALING_MUL_1; pdm_tx_slot->hp_scale = I2S_PDM_SIG_SCALING_MUL_1; @@ -1303,8 +1309,6 @@ static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s i2s_pdm_rx_slot_config_t *pdm_rx_slot = (i2s_pdm_rx_slot_config_t *)calloc(1, sizeof(i2s_pdm_rx_slot_config_t)); ESP_RETURN_ON_FALSE(pdm_rx_slot, ESP_ERR_NO_MEM, TAG, "no memory for slot configuration struct"); memcpy(pdm_rx_slot, &slot_cfg, sizeof(i2s_slot_config_t)); - pdm_rx_slot->slot_mode = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? - I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO; p_i2s[i2s_num]->slot_cfg = pdm_rx_slot; @@ -1330,7 +1334,6 @@ static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s uint32_t mx_slot = i2s_get_max_channel_num(tdm_slot->slot_mask); tdm_slot->total_slot = mx_slot < i2s_config->total_chan ? mx_slot : i2s_config->total_chan; tdm_slot->ws_width = I2S_TDM_AUTO_WS_WIDTH; - tdm_slot->slot_mode = I2S_SLOT_MODE_STEREO; tdm_slot->ws_pol = false; if (i2s_config->communication_format == I2S_COMM_FORMAT_STAND_I2S) { tdm_slot->bit_shift = true; @@ -1356,7 +1359,7 @@ static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s ESP_RETURN_ON_FALSE(tdm_clk, ESP_ERR_NO_MEM, TAG, "no memory for clock configuration struct"); memcpy(tdm_clk, &clk_cfg, sizeof(i2s_clk_config_t)); p_i2s[i2s_num]->clk_cfg = tdm_clk; - p_i2s[i2s_num]->active_slot = i2s_get_active_channel_num(tdm_slot->slot_mode); + p_i2s[i2s_num]->active_slot = i2s_get_active_channel_num(tdm_slot->slot_mask); p_i2s[i2s_num]->total_slot = tdm_slot->total_slot; goto finish; } diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2s.c b/components/esp_lcd/src/esp_lcd_panel_io_i2s.c index be23d46481..f722463933 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2s.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2s.c @@ -185,7 +185,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc i2s_ll_tx_bypass_pcm(bus->hal.dev, true); i2s_ll_tx_set_slave_mod(bus->hal.dev, false); i2s_ll_tx_set_bits_mod(bus->hal.dev, bus_config->bus_width); - i2s_ll_tx_set_chan_mod(bus->hal.dev, 1); // mono + i2s_ll_tx_select_slot(bus->hal.dev, I2S_STD_SLOT_ONLY_LEFT); // mono bus->bus_width = bus_config->bus_width; i2s_ll_tx_enable_right_first(bus->hal.dev, true); #if SOC_I2S_SUPPORTS_DMA_EQUAL diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 3e791d3e8c..82f1baffcb 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -735,11 +735,48 @@ static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enab * @brief Set I2S tx chan mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode + * @param slot_sel select slot to send data */ -static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) { - hw->conf_chan.tx_chan_mod = val; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->conf_chan.tx_chan_mod = 1; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->conf_chan.tx_chan_mod = 2; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->conf_chan.tx_chan_mod = 0; + break; + default: + break; + } +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to receive data + */ +static inline void i2s_ll_rx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->conf_chan.rx_chan_mod = 1; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->conf_chan.rx_chan_mod = 2; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->conf_chan.rx_chan_mod = 0; + break; + default: + break; + } } /** diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index e97697de9e..686cd6bf50 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -17,6 +17,7 @@ #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" #include "hal/i2s_types.h" +#include "hal/i2s_types_priv.h" #ifdef __cplusplus extern "C" { @@ -550,6 +551,62 @@ static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val; } +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to send data + */ +static inline void i2s_ll_tx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = 1; // tx_tdm_tot_chan_num = 2 slots - 1 = 1 + hw->tx_tdm_ctrl.val &= ~I2S_LL_TDM_CH_MASK; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->tx_tdm_ctrl.val |= 0x02; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->tx_tdm_ctrl.val |= 0x01; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->tx_tdm_ctrl.val |= 0x03; + break; + default: + break; + } +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to receive data + */ +static inline void i2s_ll_rx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = 1; // rx_tdm_tot_chan_num = 2 slots - 1 = 1 + hw->rx_tdm_ctrl.val &= ~I2S_LL_TDM_CH_MASK; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->rx_tdm_ctrl.val |= 0x02; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->rx_tdm_ctrl.val |= 0x01; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->rx_tdm_ctrl.val |= 0x03; + break; + default: + break; + } +} + /** * @brief Set TX WS signal pol level * diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 11a4e93feb..cd8418dda1 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -18,6 +18,7 @@ #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" #include "hal/i2s_types.h" +#include "hal/i2s_types_priv.h" #ifdef __cplusplus extern "C" { @@ -551,6 +552,63 @@ static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val; } +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to send data + */ +static inline void i2s_ll_tx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = 1; // tx_tdm_tot_chan_num = 2 slots - 1 = 1 + hw->tx_tdm_ctrl.val &= ~I2S_LL_TDM_CH_MASK; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->tx_tdm_ctrl.val |= 0x02; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->tx_tdm_ctrl.val |= 0x01; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->tx_tdm_ctrl.val |= 0x03; + break; + default: + break; + } +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to receive data + */ +static inline void i2s_ll_rx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = 1; // rx_tdm_tot_chan_num = 2 slots - 1 = 1 + hw->rx_tdm_ctrl.val &= ~I2S_LL_TDM_CH_MASK; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->rx_tdm_ctrl.val |= 0x02; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->rx_tdm_ctrl.val |= 0x01; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->rx_tdm_ctrl.val |= 0x03; + break; + default: + break; + } +} + + /** * @brief Set TX WS signal pol level * diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index e6dc1c025b..f1162ec41e 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -19,6 +19,7 @@ #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" #include "hal/i2s_types.h" +#include "hal/i2s_types_priv.h" #ifdef __cplusplus extern "C" { @@ -828,11 +829,48 @@ static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enab * @brief Set I2S tx chan mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode + * @param slot_sel select slot to send data */ -static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) { - hw->conf_chan.tx_chan_mod = val; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->conf_chan.tx_chan_mod = 1; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->conf_chan.tx_chan_mod = 2; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->conf_chan.tx_chan_mod = 0; + break; + default: + break; + } +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to receive data + */ +static inline void i2s_ll_rx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->conf_chan.rx_chan_mod = 1; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->conf_chan.rx_chan_mod = 2; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->conf_chan.rx_chan_mod = 0; + break; + default: + break; + } } /** diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 3f76ef07b1..0d33d13de8 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -17,6 +17,7 @@ #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" #include "hal/i2s_types.h" +#include "hal/i2s_types_priv.h" #ifdef __cplusplus extern "C" { @@ -553,6 +554,62 @@ static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val; } +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to send data + */ +static inline void i2s_ll_tx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = 1; // tx_tdm_tot_chan_num = 2 slots - 1 = 1 + hw->tx_tdm_ctrl.val &= ~I2S_LL_TDM_CH_MASK; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->tx_tdm_ctrl.val |= 0x02; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->tx_tdm_ctrl.val |= 0x01; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->tx_tdm_ctrl.val |= 0x03; + break; + default: + break; + } +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_sel select slot to receive data + */ +static inline void i2s_ll_rx_select_slot(i2s_dev_t *hw, i2s_std_slot_sel_t slot_sel) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = 1; // rx_tdm_tot_chan_num = 2 slots - 1 = 1 + hw->rx_tdm_ctrl.val &= ~I2S_LL_TDM_CH_MASK; + switch (slot_sel) + { + case I2S_STD_SLOT_ONLY_LEFT: + hw->rx_tdm_ctrl.val |= 0x02; + break; + case I2S_STD_SLOT_ONLY_RIGHT: + hw->rx_tdm_ctrl.val |= 0x01; + break; + case I2S_STD_SLOT_LEFT_RIGHT: + hw->rx_tdm_ctrl.val |= 0x03; + break; + default: + break; + } +} + /** * @brief Set TX WS signal pol level * diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 532acca408..f0fce8ff69 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -69,17 +69,13 @@ void i2s_hal_std_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_sl i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO); i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->bit_shift); i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->ws_width); + i2s_ll_tx_select_slot(hal->dev, slot_cfg->slot_sel); #if SOC_I2S_HW_VERSION_1 i2s_ll_tx_enable_msb_right(hal->dev, slot_cfg->msb_right); i2s_ll_tx_enable_right_first(hal->dev, slot_cfg->ws_pol); /* Should always enable fifo */ i2s_ll_tx_force_enable_fifo_mod(hal->dev, true); #elif SOC_I2S_HW_VERSION_2 - /* There are always 2 slots in std mode */ - i2s_ll_tx_set_chan_num(hal->dev, 2); - /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot - * Otherwise always enable the first two slots */ - i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 0x01 : 0x03); i2s_ll_tx_set_half_sample_bit(hal->dev, slot_bit_width); i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol); i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb); @@ -99,17 +95,13 @@ void i2s_hal_std_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_sl i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO); i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->bit_shift); i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->ws_width); + i2s_ll_rx_select_slot(hal->dev, slot_cfg->slot_sel); #if SOC_I2S_HW_VERSION_1 i2s_ll_rx_enable_msb_right(hal->dev, slot_cfg->msb_right); i2s_ll_rx_enable_right_first(hal->dev, slot_cfg->ws_pol); /* Should always enable fifo */ i2s_ll_rx_force_enable_fifo_mod(hal->dev, true); #elif SOC_I2S_HW_VERSION_2 - /* There are always 2 slots in std mode */ - i2s_ll_rx_set_chan_num(hal->dev, 2); - /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot - * Otherwise always enable the first two slots */ - i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 0x01 : 0x03); i2s_ll_rx_set_half_sample_bit(hal->dev, slot_bit_width); i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol); i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb); diff --git a/components/hal/include/hal/i2s_std.h b/components/hal/include/hal/i2s_std.h index d4fb8b5dd1..48e1fcf367 100644 --- a/components/hal/include/hal/i2s_std.h +++ b/components/hal/include/hal/i2s_std.h @@ -32,6 +32,8 @@ extern "C" { .ws_width = bits_per_sample, \ .ws_pol = false, \ .bit_shift = true, \ + .slot_sel = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_STD_SLOT_ONLY_LEFT : I2S_STD_SLOT_LEFT_RIGHT, \ .msb_right = false, \ } @@ -49,6 +51,8 @@ extern "C" { .ws_width = 1, \ .ws_pol = true, \ .bit_shift = true, \ + .slot_sel = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_STD_SLOT_ONLY_LEFT : I2S_STD_SLOT_LEFT_RIGHT, \ .msb_right = false, \ } @@ -65,6 +69,8 @@ extern "C" { .ws_width = bits_per_sample, \ .ws_pol = false, \ .bit_shift = false, \ + .slot_sel = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_STD_SLOT_ONLY_LEFT : I2S_STD_SLOT_LEFT_RIGHT, \ .msb_right = false, \ } @@ -82,6 +88,8 @@ extern "C" { .ws_width = bits_per_sample, \ .ws_pol = false, \ .bit_shift = true, \ + .slot_sel = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_STD_SLOT_ONLY_LEFT : I2S_STD_SLOT_LEFT_RIGHT, \ .left_align = false, \ .big_endian = false, \ .bit_order_lsb = false \ @@ -101,6 +109,8 @@ extern "C" { .ws_width = 1, \ .ws_pol = true, \ .bit_shift = true, \ + .slot_sel = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_STD_SLOT_ONLY_LEFT : I2S_STD_SLOT_LEFT_RIGHT, \ .left_align = false, \ .big_endian = false, \ .bit_order_lsb = false \ @@ -119,6 +129,8 @@ extern "C" { .ws_width = bits_per_sample, \ .ws_pol = false, \ .bit_shift = false, \ + .slot_sel = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_STD_SLOT_ONLY_LEFT : I2S_STD_SLOT_LEFT_RIGHT, \ .left_align = false, \ .big_endian = false, \ .bit_order_lsb = false \ @@ -151,6 +163,7 @@ typedef struct { uint32_t ws_width; /*!< WS signal width (i.e. the number of bclk ticks that ws signal is high) */ bool ws_pol; /*!< WS signal polarity, set true to enable high lever first */ bool bit_shift; /*!< Set to enbale bit shift in Philip mode */ + i2s_std_slot_sel_t slot_sel; /*!< Select the left, right or both slot */ #if SOC_I2S_HW_VERSION_1 // For esp32/esp32-s2 bool msb_right; /*!< Set to place right channel data at the MSB in the FIFO */ #else diff --git a/components/hal/include/hal/i2s_types_priv.h b/components/hal/include/hal/i2s_types_priv.h index 342327fcf8..5e33548b4e 100644 --- a/components/hal/include/hal/i2s_types_priv.h +++ b/components/hal/include/hal/i2s_types_priv.h @@ -35,6 +35,15 @@ typedef enum { I2S_SLOT_MODE_STEREO = 2, /*!< I2S channel slot format stereo, transmit different data in different slots for tx mode, receive the data in all slots for rx mode. */ } i2s_slot_mode_t; +/** + * @brief I2S slot select in standard mode + */ +typedef enum { + I2S_STD_SLOT_ONLY_LEFT = 0x01, /*!< I2S only transmits or receives left slot */ + I2S_STD_SLOT_ONLY_RIGHT = 0x02, /*!< I2S only transmits or receives right slot */ + I2S_STD_SLOT_LEFT_RIGHT = 0x03, /*!< I2S only transmits or receives both left and right slot */ +} i2s_std_slot_sel_t; + /** * @brief I2S channel direction */