Skip to content

Commit 73ca054

Browse files
committed
i2s: fixed incorrect channel format on ESP32
Closes: #9635
1 parent ea51ee1 commit 73ca054

File tree

3 files changed

+114
-29
lines changed

3 files changed

+114
-29
lines changed

components/hal/esp32/include/hal/i2s_ll.h

+46-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <stdbool.h>
2626
#include "hal/misc.h"
27+
#include "hal/assert.h"
2728
#include "soc/i2s_periph.h"
2829
#include "soc/i2s_struct.h"
2930
#include "hal/i2s_types.h"
@@ -688,22 +689,57 @@ static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enab
688689
* @brief Set I2S tx chan mode
689690
*
690691
* @param hw Peripheral I2S hardware instance address.
691-
* @param val value to set tx chan mode
692-
*/
693-
static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val)
694-
{
695-
hw->conf_chan.tx_chan_mod = val;
692+
* @param chan_fmt The channel format of the TX channel
693+
*/
694+
static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, i2s_channel_fmt_t chan_fmt)
695+
{
696+
switch (chan_fmt) {
697+
case I2S_CHANNEL_FMT_ALL_RIGHT:
698+
hw->conf_chan.tx_chan_mod = 1;
699+
break;
700+
case I2S_CHANNEL_FMT_ONLY_RIGHT:
701+
hw->conf_chan.tx_chan_mod = 3;
702+
break;
703+
case I2S_CHANNEL_FMT_ALL_LEFT:
704+
hw->conf_chan.tx_chan_mod = 2;
705+
break;
706+
case I2S_CHANNEL_FMT_ONLY_LEFT:
707+
hw->conf_chan.tx_chan_mod = 4;
708+
break;
709+
case I2S_CHANNEL_FMT_RIGHT_LEFT:
710+
hw->conf_chan.tx_chan_mod = 0;
711+
break;
712+
default:
713+
HAL_ASSERT(false);
714+
}
696715
}
697716

698717
/**
699718
* @brief Set I2S rx chan mode
700719
*
701720
* @param hw Peripheral I2S hardware instance address.
702-
* @param val value to set rx chan mode
703-
*/
704-
static inline void i2s_ll_rx_set_chan_mod(i2s_dev_t *hw, uint32_t val)
705-
{
706-
hw->conf_chan.rx_chan_mod = val;
721+
* @param chan_fmt The channel format of the RX channel
722+
* @param is_msb_right Is msb_right enabled, if it does, we need to flip the channel
723+
*/
724+
static inline void i2s_ll_rx_set_chan_mod(i2s_dev_t *hw, i2s_channel_fmt_t chan_fmt, bool is_msb_right)
725+
{
726+
switch (chan_fmt) {
727+
case I2S_CHANNEL_FMT_ALL_RIGHT:
728+
/* fall through */
729+
case I2S_CHANNEL_FMT_ONLY_RIGHT:
730+
hw->conf_chan.rx_chan_mod = is_msb_right ? 1 : 2;
731+
break;
732+
case I2S_CHANNEL_FMT_ALL_LEFT:
733+
/* fall through */
734+
case I2S_CHANNEL_FMT_ONLY_LEFT:
735+
hw->conf_chan.rx_chan_mod = is_msb_right ? 2 : 1;
736+
break;
737+
case I2S_CHANNEL_FMT_RIGHT_LEFT:
738+
hw->conf_chan.rx_chan_mod = 0;
739+
break;
740+
default:
741+
HAL_ASSERT(false);
742+
}
707743
}
708744

709745
/**

components/hal/esp32s2/include/hal/i2s_ll.h

+46-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <stdbool.h>
2626
#include "hal/misc.h"
27+
#include "hal/assert.h"
2728
#include "soc/i2s_periph.h"
2829
#include "soc/i2s_struct.h"
2930
#include "hal/i2s_types.h"
@@ -764,22 +765,57 @@ static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enab
764765
* @brief Set I2S tx chan mode
765766
*
766767
* @param hw Peripheral I2S hardware instance address.
767-
* @param val value to set tx chan mode
768-
*/
769-
static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val)
770-
{
771-
hw->conf_chan.tx_chan_mod = val;
768+
* @param chan_fmt The channel format of the TX channel
769+
*/
770+
static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, i2s_channel_fmt_t chan_fmt)
771+
{
772+
switch (chan_fmt) {
773+
case I2S_CHANNEL_FMT_ALL_RIGHT:
774+
hw->conf_chan.tx_chan_mod = 1;
775+
break;
776+
case I2S_CHANNEL_FMT_ONLY_RIGHT:
777+
hw->conf_chan.tx_chan_mod = 3;
778+
break;
779+
case I2S_CHANNEL_FMT_ALL_LEFT:
780+
hw->conf_chan.tx_chan_mod = 2;
781+
break;
782+
case I2S_CHANNEL_FMT_ONLY_LEFT:
783+
hw->conf_chan.tx_chan_mod = 4;
784+
break;
785+
case I2S_CHANNEL_FMT_RIGHT_LEFT:
786+
hw->conf_chan.tx_chan_mod = 0;
787+
break;
788+
default:
789+
HAL_ASSERT(false);
790+
}
772791
}
773792

