Selaa lähdekoodia

Merge branch 'bugfix/i2s_only_right_mode' into 'master'

i2s: fix only right case

Closes IDFGH-6918

See merge request espressif/esp-idf!17679
Kevin (Lao Kaiyao) 3 vuotta sitten
vanhempi
sitoutus
5bb2379bac

+ 12 - 9
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;
     }

+ 1 - 1
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

+ 40 - 3
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_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.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_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val)
+static inline void i2s_ll_rx_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.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;
+    }
 }
 
 /**

+ 57 - 0
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
  *

+ 58 - 0
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
  *

+ 41 - 3
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;
+    }
 }
 
 /**

+ 57 - 0
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
  *

+ 2 - 10
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);

+ 13 - 0
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

+ 9 - 0
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
  */