From 9b8a78153fc4c23512822c6ca74c901acba3246f Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 24 Oct 2022 16:29:20 +0800 Subject: [PATCH 1/2] i2s: refactor soc caps --- .../soc/esp32c3/include/soc/Kconfig.soc_caps.in | 8 ++------ components/soc/esp32c3/include/soc/soc_caps.h | 3 +-- .../soc/esp32c6/include/soc/Kconfig.soc_caps.in | 8 ++------ components/soc/esp32c6/include/soc/soc_caps.h | 3 +-- .../soc/esp32h2/include/soc/Kconfig.soc_caps.in | 8 ++------ components/soc/esp32h2/include/soc/soc_caps.h | 3 +-- .../soc/esp32s3/include/soc/Kconfig.soc_caps.in | 12 ++++-------- components/soc/esp32s3/include/soc/soc_caps.h | 5 ++--- examples/peripherals/.build-test-rules.yml | 4 ++-- 9 files changed, 17 insertions(+), 37 deletions(-) diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 6a715917e9b..7242b2f9bfb 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -380,12 +380,8 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX - bool - default y - -config SOC_I2S_SUPPORTS_PDM_CODEC - bool - default y + int + default 2 config SOC_I2S_SUPPORTS_TDM bool diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index ba86f24ded2..d9e9dd4e487 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -185,8 +185,7 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (1) -#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_PDM_TX (2) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 1493ebdc05f..84655b99da9 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -312,12 +312,8 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX - bool - default y - -config SOC_I2S_SUPPORTS_PDM_CODEC - bool - default y + int + default 2 config SOC_I2S_SUPPORTS_TDM bool diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index d87ad897c0a..f0b7033a0cc 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -193,8 +193,7 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (1) -#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_PDM_TX (2) #define SOC_I2S_SUPPORTS_TDM (1) // TODO: IDF-5328 (Copy from esp32c3, need check) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 5fc424d9f56..c6be565fc35 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -356,12 +356,8 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX - bool - default y - -config SOC_I2S_SUPPORTS_PDM_CODEC - bool - default y + int + default 2 config SOC_I2S_SUPPORTS_TDM bool diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 1c7778c6f70..f192b91f43c 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -191,8 +191,7 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (1) -#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_PDM_TX (2) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index c08e1b82714..ddde109d7b4 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -444,16 +444,12 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX - bool - default y + int + default 2 config SOC_I2S_SUPPORTS_PDM_RX - bool - default y - -config SOC_I2S_SUPPORTS_PDM_CODEC - bool - default y + int + default 4 config SOC_I2S_SUPPORTS_TDM bool diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 1ac13266cbd..cea56503fd1 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -186,9 +186,8 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (1) -#define SOC_I2S_SUPPORTS_PDM_RX (1) -#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_PDM_TX (2) +#define SOC_I2S_SUPPORTS_PDM_RX (4) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index ed9d3ea6ef6..3ca45dd0bed 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -80,8 +80,8 @@ examples/peripherals/i2s/i2s_codec/i2s_es8311: reason: target esp32c6 is not supported yet examples/peripherals/i2s/i2s_recorder: - disable: - - if: SOC_I2S_SUPPORTS_PDM_RX != 1 + enable: + - if: SOC_I2S_SUPPORTS_PDM_RX > 0 examples/peripherals/lcd/i2c_oled: disable: From fa9b022f6832b54889608ade5ddc5e52698f818d Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 24 Oct 2022 17:33:49 +0800 Subject: [PATCH 2/2] i2s: support 4 line pdm rx on esp32s3 --- components/driver/i2s/i2s_pdm.c | 18 ++++-- components/driver/include/driver/i2s_pdm.h | 9 ++- components/hal/i2s_hal.c | 13 ++-- components/hal/include/hal/i2s_types.h | 12 ++++ components/soc/esp32/i2s_periph.c | 2 - .../soc/esp32/include/soc/Kconfig.soc_caps.in | 8 +++ components/soc/esp32/include/soc/soc_caps.h | 2 + components/soc/esp32c3/i2s_periph.c | 4 +- .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 ++ .../soc/esp32c3/include/soc/gpio_sig_map.h | 2 +- components/soc/esp32c3/include/soc/soc_caps.h | 3 +- components/soc/esp32c6/i2s_periph.c | 3 +- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32c6/include/soc/soc_caps.h | 3 +- components/soc/esp32h2/i2s_periph.c | 4 +- .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32h2/include/soc/soc_caps.h | 3 +- components/soc/esp32s2/i2s_periph.c | 1 - components/soc/esp32s3/i2s_periph.c | 18 ++++-- .../esp32s3/include/soc/Kconfig.soc_caps.in | 8 +++ .../soc/esp32s3/include/soc/gpio_sig_map.h | 26 +++----- components/soc/esp32s3/include/soc/soc_caps.h | 6 +- components/soc/include/soc/i2s_periph.h | 16 ++++- docs/en/api-reference/peripherals/i2s.rst | 12 ++-- .../i2s/i2s_basic/i2s_pdm/README.md | 62 ++++++++++++++++++- .../i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c | 22 ++++++- tools/ci/check_copyright_ignore.txt | 1 - 27 files changed, 210 insertions(+), 60 deletions(-) diff --git a/components/driver/i2s/i2s_pdm.c b/components/driver/i2s/i2s_pdm.c index 6863453d235..aabcfe3d30e 100644 --- a/components/driver/i2s/i2s_pdm.c +++ b/components/driver/i2s/i2s_pdm.c @@ -118,9 +118,9 @@ static esp_err_t i2s_pdm_tx_set_gpio(i2s_chan_handle_t handle, const i2s_pdm_tx_ i2s_pdm_tx_config_t *pdm_tx_cfg = (i2s_pdm_tx_config_t *)handle->mode_info; /* Set data output GPIO */ i2s_gpio_check_and_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); -#if SOC_I2S_HW_VERSION_2 +#if SOC_I2S_PDM_MAX_TX_LINES > 1 if (pdm_tx_cfg->slot_cfg.line_mode == I2S_PDM_TX_TWO_LINE_DAC) { - i2s_gpio_check_and_set(gpio_cfg->dout2, i2s_periph_signal[id].data_out1_sig, false, false); + i2s_gpio_check_and_set(gpio_cfg->dout2, i2s_periph_signal[id].data_out_sigs[1], false, false); } #endif @@ -393,8 +393,17 @@ static esp_err_t i2s_pdm_rx_set_gpio(i2s_chan_handle_t handle, const i2s_pdm_rx_ ESP_ERR_INVALID_ARG, TAG, "clk gpio is invalid"); ESP_RETURN_ON_FALSE((gpio_cfg->din == -1 || GPIO_IS_VALID_GPIO(gpio_cfg->din)), ESP_ERR_INVALID_ARG, TAG, "dout gpio is invalid"); + i2s_pdm_rx_config_t *pdm_rx_cfg = (i2s_pdm_rx_config_t *)handle->mode_info; /* Set data input GPIO */ +#if SOC_I2S_PDM_MAX_RX_LINES > 1 + for (int i = 0; i < SOC_I2S_PDM_MAX_RX_LINES; i++) { + if (pdm_rx_cfg->slot_cfg.slot_mask & (0x03 << (i * 2))) { + i2s_gpio_check_and_set(gpio_cfg->dins[i], i2s_periph_signal[id].data_in_sigs[i], true, false); + } + } +#else i2s_gpio_check_and_set(gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); +#endif if (handle->role == I2S_ROLE_SLAVE) { /* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */ @@ -410,7 +419,6 @@ static esp_err_t i2s_pdm_rx_set_gpio(i2s_chan_handle_t handle, const i2s_pdm_rx_ i2s_ll_mclk_bind_to_rx_clk(handle->controller->hal.dev); #endif /* Update the mode info: gpio configuration */ - i2s_pdm_rx_config_t *pdm_rx_cfg = (i2s_pdm_rx_config_t *)handle->mode_info; memcpy(&(pdm_rx_cfg->gpio_cfg), gpio_cfg, sizeof(i2s_pdm_rx_gpio_config_t)); return ESP_OK; @@ -433,9 +441,9 @@ esp_err_t i2s_channel_init_pdm_rx_mode(i2s_chan_handle_t handle, const i2s_pdm_r } handle->mode_info = calloc(1, sizeof(i2s_pdm_rx_config_t)); ESP_GOTO_ON_FALSE(handle->mode_info, ESP_ERR_NO_MEM, err, TAG, "no memory for storing the configurations"); - ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_gpio(handle, &pdm_rx_cfg->gpio_cfg), err, TAG, "initialize channel failed while setting gpio pins"); - /* i2s_set_pdm_rx_slot should be called before i2s_set_pdm_rx_clock while initializing, because clock is relay on the slot */ + /* i2s_set_pdm_rx_slot should be called before i2s_set_pdm_rx_clock and i2s_pdm_rx_set_gpio while initializing, because clock is relay on the slot */ ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_slot(handle, &pdm_rx_cfg->slot_cfg), err, TAG, "initialize channel failed while setting slot"); + ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_gpio(handle, &pdm_rx_cfg->gpio_cfg), err, TAG, "initialize channel failed while setting gpio pins"); #if SOC_I2S_SUPPORTS_APLL /* Enable APLL and acquire its lock when the clock source is APLL */ if (pdm_rx_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { diff --git a/components/driver/include/driver/i2s_pdm.h b/components/driver/include/driver/i2s_pdm.h index 26a20df8dad..4d0794563f2 100644 --- a/components/driver/include/driver/i2s_pdm.h +++ b/components/driver/include/driver/i2s_pdm.h @@ -75,8 +75,11 @@ typedef struct { * @brief I2S PDM tx mode GPIO pins configuration */ typedef struct { - gpio_num_t clk; /*!< PDM clk pin, output */ - gpio_num_t din; /*!< DATA pin, input */ + gpio_num_t clk; /*!< PDM clk pin, output */ + union { + gpio_num_t din; /*!< DATA pin 0, input */ + gpio_num_t dins[SOC_I2S_PDM_MAX_RX_LINES]; /*!< DATA pins, input, only take effect when corresponding I2S_PDM_RX_LINEx_SLOT_xxx is enabled in i2s_pdm_rx_slot_config_t::slot_mask */ + }; struct { uint32_t clk_inv: 1; /*!< Set 1 to invert the clk output */ } invert_flags; /*!< GPIO pin invert flags */ @@ -280,7 +283,7 @@ typedef struct { typedef struct { gpio_num_t clk; /*!< PDM clk pin, output */ gpio_num_t dout; /*!< DATA pin, output */ -#if SOC_I2S_HW_VERSION_2 +#if SOC_I2S_PDM_MAX_TX_LINES > 1 gpio_num_t dout2; /*!< The second data pin for the DAC dual-line mode, * only take effect when the line mode is `I2S_PDM_TX_TWO_LINE_DAC` */ diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 6c7f51e49fd..8a5d1c708a6 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -145,7 +145,7 @@ void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha i2s_ll_tx_force_enable_fifo_mod(hal->dev, true); i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width); i2s_ll_tx_enable_mono_mode(hal->dev, is_mono); - i2s_ll_tx_select_pdm_slot(hal->dev, slot_cfg->pdm_tx.slot_mask, is_mono); + i2s_ll_tx_select_pdm_slot(hal->dev, slot_cfg->pdm_tx.slot_mask & I2S_STD_SLOT_BOTH, is_mono); i2s_ll_tx_enable_msb_right(hal->dev, false); i2s_ll_tx_enable_right_first(hal->dev, false); #elif SOC_I2S_HW_VERSION_2 @@ -202,10 +202,15 @@ void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha #elif SOC_I2S_HW_VERSION_2 i2s_ll_tx_set_half_sample_bit(hal->dev, 16); i2s_ll_rx_enable_mono_mode(hal->dev, false); +#if SOC_I2S_PDM_MAX_RX_LINES > 1 + uint32_t slot_mask = (slot_cfg->slot_mode == I2S_SLOT_MODE_STEREO && slot_cfg->pdm_rx.slot_mask <= I2S_PDM_SLOT_BOTH) ? + I2S_PDM_SLOT_BOTH : slot_cfg->pdm_rx.slot_mask; +#else /* Set the channel mask to enable corresponding slots, always enable two slots for stereo mode */ - i2s_ll_rx_set_active_chan_mask(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_STEREO ? - I2S_PDM_SLOT_BOTH : slot_cfg->pdm_rx.slot_mask); -#endif + uint32_t slot_mask = slot_cfg->slot_mode == I2S_SLOT_MODE_STEREO ? I2S_PDM_SLOT_BOTH : slot_cfg->pdm_rx.slot_mask; +#endif // SOC_I2S_SUPPORTS_PDM_RX > 1 + i2s_ll_rx_set_active_chan_mask(hal->dev, slot_mask); +#endif // SOC_I2S_SUPPORTS_PDM_RX } void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal) diff --git a/components/hal/include/hal/i2s_types.h b/components/hal/include/hal/i2s_types.h index c7efe1be222..68ca08c3b2b 100644 --- a/components/hal/include/hal/i2s_types.h +++ b/components/hal/include/hal/i2s_types.h @@ -141,6 +141,18 @@ typedef enum { I2S_PDM_SLOT_RIGHT = BIT(0), /*!< I2S PDM only transmits or receives the PDM device whose 'select' pin is pulled up */ I2S_PDM_SLOT_LEFT = BIT(1), /*!< I2S PDM only transmits or receives the PDM device whose 'select' pin is pulled down */ I2S_PDM_SLOT_BOTH = BIT(0) | BIT(1), /*!< I2S PDM transmits or receives both two slots */ +#if SOC_I2S_PDM_MAX_RX_LINES > 1 + /* The following enumerators are only used in multi-line PDM RX mode */ + I2S_PDM_RX_LINE0_SLOT_RIGHT = I2S_PDM_SLOT_RIGHT, /*!< I2S PDM receives the right slot on line 0 */ + I2S_PDM_RX_LINE0_SLOT_LEFT = I2S_PDM_SLOT_LEFT, /*!< I2S PDM receives the left slot on line 0 */ + I2S_PDM_RX_LINE1_SLOT_RIGHT = BIT(2), /*!< I2S PDM receives the right slot on line 1 */ + I2S_PDM_RX_LINE1_SLOT_LEFT = BIT(3), /*!< I2S PDM receives the left slot on line 1 */ + I2S_PDM_RX_LINE2_SLOT_RIGHT = BIT(4), /*!< I2S PDM receives the right slot on line 2 */ + I2S_PDM_RX_LINE2_SLOT_LEFT = BIT(5), /*!< I2S PDM receives the left slot on line 2 */ + I2S_PDM_RX_LINE3_SLOT_RIGHT = BIT(6), /*!< I2S PDM receives the right slot on line 3 */ + I2S_PDM_RX_LINE3_SLOT_LEFT = BIT(7), /*!< I2S PDM receives the left slot on line 3 */ + I2S_PDM_LINE_SLOT_ALL = 0x00ff, /*!< I2S PDM receives all slots */ +#endif } i2s_pdm_slot_mask_t; #if SOC_I2S_SUPPORTS_TDM diff --git a/components/soc/esp32/i2s_periph.c b/components/soc/esp32/i2s_periph.c index a96802b6eeb..d2c0c227a1e 100644 --- a/components/soc/esp32/i2s_periph.c +++ b/components/soc/esp32/i2s_periph.c @@ -25,7 +25,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_rx_ws_sig = I2S0I_WS_IN_IDX, .data_out_sig = I2S0O_DATA_OUT23_IDX, - .data_out1_sig = -1, .data_in_sig = I2S0I_DATA_IN15_IDX, .irq = ETS_I2S0_INTR_SOURCE, @@ -45,7 +44,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_rx_ws_sig = I2S1I_WS_IN_IDX, .data_out_sig = I2S1O_DATA_OUT23_IDX, - .data_out1_sig = -1, .data_in_sig = I2S1I_DATA_IN15_IDX, .irq = ETS_I2S1_INTR_SOURCE, diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index fc032e84450..308b5d2ecb4 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -307,10 +307,18 @@ config SOC_I2S_SUPPORTS_PDM_TX bool default y +config SOC_I2S_PDM_MAX_TX_LINES + int + default 1 + config SOC_I2S_SUPPORTS_PDM_RX bool default y +config SOC_I2S_PDM_MAX_RX_LINES + int + default 1 + config SOC_I2S_SUPPORTS_ADC_DAC bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index cea3f6d1d62..7b0ca67e345 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -187,7 +187,9 @@ #define SOC_I2S_SUPPORTS_APLL (1) #define SOC_I2S_SUPPORTS_PDM (1) #define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_PDM_MAX_TX_LINES (1U) #define SOC_I2S_SUPPORTS_PDM_RX (1) +#define SOC_I2S_PDM_MAX_RX_LINES (1U) #define SOC_I2S_SUPPORTS_ADC_DAC (1) #define SOC_I2S_SUPPORTS_ADC (1) #define SOC_I2S_SUPPORTS_DAC (1) diff --git a/components/soc/esp32c3/i2s_periph.c b/components/soc/esp32c3/i2s_periph.c index 44dd02d334a..88937899fd3 100644 --- a/components/soc/esp32c3/i2s_periph.c +++ b/components/soc/esp32c3/i2s_periph.c @@ -24,8 +24,8 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_tx_ws_sig = I2SO_WS_IN_IDX, .s_rx_ws_sig = I2SI_WS_IN_IDX, - .data_out_sig = I2SO_SD_OUT_IDX, - .data_out1_sig = I2SO_SD1_OUT_IDX, + .data_out_sigs[0] = I2SO_SD_OUT_IDX, + .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, .irq = -1, diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 7242b2f9bfb..053eddc3e60 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -380,6 +380,10 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX + bool + default y + +config SOC_I2S_PDM_MAX_TX_LINES int default 2 diff --git a/components/soc/esp32c3/include/soc/gpio_sig_map.h b/components/soc/esp32c3/include/soc/gpio_sig_map.h index badcefdc09e..f471e316ac9 100644 --- a/components/soc/esp32c3/include/soc/gpio_sig_map.h +++ b/components/soc/esp32c3/include/soc/gpio_sig_map.h @@ -92,7 +92,7 @@ #define GPIO_SD1_OUT_IDX 56 #define GPIO_SD2_OUT_IDX 57 #define GPIO_SD3_OUT_IDX 58 -#define I2SO_SD1_OUT_IDX 59 +#define I2SO_SD1_OUT_IDX 59 // Only used in I2S PDM TX mode #define FSPICLK_IN_IDX 63 #define FSPICLK_OUT_IDX 63 #define FSPIQ_IN_IDX 64 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index d9e9dd4e487..d7040eee482 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -185,7 +185,8 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (2) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_PDM_MAX_TX_LINES (2) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/components/soc/esp32c6/i2s_periph.c b/components/soc/esp32c6/i2s_periph.c index 53417594ce6..89f49e26171 100644 --- a/components/soc/esp32c6/i2s_periph.c +++ b/components/soc/esp32c6/i2s_periph.c @@ -24,7 +24,8 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_tx_ws_sig = I2SO_WS_IN_IDX, .s_rx_ws_sig = I2SI_WS_IN_IDX, - .data_out_sig = I2SO_SD_OUT_IDX, + .data_out_sigs[0] = I2SO_SD_OUT_IDX, + .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, .irq = -1, diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 84655b99da9..1f09f1359b7 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -312,6 +312,10 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX + bool + default y + +config SOC_I2S_PDM_MAX_TX_LINES int default 2 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index f0b7033a0cc..8ee7a4855d5 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -193,7 +193,8 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (2) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_PDM_MAX_TX_LINES (2) #define SOC_I2S_SUPPORTS_TDM (1) // TODO: IDF-5328 (Copy from esp32c3, need check) diff --git a/components/soc/esp32h2/i2s_periph.c b/components/soc/esp32h2/i2s_periph.c index 08a85b70d08..26a3d5503ce 100644 --- a/components/soc/esp32h2/i2s_periph.c +++ b/components/soc/esp32h2/i2s_periph.c @@ -24,8 +24,8 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_tx_ws_sig = I2SO_WS_IN_IDX, .s_rx_ws_sig = I2SI_WS_IN_IDX, - .data_out_sig = I2SO_SD_OUT_IDX, - .data_out1_sig = I2SO_SD1_OUT_IDX, + .data_out_sigs[0] = I2SO_SD_OUT_IDX, + .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, .irq = ETS_I2S1_INTR_SOURCE, diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index c6be565fc35..f72a52bb848 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -356,6 +356,10 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX + bool + default y + +config SOC_I2S_PDM_MAX_TX_LINES int default 2 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index f192b91f43c..c4b44172fe6 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -191,7 +191,8 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (2) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_PDM_MAX_TX_LINES (2) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/components/soc/esp32s2/i2s_periph.c b/components/soc/esp32s2/i2s_periph.c index fd01440c65a..2bee28695a7 100644 --- a/components/soc/esp32s2/i2s_periph.c +++ b/components/soc/esp32s2/i2s_periph.c @@ -25,7 +25,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_rx_ws_sig = I2S0I_WS_IN_IDX, .data_out_sig = I2S0O_DATA_OUT23_IDX, - .data_out1_sig = -1, .data_in_sig = I2S0I_DATA_IN15_IDX, .irq = ETS_I2S0_INTR_SOURCE, diff --git a/components/soc/esp32s3/i2s_periph.c b/components/soc/esp32s3/i2s_periph.c index 1f3715a9e74..64233b9d9af 100644 --- a/components/soc/esp32s3/i2s_periph.c +++ b/components/soc/esp32s3/i2s_periph.c @@ -24,9 +24,12 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_tx_ws_sig = I2S0O_WS_IN_IDX, .s_rx_ws_sig = I2S0I_WS_IN_IDX, - .data_out_sig = I2S0O_SD_OUT_IDX, - .data_out1_sig = I2S0O_SD1_OUT_IDX, - .data_in_sig = I2S0I_SD_IN_IDX, + .data_out_sigs[0] = I2S0O_SD_OUT_IDX, + .data_out_sigs[1] = I2S0O_SD1_OUT_IDX, + .data_in_sigs[0] = I2S0I_SD_IN_IDX, + .data_in_sigs[1] = I2S0I_SD1_IN_IDX, + .data_in_sigs[2] = I2S0I_SD2_IN_IDX, + .data_in_sigs[3] = I2S0I_SD3_IN_IDX, .irq = -1, .module = PERIPH_I2S0_MODULE, @@ -44,9 +47,12 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .s_tx_ws_sig = I2S1O_WS_IN_IDX, .s_rx_ws_sig = I2S1I_WS_IN_IDX, - .data_out_sig = I2S1O_SD_OUT_IDX, - .data_out1_sig = -1, - .data_in_sig = I2S1I_SD_IN_IDX, + .data_out_sigs[0] = I2S1O_SD_OUT_IDX, + .data_out_sigs[1] = -1, + .data_in_sigs[0] = I2S1I_SD_IN_IDX, + .data_in_sigs[1] = -1, + .data_in_sigs[2] = -1, + .data_in_sigs[3] = -1, .irq = -1, .module = PERIPH_I2S1_MODULE, diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index ddde109d7b4..bc9569b8c7d 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -444,10 +444,18 @@ config SOC_I2S_SUPPORTS_PDM default y config SOC_I2S_SUPPORTS_PDM_TX + bool + default y + +config SOC_I2S_PDM_MAX_TX_LINES int default 2 config SOC_I2S_SUPPORTS_PDM_RX + bool + default y + +config SOC_I2S_PDM_MAX_RX_LINES int default 4 diff --git a/components/soc/esp32s3/include/soc/gpio_sig_map.h b/components/soc/esp32s3/include/soc/gpio_sig_map.h index 1d6506fd805..783f590d5bf 100644 --- a/components/soc/esp32s3/include/soc/gpio_sig_map.h +++ b/components/soc/esp32s3/include/soc/gpio_sig_map.h @@ -1,16 +1,8 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_GPIO_SIG_MAP_H_ #define _SOC_GPIO_SIG_MAP_H_ @@ -113,11 +105,11 @@ #define BB_DIAG14_IDX 49 #define GPIO_BT_PRIORITY_IDX 50 #define BB_DIAG15_IDX 50 -#define I2S0I_SD1_IN_IDX 51 +#define I2S0I_SD1_IN_IDX 51 // Only used in I2S PDM RX mode #define BB_DIAG16_IDX 51 -#define I2S0I_SD2_IN_IDX 52 +#define I2S0I_SD2_IN_IDX 52 // Only used in I2S PDM RX mode #define BB_DIAG17_IDX 52 -#define I2S0I_SD3_IN_IDX 53 +#define I2S0I_SD3_IN_IDX 53 // Only used in I2S PDM RX mode #define BB_DIAG18_IDX 53 #define CORE1_GPIO_IN7_IDX 54 #define CORE1_GPIO_OUT7_IDX 54 @@ -232,7 +224,7 @@ #define SUBSPICS1_OUT_IDX 125 #define FSPIDQS_OUT_IDX 126 #define SPI3_CS2_OUT_IDX 127 -#define I2S0O_SD1_OUT_IDX 128 +#define I2S0O_SD1_OUT_IDX 128 // Only used in I2S PDM TX mode #define CORE1_GPIO_IN0_IDX 129 #define CORE1_GPIO_OUT0_IDX 129 #define CORE1_GPIO_IN1_IDX 130 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index cea56503fd1..53f897e6fc6 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -186,8 +186,10 @@ #define SOC_I2S_SUPPORTS_XTAL (1) #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) -#define SOC_I2S_SUPPORTS_PDM_TX (2) -#define SOC_I2S_SUPPORTS_PDM_RX (4) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_PDM_MAX_TX_LINES (2) +#define SOC_I2S_SUPPORTS_PDM_RX (1) +#define SOC_I2S_PDM_MAX_RX_LINES (4) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/components/soc/include/soc/i2s_periph.h b/components/soc/include/soc/i2s_periph.h index 35522f385ef..e6e8cc29d7e 100644 --- a/components/soc/include/soc/i2s_periph.h +++ b/components/soc/include/soc/i2s_periph.h @@ -31,9 +31,19 @@ typedef struct { const uint8_t s_tx_ws_sig; const uint8_t s_rx_ws_sig; - const uint8_t data_out_sig; - const uint8_t data_out1_sig; // Only valid in version 2 - const uint8_t data_in_sig; + union { + const uint8_t data_out_sig; +#if SOC_I2S_PDM_MAX_TX_LINES + const uint8_t data_out_sigs[SOC_I2S_PDM_MAX_TX_LINES]; // Only valid in version 2 +#endif + }; + + union { + const uint8_t data_in_sig; +#if SOC_I2S_PDM_MAX_RX_LINES + const uint8_t data_in_sigs[SOC_I2S_PDM_MAX_RX_LINES]; +#endif + }; const uint8_t irq; const periph_module_t module; diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index 2c5cb35aa5c..3a065e3a10d 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -135,7 +135,7 @@ Standard mode always has left and right two sound channels which are called 'slo PDM Mode (TX) ^^^^^^^^^^^^^ - PDM(Pulse-density Modulation) mode for tx channel can convert PCM data into PDM format which always has left and right slots. PDM TX can only support 16 bits width sample data. PDM TX only needs CLK pin for clock signal and DOUT pin for data signal (i.e. WS and SD signal in the following figure, the BCK signal is an internal bit sampling clock, not needed between PDM devices). This mode allows user to configure the up-sampling parameters :cpp:member:`i2s_pdm_tx_clk_config_t::up_sample_fp` :cpp:member:`i2s_pdm_tx_clk_config_t::up_sample_fs`. The up-sampling rate can be calculated by ``up_sample_rate = fp / fs``, there are up-sampling modes in PDM TX: + PDM(Pulse-density Modulation) mode for tx channel can convert PCM data into PDM format which always has left and right slots. PDM TX can only support 16 bits width sample data. PDM TX is only supported on I2S0, it needs at least a CLK pin for clock signal and a DOUT pin for data signal (i.e. WS and SD signal in the following figure, the BCK signal is an internal bit sampling clock, not needed between PDM devices). This mode allows user to configure the up-sampling parameters :cpp:member:`i2s_pdm_tx_clk_config_t::up_sample_fp` :cpp:member:`i2s_pdm_tx_clk_config_t::up_sample_fs`. The up-sampling rate can be calculated by ``up_sample_rate = fp / fs``, there are up-sampling modes in PDM TX: - **Fixed Clock Frequency**: In this mode the up-sampling rate will change according to the sample rate. Setting ``fp = 960`` and ``fs = sample_rate / 100``, then the clock frequency(Fpdm) on CLK pin will be fixed to 128 * 48 KHz = 6.144 MHz, note that this frequency is not equal to the sample rate(Fpcm). - **Fixed Up-sampling Rate**: In this mode the up-sampling rate is fixed to 2. Setting ``fp = 960`` and ``fs = 480``, then the clock frequency(Fpdm) on CLK pin will be ``128 * sample_rate`` @@ -148,7 +148,7 @@ Standard mode always has left and right two sound channels which are called 'slo PDM Mode (RX) ^^^^^^^^^^^^^ - PDM(Pulse-density Modulation) mode for rx channel can receive PDM format data and convert the data into PCM format. PDM RX can only support 16 bits width sample data. PDM RX only need WS pin for clock signal and DIN pin for data signal. This mode allows user to configure the down-sampling parameter :cpp:member:`i2s_pdm_rx_clk_config_t::dn_sample_mode`, there are two down-sampling modes in PDM RX: + PDM(Pulse-density Modulation) mode for rx channel can receive PDM format data and convert the data into PCM format. PDM RX is only supported on I2S0, it can only support 16 bits width sample data. PDM RX needs at least a CLK pin for clock signal and a DIN pin for data signal. This mode allows user to configure the down-sampling parameter :cpp:member:`i2s_pdm_rx_clk_config_t::dn_sample_mode`, there are two down-sampling modes in PDM RX: - :cpp:enumerator:`i2s_pdm_dsr_t::I2S_PDM_DSR_8S`: In this mode, the clock frequency(Fpdm) on WS pin will be sample_rate(Fpcm) * 64. - :cpp:enumerator:`i2s_pdm_dsr_t::I2S_PDM_DSR_16S`: In this mode, the clock frequency(Fpdm) on WS pin will be sample_rate(Fpcm) * 128. @@ -343,7 +343,7 @@ Here is the table of the real data on the line with different :cpp:member:`i2s_s Similar for 8-bit and 32-bit data width, the type of the buffer is better to be ``uint8_t`` and ``uint32_t`` type. But specially, when the data width is 24-bit, the data buffer should aligned with 3-byte(i.e. every 3 bytes stands for a 24-bit data in one slot), additionally, :cpp:member:`i2s_chan_config_t::dma_frame_num`, :cpp:member:`i2s_std_clk_config_t::mclk_multiple` and the writting buffer size should be the multiple of ``3``, otherwise the data on the line or the sample rate will be incorrect. -.. only:: esp32c3 or esp32s3 or esp32h2 +.. only:: not (esp32 or esp32s2) +----------------+-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | data bit width | slot mode | slot mask | ws low | ws high | ws low | ws high | ws low | ws high | ws low | ws high | @@ -464,7 +464,7 @@ Here is the table of the data that received in the buffer with different :cpp:me ``8-bit``, ``24-bit`` and ``32-bit`` are similar as ``16-bit``, the data bit-width in the receiving buffer are equal to the data bit-width on the line. Additionally, when using ``24-bit`` data width, :cpp:member:`i2s_chan_config_t::dma_frame_num`, :cpp:member:`i2s_std_clk_config_t::mclk_multiple` and the receiving buffer size should be the multiple of ``3``, otherwise the data on the line or the sample rate will be incorrect. -.. only:: esp32c3 or esp32s3 or esp32h2 +.. only:: not (esp32 or esp32s2) +----------------+-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ | data bit width | slot mode | slot mask | data 0 | data 1 | data 2 | data 3 | data 4 | data 5 | data 6 | data 7 | @@ -569,7 +569,7 @@ Here is the table of the data that received in the buffer with different :cpp:me | | both | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | +-----------+-----------+----------+----------+----------+----------+----------+----------+----------+----------+ - .. only:: esp32c3 or esp32s3 or esp32h2 + .. only:: not esp32 Here is the table of the real data on the line with different :cpp:member:`i2s_pdm_tx_slot_config_t::slot_mode` and :cpp:member:`i2s_pdm_tx_slot_config_t::line_mode` (The PDM format on the line is transferred to PCM format for easier comprehension). @@ -676,6 +676,8 @@ Here is the table of the data that received in the buffer with different :cpp:me The right slot is received first in stereo mode. To switch the left and right slot in the buffer, please set the :cpp:member:`i2s_pdm_rx_gpio_config_t::invert_flags::clk_inv` to force invert the clock signal. + Specially, ESP32-S3 can support up to 4 data lines in PDM RX mode, each data line can be connected to two PDM MICs (left and right slots), which means the PDM RX on ESP32-S3 can support up to 8 PDM MICs. To enable multiple data lines, set the bits in :cpp:member:`i2s_pdm_rx_gpio_config_t::slot_mask` to enable corresponding slots first, and then set the data GPIOs in :cpp:type:`i2s_pdm_rx_gpio_config_t`. + .. code-block:: c #include "driver/i2s_pdm.h" diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md b/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md index bcb7f73f000..04700c11bd7 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/README.md @@ -18,7 +18,7 @@ This example is going to show how to use the PDM TX and RX mode. #### PDM RX -* A PDM microphone whose `sel` pin is supposed to be pulled down, and connecting its `clk` pin to `EXAMPLE_PDM_RX_CLK_IO`, `data` pin to `EXAMPLE_PDM_RX_DIN_IO`. +* For non-ESP32-S3 SoC, a PDM microphone whose `sel` pin is supposed to be pulled down, and connecting its `clk` pin to `EXAMPLE_PDM_RX_CLK_IO`, `data` pin to `EXAMPLE_PDM_RX_DIN_IO`. ``` ┌───────────────────────┐ ┌──────────────────┐ @@ -36,6 +36,66 @@ This example is going to show how to use the PDM TX and RX mode. └───────────────────────┘ └──────────────────┘ ``` +* For ESP32-S3 SoC, this example shows how to support 8 PDM microphones, in this case, the connection can be: + +``` +┌──────────────────┐ ┌─────────────────────────┐ ┌──────────────────┐ +│ PDM microphone3 │ │ ESP │ │ PDM microphone1 │ +│ │ PDM clock │ │ PDM clock │ │ +│ CLK │◄───┬───────────────────┤ EXAMPLE_PDM_RX_CLK_IO ├───────────────────┬───►│ CLK │ +│ │ │ │ │ │ │ │ +│ DATA ├────┼────┐ │ EXAMPLE_PDM_RX_DIN_IO │◄─────────────┬────┼────┤ DATA │ +│ │ │ │ │ │ │ │ │ │ +│ SEL ├────┼────┼─────────┐ │ │ ┌─────────┼────┼────┤ SEL │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ GND ├────┼────┼────┐ │ │ │ │ ┌────┼────┼────┤ GND │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ VCC ├────┼────┼────┼────┤ │ │ ├────┼────┼────┼────┤ VCC │ +└──────────────────┘ │ │ │ │ │ │ │ │ │ │ └──────────────────┘ + │ │ │ │ │ │ │ │ │ │ +┌──────────────────┐ │ │ │ │ │ │ │ │ │ │ ┌──────────────────┐ +│ PDM microphone4 │ │ │ │ │ │ │ │ │ │ │ │ PDM microphone2 │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ CLK │◄───┤ │ │ │ │ │ │ │ │ ├───►│ CLK │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ DATA ├────┼────┴────┼────┼───►│ EXAMPLE_PDM_RX_DIN1_IO │ │ │ └────┼────┤ DATA │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ SEL ├────┼─────────┤ │ │ │ │ ├─────────┼────┤ SEL │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ GND ├────┼─────────┤ │ │ │ │ ├─────────┼────┤ GND │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ VCC ├────┼─────────┼────┤ │ │ ├────┼─────────┼────┤ VCC │ +└──────────────────┘ │ │ │ │ │ │ │ │ └──────────────────┘ + │ │ │ │ │ │ │ │ +┌──────────────────┐ │ │ │ │ │ │ │ │ ┌──────────────────┐ +│ PDM microphone7 │ │ │ │ │ │ │ │ │ │ PDM microphone5 │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ CLK │◄───┤ │ │ │ │ │ │ ├───►│ CLK │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ DATA ├────┼────┐ │ │ │ EXAMPLE_PDM_RX_DIN2_IO │◄───┼────┼────┬────┼────┤ DATA │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ SEL ├────┼────┼────┼────┤ │ │ ├────┼────┼────┼────┤ SEL │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ GND ├────┼────┼────┤ │ │ │ │ ├────┼────┼────┤ GND │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ VCC ├────┼────┼────┼────┤ │ │ ├────┼────┼────┼────┤ VCC │ +└──────────────────┘ │ │ │ │ │ │ │ │ │ │ └──────────────────┘ + │ │ │ │ │ │ │ │ │ │ +┌──────────────────┐ │ │ │ │ │ │ │ │ │ │ ┌──────────────────┐ +│ PDM microphone8 │ │ │ │ │ │ │ │ │ │ │ │ PDM microphone6 │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ CLK │◄───┘ │ │ │ │ │ │ │ │ └───►│ CLK │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ DATA ├─────────┴────┼────┼───►│ EXAMPLE_PDM_RX_DIN3_IO │ │ │ └─────────┤ DATA │ +│ │ │ │ │ │ │ │ │ │ +│ SEL ├──────────────┤ │ │ │ │ ├──────────────┤ SEL │ +│ │ │ │ │ │ │ │ │ │ +│ GND ├──────────────┴────┼────┤ GND ├────┼────┴──────────────┤ GND │ +│ │ │ │ │ │ │ │ +│ VCC ├───────────────────┴────┤ VCC ├────┴───────────────────┤ VCC │ +└──────────────────┘ └─────────────────────────┘ └──────────────────┘ +``` + #### PDM TX * An earphone or a speaker diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c index dc44a3807d6..08f091b41d2 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c @@ -15,7 +15,12 @@ #include "i2s_pdm_example.h" #define EXAMPLE_PDM_RX_CLK_IO GPIO_NUM_0 // I2S PDM RX clock io number -#define EXAMPLE_PDM_RX_DIN_IO GPIO_NUM_2 // I2S PDM RX data in io number +#define EXAMPLE_PDM_RX_DIN_IO GPIO_NUM_4 // I2S PDM RX data in io number +#if CONFIG_IDF_TARGET_ESP32S3 +#define EXAMPLE_PDM_RX_DIN1_IO GPIO_NUM_5 // I2S PDM RX data line1 in io number +#define EXAMPLE_PDM_RX_DIN2_IO GPIO_NUM_6 // I2S PDM RX data line2 in io number +#define EXAMPLE_PDM_RX_DIN3_IO GPIO_NUM_7 // I2S PDM RX data line3 in io number +#endif #define EXAMPLE_PDM_RX_FREQ_HZ 16000 // I2S PDM RX frequency @@ -39,12 +44,27 @@ static i2s_chan_handle_t i2s_example_init_pdm_rx(void) .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), .gpio_cfg = { .clk = EXAMPLE_PDM_RX_CLK_IO, +#if CONFIG_IDF_TARGET_ESP32S3 + // Only ESP32-S3 can support 4-line PDM RX + .dins = { + EXAMPLE_PDM_RX_DIN_IO, + EXAMPLE_PDM_RX_DIN1_IO, + EXAMPLE_PDM_RX_DIN2_IO, + EXAMPLE_PDM_RX_DIN3_IO, + }, +#else .din = EXAMPLE_PDM_RX_DIN_IO, +#endif .invert_flags = { .clk_inv = false, }, }, }; +#if CONFIG_IDF_TARGET_ESP32S3 + // Enable all slots for example + pdm_rx_cfg.slot_cfg.slot_mode = I2S_SLOT_MODE_STEREO; + pdm_rx_cfg.slot_cfg.slot_mask = I2S_PDM_LINE_SLOT_ALL; +#endif ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_rx_cfg)); /* Step 3: Enable the rx channels before reading data */ diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index ca2c0e43854..3717274f93c 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1104,7 +1104,6 @@ components/soc/esp32s3/include/soc/extmem_struct.h components/soc/esp32s3/include/soc/fe_reg.h components/soc/esp32s3/include/soc/gpio_pins.h components/soc/esp32s3/include/soc/gpio_reg.h -components/soc/esp32s3/include/soc/gpio_sig_map.h components/soc/esp32s3/include/soc/hinf_reg.h components/soc/esp32s3/include/soc/hinf_struct.h components/soc/esp32s3/include/soc/host_reg.h