774793
/**
775794
* @brief Set I2S rx chan mode
776795
*
777796
* @param hw Peripheral I2S hardware instance address.
778-
* @param val value to set rx chan mode
779-
*/
780-
static inline void i2s_ll_rx_set_chan_mod(i2s_dev_t *hw, uint32_t val)
781-
{
782-
hw->conf_chan.rx_chan_mod = val;
797+
* @param chan_fmt The channel format of the RX channel
798+
* @param is_msb_right Is msb_right enabled, if it does, we need to flip the channel
799+
*/
800+
static inline void i2s_ll_rx_set_chan_mod(i2s_dev_t *hw, i2s_channel_fmt_t chan_fmt, bool is_msb_right)
801+
{
802+
switch (chan_fmt) {
803+
case I2S_CHANNEL_FMT_ALL_RIGHT:
804+
/* fall through */
805+
case I2S_CHANNEL_FMT_ONLY_RIGHT:
806+
hw->conf_chan.rx_chan_mod = is_msb_right ? 1 : 2;
807+
break;
808+
case I2S_CHANNEL_FMT_ALL_LEFT:
809+
/* fall through */
810+
case I2S_CHANNEL_FMT_ONLY_LEFT:
811+
hw->conf_chan.rx_chan_mod = is_msb_right ? 2 : 1;
812+
break;
813+
case I2S_CHANNEL_FMT_RIGHT_LEFT:
814+
hw->conf_chan.rx_chan_mod = 0;
815+
break;
816+
default:
817+
HAL_ASSERT(false);
818+
}
783819
}
784820

785821
/**

components/hal/i2s_hal.c

+22-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
#include "hal/i2s_hal.h"
1313
#include "sdkconfig.h"
1414

15+
#ifndef SOC_I2S_SUPPORTS_TDM
16+
#define I2S_HAL_DEFAULT_MSB_RIGHT (false) // Default msb_right bit to false
17+
#define I2S_HAL_DEFAULT_RIGHT_FIRST (I2S_HAL_DEFAULT_MSB_RIGHT) // Normally right_first bit keeps same as msb_right
18+
#endif // SOC_I2S_SUPPORTS_TDM
19+
1520
/**
1621
* @brief Calculate the closest sample rate clock configuration.
1722
* clock relationship:
@@ -185,9 +190,9 @@ void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *
185190
#if CONFIG_IDF_TARGET_ESP32
186191
i2s_ll_tx_enable_msb_right(hal->dev, hal_cfg->sample_bits <= I2S_BITS_PER_SAMPLE_16BIT);
187192
#else
188-
i2s_ll_tx_enable_msb_right(hal->dev, false);
193+
i2s_ll_tx_enable_msb_right(hal->dev, I2S_HAL_DEFAULT_MSB_RIGHT);
189194
#endif
190-
i2s_ll_tx_enable_right_first(hal->dev, false);
195+
i2s_ll_tx_enable_right_first(hal->dev, I2S_HAL_DEFAULT_RIGHT_FIRST);
191196
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
192197
#endif
193198
}
@@ -213,9 +218,9 @@ void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *
213218
#if CONFIG_IDF_TARGET_ESP32
214219
i2s_ll_rx_enable_msb_right(hal->dev, hal_cfg->sample_bits <= I2S_BITS_PER_SAMPLE_16BIT);
215220
#else
216-
i2s_ll_rx_enable_msb_right(hal->dev, false);
221+
i2s_ll_rx_enable_msb_right(hal->dev, I2S_HAL_DEFAULT_MSB_RIGHT);
217222
#endif
218-
i2s_ll_rx_enable_right_first(hal->dev, false);
223+
i2s_ll_rx_enable_right_first(hal->dev, I2S_HAL_DEFAULT_RIGHT_FIRST);
219224
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
220225
#endif
221226
}
@@ -248,8 +253,8 @@ void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t
248253
i2s_ll_tx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
249254
i2s_ll_tx_set_chan_num(hal->dev, chan_num);
250255
#else
251-
i2s_ll_tx_set_chan_mod(hal->dev, hal_cfg->chan_fmt < I2S_CHANNEL_FMT_ONLY_RIGHT ? hal_cfg->chan_fmt : (hal_cfg->chan_fmt >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left
252-
#endif
256+
i2s_ll_tx_set_chan_mod(hal->dev, hal_cfg->chan_fmt);
257+
#endif // SOC_I2S_SUPPORTS_TDM
253258
#if SOC_I2S_SUPPORTS_PDM_CODEC
254259
if (hal_cfg->mode & I2S_MODE_PDM) {
255260
// Fixed to 16 while using mono mode and 32 while using stereo mode
@@ -290,10 +295,18 @@ void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t
290295
i2s_ll_rx_set_chan_num(hal->dev, chan_num);
291296
#if SOC_I2S_SUPPORTS_PDM_RX
292297
is_mono = (hal_cfg->mode & I2S_MODE_PDM) ? false : true;
293-
#endif
298+
#endif // SOC_I2S_SUPPORTS_PDM_RX
294299
#else
295-
i2s_ll_rx_set_chan_mod(hal->dev, hal_cfg->chan_fmt < I2S_CHANNEL_FMT_ONLY_RIGHT ? hal_cfg->chan_fmt : (hal_cfg->chan_fmt >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left
296-
#endif
300+
/* rx_chan_mod is related to msb_right, we take it into consideration here.
301+
* It is calculated again here instead of reading the value from the register,
302+
* so that we can avoid introducing the calling sequence dependency */
303+
bool is_msb_right = I2S_HAL_DEFAULT_MSB_RIGHT; // Set default to false for ESP32-S2
304+
#if CONFIG_IDF_TARGET_ESP32
305+
/* Specially, `msb_right` on esp32 is related to sample bits and PDM mode */
306+
is_msb_right |= (hal_cfg->sample_bits <= I2S_BITS_PER_SAMPLE_16BIT) || (hal_cfg->mode & I2S_MODE_PDM);
307+
#endif // CONFIG_IDF_TARGET_ESP32
308+
i2s_ll_rx_set_chan_mod(hal->dev, hal_cfg->chan_fmt, is_msb_right);
309+
#endif // SOC_I2S_SUPPORTS_TDM
297310
i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits);
298311
i2s_ll_rx_enable_mono_mode(hal->dev, is_mono);
299312

0 commit comments

Comments
 (0)