mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 21:24:32 +02:00
Merge branch 'fix/example_pdm_mic_recording' into 'master'
example: Fixed example I2S PDM microphone recording on sdcard Closes IDF-3952 and IDFGH-5912 See merge request espressif/esp-idf!14928
This commit is contained in:
@@ -1550,10 +1550,10 @@ static esp_err_t i2s_check_cfg_validity(i2s_port_t i2s_num, i2s_hal_config_t *cf
|
|||||||
if (cfg->mode & I2S_MODE_PDM) {
|
if (cfg->mode & I2S_MODE_PDM) {
|
||||||
ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode only support on I2S0");
|
ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode only support on I2S0");
|
||||||
#if !SOC_I2S_SUPPORTS_PDM_TX
|
#if !SOC_I2S_SUPPORTS_PDM_TX
|
||||||
ESP_RETURN_ON_FALSE(cfg->mode & I2S_MODE_TX, ESP_ERR_INVALID_ARG, TAG, "PDM does not support TX on this chip");
|
ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_TX), ESP_ERR_INVALID_ARG, TAG, "PDM does not support TX on this chip");
|
||||||
#endif // SOC_I2S_SUPPORTS_PDM_TX
|
#endif // SOC_I2S_SUPPORTS_PDM_TX
|
||||||
#if !SOC_I2S_SUPPORTS_PDM_RX
|
#if !SOC_I2S_SUPPORTS_PDM_RX
|
||||||
ESP_RETURN_ON_FALSE(cfg->mode & I2S_MODE_RX, ESP_ERR_INVALID_ARG, TAG, "PDM does not support RX on this chip");
|
ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_RX), ESP_ERR_INVALID_ARG, TAG, "PDM does not support RX on this chip");
|
||||||
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// 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.
|
|
||||||
|
|
||||||
// The LL layer for I2S register operations
|
// The LL layer for I2S register operations
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@@ -86,6 +78,26 @@ static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw)
|
|||||||
hw->rx_clkm_conf.rx_clk_active = 1;
|
hw->rx_clkm_conf.rx_clk_active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable I2S tx module clock
|
||||||
|
*
|
||||||
|
* @param hw Peripheral I2S hardware instance address.
|
||||||
|
*/
|
||||||
|
static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->tx_clkm_conf.tx_clk_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable I2S rx module clock
|
||||||
|
*
|
||||||
|
* @param hw Peripheral I2S hardware instance address.
|
||||||
|
*/
|
||||||
|
static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->rx_clkm_conf.rx_clk_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S mclk use tx module clock
|
* @brief I2S mclk use tx module clock
|
||||||
*
|
*
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// 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.
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* NOTICE
|
* NOTICE
|
||||||
@@ -87,6 +79,26 @@ static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw)
|
|||||||
hw->rx_clkm_conf.rx_clk_active = 1;
|
hw->rx_clkm_conf.rx_clk_active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable I2S tx module clock
|
||||||
|
*
|
||||||
|
* @param hw Peripheral I2S hardware instance address.
|
||||||
|
*/
|
||||||
|
static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->tx_clkm_conf.tx_clk_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable I2S rx module clock
|
||||||
|
*
|
||||||
|
* @param hw Peripheral I2S hardware instance address.
|
||||||
|
*/
|
||||||
|
static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->rx_clkm_conf.rx_clk_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S mclk use tx module clock
|
* @brief I2S mclk use tx module clock
|
||||||
*
|
*
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// 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.
|
|
||||||
|
|
||||||
// The LL layer for I2S register operations
|
// The LL layer for I2S register operations
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@@ -87,6 +79,26 @@ static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw)
|
|||||||
hw->rx_clkm_conf.rx_clk_active = 1;
|
hw->rx_clkm_conf.rx_clk_active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable I2S tx module clock
|
||||||
|
*
|
||||||
|
* @param hw Peripheral I2S hardware instance address.
|
||||||
|
*/
|
||||||
|
static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->tx_clkm_conf.tx_clk_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable I2S rx module clock
|
||||||
|
*
|
||||||
|
* @param hw Peripheral I2S hardware instance address.
|
||||||
|
*/
|
||||||
|
static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->rx_clkm_conf.rx_clk_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S mclk use tx module clock
|
* @brief I2S mclk use tx module clock
|
||||||
*
|
*
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// 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.
|
|
||||||
|
|
||||||
|
|
||||||
// The HAL layer for I2S (common part)
|
// The HAL layer for I2S (common part)
|
||||||
@@ -104,6 +96,15 @@ void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rat
|
|||||||
{
|
{
|
||||||
/* enable pdm tx mode */
|
/* enable pdm tx mode */
|
||||||
i2s_ll_tx_enable_pdm(hal->dev, true);
|
i2s_ll_tx_enable_pdm(hal->dev, true);
|
||||||
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_tx_enable_clock(hal->dev);
|
||||||
|
i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
|
||||||
|
i2s_ll_mclk_use_tx_clk(hal->dev);
|
||||||
|
/* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
|
||||||
|
i2s_ll_tx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
|
||||||
|
#else
|
||||||
|
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
|
||||||
|
#endif
|
||||||
/* set pdm tx default presacle */
|
/* set pdm tx default presacle */
|
||||||
i2s_ll_tx_set_pdm_prescale(hal->dev, 0);
|
i2s_ll_tx_set_pdm_prescale(hal->dev, 0);
|
||||||
/* set pdm tx default sacle of high pass filter */
|
/* set pdm tx default sacle of high pass filter */
|
||||||
@@ -140,6 +141,18 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal)
|
|||||||
i2s_ll_rx_enable_pdm(hal->dev, true);
|
i2s_ll_rx_enable_pdm(hal->dev, true);
|
||||||
/* set pdm rx downsample number */
|
/* set pdm rx downsample number */
|
||||||
i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S);
|
i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S);
|
||||||
|
#if !SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
|
||||||
|
#endif
|
||||||
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_rx_enable_clock(hal->dev);
|
||||||
|
i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
|
||||||
|
i2s_ll_mclk_use_rx_clk(hal->dev);
|
||||||
|
/* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
|
||||||
|
i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
|
||||||
|
#else
|
||||||
|
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||||
|
|
||||||
@@ -286,8 +299,8 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
|||||||
{
|
{
|
||||||
/* Set tx common mode */
|
/* Set tx common mode */
|
||||||
i2s_hal_tx_set_common_mode(hal, hal_cfg);
|
i2s_hal_tx_set_common_mode(hal, hal_cfg);
|
||||||
i2s_hal_tx_set_channel_style(hal, hal_cfg);
|
|
||||||
}
|
}
|
||||||
|
i2s_hal_tx_set_channel_style(hal, hal_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set configurations for RX mode */
|
/* Set configurations for RX mode */
|
||||||
@@ -304,8 +317,8 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
|||||||
{
|
{
|
||||||
/* Set rx common mode */
|
/* Set rx common mode */
|
||||||
i2s_hal_rx_set_common_mode(hal, hal_cfg);
|
i2s_hal_rx_set_common_mode(hal, hal_cfg);
|
||||||
i2s_hal_rx_set_channel_style(hal, hal_cfg);
|
|
||||||
}
|
}
|
||||||
|
i2s_hal_rx_set_channel_style(hal, hal_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set configurations for full-duplex mode */
|
/* Set configurations for full-duplex mode */
|
||||||
@@ -318,3 +331,35 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void i2s_hal_start_tx(i2s_hal_context_t *hal)
|
||||||
|
{
|
||||||
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_tx_enable_clock(hal->dev);
|
||||||
|
#endif
|
||||||
|
i2s_ll_tx_start(hal->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2s_hal_start_rx(i2s_hal_context_t *hal)
|
||||||
|
{
|
||||||
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_rx_enable_clock(hal->dev);
|
||||||
|
#endif
|
||||||
|
i2s_ll_rx_start(hal->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2s_hal_stop_tx(i2s_hal_context_t *hal)
|
||||||
|
{
|
||||||
|
i2s_ll_tx_stop(hal->dev);
|
||||||
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_tx_disable_clock(hal->dev);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2s_hal_stop_rx(i2s_hal_context_t *hal)
|
||||||
|
{
|
||||||
|
i2s_ll_rx_stop(hal->dev);
|
||||||
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
i2s_ll_rx_disable_clock(hal->dev);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// 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.
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* NOTICE
|
* NOTICE
|
||||||
@@ -176,28 +168,28 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal);
|
|||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @param hal Context of the HAL layer
|
||||||
*/
|
*/
|
||||||
#define i2s_hal_start_tx(hal) i2s_ll_tx_start((hal)->dev)
|
void i2s_hal_start_tx(i2s_hal_context_t *hal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start I2S rx
|
* @brief Start I2S rx
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @param hal Context of the HAL layer
|
||||||
*/
|
*/
|
||||||
#define i2s_hal_start_rx(hal) i2s_ll_rx_start((hal)->dev)
|
void i2s_hal_start_rx(i2s_hal_context_t *hal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop I2S tx
|
* @brief Stop I2S tx
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @param hal Context of the HAL layer
|
||||||
*/
|
*/
|
||||||
#define i2s_hal_stop_tx(hal) i2s_ll_tx_stop((hal)->dev)
|
void i2s_hal_stop_tx(i2s_hal_context_t *hal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop I2S rx
|
* @brief Stop I2S rx
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @param hal Context of the HAL layer
|
||||||
*/
|
*/
|
||||||
#define i2s_hal_stop_rx(hal) i2s_ll_rx_stop((hal)->dev)
|
void i2s_hal_stop_rx(i2s_hal_context_t *hal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the received data length to trigger `in_suc_eof` interrupt.
|
* @brief Set the received data length to trigger `in_suc_eof` interrupt.
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32 |
|
| Supported Targets | ESP32 | ESP32-S3 |
|
||||||
| ----------------- | ----- |
|
| ----------------- | ----- | -------- |
|
||||||
|
|
||||||
# I2S Digital Microphone Recording Example
|
# I2S Digital Microphone Recording Example
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ The audio is recorded into the SDCard using WAVE file format.
|
|||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
* A development board with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
|
* A development board with ESP32 or ESP32S3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
|
||||||
* A USB cable for power supply and programming
|
* A USB cable for power supply and programming
|
||||||
* A digital microphone (SPK0838HT4H PDM output was used in this example)
|
* A digital microphone (SPK0838HT4H PDM output was used in this example)
|
||||||
|
|
||||||
@@ -28,17 +28,17 @@ The default GPIO configuration is the following:
|
|||||||
|
|
||||||
|Mic | GPIO |
|
|Mic | GPIO |
|
||||||
|:---------:|:------:|
|
|:---------:|:------:|
|
||||||
| PDM Clock | GPIO22 |
|
| PDM Clock | GPIO4 |
|
||||||
| PDM Data | GPIO23 |
|
| PDM Data | GPIO5 |
|
||||||
|
|
||||||
The SDCard is connected using SPI peripheral.
|
The SDCard is connected using SPI peripheral.
|
||||||
|
|
||||||
| SPI | SDCard | GPIO |
|
| SPI | SDCard | GPIO |
|
||||||
|:----:|:------:|:------:|
|
|:----:|:------:|:------:|
|
||||||
| MISO | DAT0 | GPIO2 |
|
| MISO | DAT0 | GPIO17 |
|
||||||
| MOSI | CMD | GPIO15 |
|
| MOSI | CMD | GPIO16 |
|
||||||
| SCLK | CLK | GPIO14 |
|
| SCLK | CLK | GPIO18 |
|
||||||
| CS | CD | GPIO13 |
|
| CS | CD | GPIO19 |
|
||||||
|
|
||||||
To change the GPIO configuration, see the `Example Configuration` from the menuconfig.
|
To change the GPIO configuration, see the `Example Configuration` from the menuconfig.
|
||||||
|
|
||||||
|
@@ -4,25 +4,25 @@ menu "Example Configuration"
|
|||||||
|
|
||||||
config EXAMPLE_SPI_MISO_GPIO
|
config EXAMPLE_SPI_MISO_GPIO
|
||||||
int "SPI MISO GPIO"
|
int "SPI MISO GPIO"
|
||||||
default 2
|
default 15
|
||||||
help
|
help
|
||||||
Set the GPIO number used for MISO from SPI.
|
Set the GPIO number used for MISO from SPI.
|
||||||
|
|
||||||
config EXAMPLE_SPI_MOSI_GPIO
|
config EXAMPLE_SPI_MOSI_GPIO
|
||||||
int "SPI MOSI GPIO"
|
int "SPI MOSI GPIO"
|
||||||
default 15
|
default 14
|
||||||
help
|
help
|
||||||
Set the GPIO number used for MOSI from SPI.
|
Set the GPIO number used for MOSI from SPI.
|
||||||
|
|
||||||
config EXAMPLE_SPI_SCLK_GPIO
|
config EXAMPLE_SPI_SCLK_GPIO
|
||||||
int "SPI SCLK GPIO"
|
int "SPI SCLK GPIO"
|
||||||
default 14
|
default 18
|
||||||
help
|
help
|
||||||
Set the GPIO number used for SCLK from SPI.
|
Set the GPIO number used for SCLK from SPI.
|
||||||
|
|
||||||
config EXAMPLE_SPI_CS_GPIO
|
config EXAMPLE_SPI_CS_GPIO
|
||||||
int "SPI CS GPIO"
|
int "SPI CS GPIO"
|
||||||
default 13
|
default 19
|
||||||
help
|
help
|
||||||
Set the GPIO number used for CS from SPI.
|
Set the GPIO number used for CS from SPI.
|
||||||
|
|
||||||
@@ -36,13 +36,13 @@ menu "Example Configuration"
|
|||||||
help
|
help
|
||||||
Set the I2S channel number.
|
Set the I2S channel number.
|
||||||
|
|
||||||
config EXAMPLE_AUDIO_SAMPLE_RATE
|
config EXAMPLE_SAMPLE_RATE
|
||||||
int "Audio Sample Rate"
|
int "Audio Sample Rate"
|
||||||
default 44100
|
default 44100
|
||||||
help
|
help
|
||||||
Set the audio sample rate frequency. Usually 16000 or 44100 Hz.
|
Set the audio sample rate frequency. Usually 16000 or 44100 Hz.
|
||||||
|
|
||||||
config EXAMPLE_AUDIO_BIT_SAMPLE
|
config EXAMPLE_BIT_SAMPLE
|
||||||
int "Audio Bit Sample"
|
int "Audio Bit Sample"
|
||||||
default 16
|
default 16
|
||||||
help
|
help
|
||||||
@@ -50,13 +50,13 @@ menu "Example Configuration"
|
|||||||
|
|
||||||
config EXAMPLE_I2S_DATA_GPIO
|
config EXAMPLE_I2S_DATA_GPIO
|
||||||
int "I2S Data GPIO"
|
int "I2S Data GPIO"
|
||||||
default 23
|
default 5
|
||||||
help
|
help
|
||||||
Set the GPIO number used for transmitting/receiving data from I2S.
|
Set the GPIO number used for transmitting/receiving data from I2S.
|
||||||
|
|
||||||
config EXAMPLE_I2S_CLK_GPIO
|
config EXAMPLE_I2S_CLK_GPIO
|
||||||
int "I2S Clock GPIO"
|
int "I2S Clock GPIO"
|
||||||
default 22
|
default 4
|
||||||
help
|
help
|
||||||
Set the GPIO number used for the clock line from I2S.
|
Set the GPIO number used for the clock line from I2S.
|
||||||
|
|
||||||
|
@@ -8,30 +8,28 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "driver/i2s.h"
|
#include "driver/i2s.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "esp_system.h"
|
|
||||||
#include <math.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include <sys/unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_vfs_fat.h"
|
|
||||||
#include "driver/sdspi_host.h"
|
|
||||||
#include "driver/spi_common.h"
|
#include "driver/spi_common.h"
|
||||||
#include "sdmmc_cmd.h"
|
#include "sdmmc_cmd.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
static const char* TAG = "pdm_rec_example";
|
static const char* TAG = "pdm_rec_example";
|
||||||
|
|
||||||
#define AUDIO_SAMPLE_SIZE (CONFIG_EXAMPLE_AUDIO_BIT_SAMPLE * 1024)
|
#define SPI_DMA_CHAN SPI_DMA_CH_AUTO
|
||||||
#define SAMPLES_NUM ((CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE/100) * 2)
|
#define NUM_CHANNELS (1) // For mono recording only!
|
||||||
#define BYTE_RATE (1 * CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE * ((CONFIG_EXAMPLE_AUDIO_BIT_SAMPLE / 8))
|
|
||||||
#define FLASH_RECORD_SIZE (BYTE_RATE * CONFIG_EXAMPLE_REC_TIME))
|
|
||||||
#define SD_MOUNT_POINT "/sdcard"
|
#define SD_MOUNT_POINT "/sdcard"
|
||||||
#define SPI_DMA_CHAN (1)
|
#define SAMPLE_SIZE (CONFIG_EXAMPLE_BIT_SAMPLE * 1024)
|
||||||
|
#define BYTE_RATE (CONFIG_EXAMPLE_SAMPLE_RATE * (CONFIG_EXAMPLE_BIT_SAMPLE / 8)) * NUM_CHANNELS
|
||||||
|
|
||||||
// When testing SD and SPI modes, keep in mind that once the card has been
|
// When testing SD and SPI modes, keep in mind that once the card has been
|
||||||
// initialized in SPI mode, it can not be reinitialized in SD mode without
|
// initialized in SPI mode, it can not be reinitialized in SD mode without
|
||||||
@@ -39,7 +37,7 @@ static const char* TAG = "pdm_rec_example";
|
|||||||
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
||||||
sdmmc_card_t* card;
|
sdmmc_card_t* card;
|
||||||
|
|
||||||
static int16_t i2s_readraw_buff[AUDIO_SAMPLE_SIZE];
|
static int16_t i2s_readraw_buff[SAMPLE_SIZE];
|
||||||
size_t bytes_read;
|
size_t bytes_read;
|
||||||
const int WAVE_HEADER_SIZE = 44;
|
const int WAVE_HEADER_SIZE = 44;
|
||||||
|
|
||||||
@@ -52,17 +50,10 @@ void mount_sdcard(void)
|
|||||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||||
.format_if_mount_failed = true,
|
.format_if_mount_failed = true,
|
||||||
.max_files = 5,
|
.max_files = 5,
|
||||||
.allocation_unit_size = 16 * 1024
|
.allocation_unit_size = 8 * 1024
|
||||||
};
|
};
|
||||||
ESP_LOGI(TAG, "Initializing SD card");
|
ESP_LOGI(TAG, "Initializing SD card");
|
||||||
|
|
||||||
// Use settings defined above to initialize SD card and mount FAT filesystem.
|
|
||||||
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
|
|
||||||
// Please check its source code and implement error recovery when developing
|
|
||||||
// production applications.
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Using SPI peripheral");
|
|
||||||
|
|
||||||
spi_bus_config_t bus_cfg = {
|
spi_bus_config_t bus_cfg = {
|
||||||
.mosi_io_num = CONFIG_EXAMPLE_SPI_MOSI_GPIO,
|
.mosi_io_num = CONFIG_EXAMPLE_SPI_MOSI_GPIO,
|
||||||
.miso_io_num = CONFIG_EXAMPLE_SPI_MISO_GPIO,
|
.miso_io_num = CONFIG_EXAMPLE_SPI_MISO_GPIO,
|
||||||
@@ -87,8 +78,7 @@ void mount_sdcard(void)
|
|||||||
|
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
if (ret == ESP_FAIL) {
|
if (ret == ESP_FAIL) {
|
||||||
ESP_LOGE(TAG, "Failed to mount filesystem. "
|
ESP_LOGE(TAG, "Failed to mount filesystem.");
|
||||||
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
|
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
|
||||||
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
||||||
@@ -100,13 +90,13 @@ void mount_sdcard(void)
|
|||||||
sdmmc_card_print_info(stdout, card);
|
sdmmc_card_print_info(stdout, card);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wavHeader(char* wav_header, uint32_t wav_size, uint32_t sample_rate){
|
void generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate){
|
||||||
|
|
||||||
// See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
|
// See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
|
||||||
uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;
|
uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;
|
||||||
uint32_t byte_rate = 1 * CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE * (CONFIG_EXAMPLE_AUDIO_BIT_SAMPLE / 8);
|
uint32_t byte_rate = BYTE_RATE;
|
||||||
|
|
||||||
const char set_wav_header[] = {
|
const char set_wav_header[] = {
|
||||||
'R','I','F','F', // ChunkID
|
'R','I','F','F', // ChunkID
|
||||||
file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
|
file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
|
||||||
'W','A','V','E', // Format
|
'W','A','V','E', // Format
|
||||||
@@ -120,19 +110,21 @@ const char set_wav_header[] = {
|
|||||||
0x10, 0x00, // BitsPerSample (16 bits)
|
0x10, 0x00, // BitsPerSample (16 bits)
|
||||||
'd','a','t','a', // Subchunk2ID
|
'd','a','t','a', // Subchunk2ID
|
||||||
wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
|
wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
|
||||||
};
|
};
|
||||||
|
|
||||||
memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
|
memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_wav(void)
|
void record_wav(uint32_t rec_time)
|
||||||
{
|
{
|
||||||
// Use POSIX and C standard library functions to work with files.
|
// Use POSIX and C standard library functions to work with files.
|
||||||
int flash_wr_size = 0;
|
int flash_wr_size = 0;
|
||||||
ESP_LOGI(TAG, "Opening file");
|
ESP_LOGI(TAG, "Opening file");
|
||||||
|
|
||||||
char wav_header_fmt[WAVE_HEADER_SIZE];
|
char wav_header_fmt[WAVE_HEADER_SIZE];
|
||||||
wavHeader(wav_header_fmt, FLASH_RECORD_SIZE, CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE);
|
|
||||||
|
uint32_t flash_rec_time = BYTE_RATE * rec_time;
|
||||||
|
generate_wav_header(wav_header_fmt, flash_rec_time, CONFIG_EXAMPLE_SAMPLE_RATE);
|
||||||
|
|
||||||
// First check if file exists before creating a new file.
|
// First check if file exists before creating a new file.
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -152,9 +144,9 @@ void record_wav(void)
|
|||||||
fwrite(wav_header_fmt, 1, WAVE_HEADER_SIZE, f);
|
fwrite(wav_header_fmt, 1, WAVE_HEADER_SIZE, f);
|
||||||
|
|
||||||
// Start recording
|
// Start recording
|
||||||
while (flash_wr_size < FLASH_RECORD_SIZE) {
|
while (flash_wr_size < flash_rec_time) {
|
||||||
// Read the RAW samples from the microphone
|
// Read the RAW samples from the microphone
|
||||||
i2s_read(CONFIG_EXAMPLE_I2S_CH, (char *)i2s_readraw_buff, AUDIO_SAMPLE_SIZE, &bytes_read, portMAX_DELAY);
|
i2s_read(CONFIG_EXAMPLE_I2S_CH, (char *)i2s_readraw_buff, SAMPLE_SIZE, &bytes_read, 100);
|
||||||
// Write the samples to the WAV file
|
// Write the samples to the WAV file
|
||||||
fwrite(i2s_readraw_buff, 1, bytes_read, f);
|
fwrite(i2s_readraw_buff, 1, bytes_read, f);
|
||||||
flash_wr_size += bytes_read;
|
flash_wr_size += bytes_read;
|
||||||
@@ -173,27 +165,32 @@ void record_wav(void)
|
|||||||
|
|
||||||
void init_microphone(void)
|
void init_microphone(void)
|
||||||
{
|
{
|
||||||
|
// Set the I2S configuration as PDM and 16bits per sample
|
||||||
i2s_config_t i2s_config = {
|
i2s_config_t i2s_config = {
|
||||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM,
|
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM,
|
||||||
.sample_rate = CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE,
|
.sample_rate = CONFIG_EXAMPLE_SAMPLE_RATE,
|
||||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
|
||||||
.dma_buf_count = 64,
|
.dma_buf_count = 8,
|
||||||
.dma_buf_len = 1024,
|
.dma_buf_len = 200,
|
||||||
.use_apll = 1
|
.use_apll = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
i2s_pin_config_t pin_config;
|
// Set the pinout configuration (set using menuconfig)
|
||||||
pin_config.bck_io_num = I2S_PIN_NO_CHANGE;
|
i2s_pin_config_t pin_config = {
|
||||||
pin_config.ws_io_num = CONFIG_EXAMPLE_I2S_CLK_GPIO;
|
.mck_io_num = I2S_PIN_NO_CHANGE,
|
||||||
pin_config.data_out_num = I2S_PIN_NO_CHANGE;
|
.bck_io_num = I2S_PIN_NO_CHANGE,
|
||||||
pin_config.data_in_num = CONFIG_EXAMPLE_I2S_DATA_GPIO;
|
.ws_io_num = CONFIG_EXAMPLE_I2S_CLK_GPIO,
|
||||||
|
.data_out_num = I2S_PIN_NO_CHANGE,
|
||||||
|
.data_in_num = CONFIG_EXAMPLE_I2S_DATA_GPIO,
|
||||||
|
};
|
||||||
|
|
||||||
i2s_driver_install(CONFIG_EXAMPLE_I2S_CH, &i2s_config, 0, NULL);
|
// Call driver installation function before any I2S R/W operation.
|
||||||
i2s_set_pin(CONFIG_EXAMPLE_I2S_CH, &pin_config);
|
ESP_ERROR_CHECK( i2s_driver_install(CONFIG_EXAMPLE_I2S_CH, &i2s_config, 0, NULL) );
|
||||||
i2s_set_clk(CONFIG_EXAMPLE_I2S_CH, CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
|
ESP_ERROR_CHECK( i2s_set_pin(CONFIG_EXAMPLE_I2S_CH, &pin_config) );
|
||||||
|
ESP_ERROR_CHECK( i2s_set_clk(CONFIG_EXAMPLE_I2S_CH, CONFIG_EXAMPLE_SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
@@ -205,5 +202,7 @@ void app_main(void)
|
|||||||
init_microphone();
|
init_microphone();
|
||||||
ESP_LOGI(TAG, "Starting recording for %d seconds!", CONFIG_EXAMPLE_REC_TIME);
|
ESP_LOGI(TAG, "Starting recording for %d seconds!", CONFIG_EXAMPLE_REC_TIME);
|
||||||
// Start Recording
|
// Start Recording
|
||||||
record_wav();
|
record_wav(CONFIG_EXAMPLE_REC_TIME);
|
||||||
|
// Stop I2S driver and destroy
|
||||||
|
ESP_ERROR_CHECK( i2s_driver_uninstall(CONFIG_EXAMPLE_I2S_CH) );
|
||||||
}
|
}
|
||||||
|
@@ -1517,7 +1517,6 @@ components/hal/esp32c3/include/hal/gpspi_flash_ll.h
|
|||||||
components/hal/esp32c3/include/hal/hmac_hal.h
|
components/hal/esp32c3/include/hal/hmac_hal.h
|
||||||
components/hal/esp32c3/include/hal/hmac_ll.h
|
components/hal/esp32c3/include/hal/hmac_ll.h
|
||||||
components/hal/esp32c3/include/hal/i2c_ll.h
|
components/hal/esp32c3/include/hal/i2c_ll.h
|
||||||
components/hal/esp32c3/include/hal/i2s_ll.h
|
|
||||||
components/hal/esp32c3/include/hal/interrupt_controller_ll.h
|
components/hal/esp32c3/include/hal/interrupt_controller_ll.h
|
||||||
components/hal/esp32c3/include/hal/ledc_ll.h
|
components/hal/esp32c3/include/hal/ledc_ll.h
|
||||||
components/hal/esp32c3/include/hal/memprot_ll.h
|
components/hal/esp32c3/include/hal/memprot_ll.h
|
||||||
@@ -1555,7 +1554,6 @@ components/hal/esp32h2/include/hal/gpspi_flash_ll.h
|
|||||||
components/hal/esp32h2/include/hal/hmac_hal.h
|
components/hal/esp32h2/include/hal/hmac_hal.h
|
||||||
components/hal/esp32h2/include/hal/hmac_ll.h
|
components/hal/esp32h2/include/hal/hmac_ll.h
|
||||||
components/hal/esp32h2/include/hal/i2c_ll.h
|
components/hal/esp32h2/include/hal/i2c_ll.h
|
||||||
components/hal/esp32h2/include/hal/i2s_ll.h
|
|
||||||
components/hal/esp32h2/include/hal/interrupt_controller_ll.h
|
components/hal/esp32h2/include/hal/interrupt_controller_ll.h
|
||||||
components/hal/esp32h2/include/hal/ledc_ll.h
|
components/hal/esp32h2/include/hal/ledc_ll.h
|
||||||
components/hal/esp32h2/include/hal/memprot_ll.h
|
components/hal/esp32h2/include/hal/memprot_ll.h
|
||||||
@@ -1634,7 +1632,6 @@ components/hal/esp32s3/include/hal/gdma_ll.h
|
|||||||
components/hal/esp32s3/include/hal/gpio_ll.h
|
components/hal/esp32s3/include/hal/gpio_ll.h
|
||||||
components/hal/esp32s3/include/hal/gpspi_flash_ll.h
|
components/hal/esp32s3/include/hal/gpspi_flash_ll.h
|
||||||
components/hal/esp32s3/include/hal/i2c_ll.h
|
components/hal/esp32s3/include/hal/i2c_ll.h
|
||||||
components/hal/esp32s3/include/hal/i2s_ll.h
|
|
||||||
components/hal/esp32s3/include/hal/interrupt_controller_ll.h
|
components/hal/esp32s3/include/hal/interrupt_controller_ll.h
|
||||||
components/hal/esp32s3/include/hal/lcd_ll.h
|
components/hal/esp32s3/include/hal/lcd_ll.h
|
||||||
components/hal/esp32s3/include/hal/ledc_ll.h
|
components/hal/esp32s3/include/hal/ledc_ll.h
|
||||||
@@ -1669,7 +1666,6 @@ components/hal/gdma_hal.c
|
|||||||
components/hal/gpio_hal.c
|
components/hal/gpio_hal.c
|
||||||
components/hal/i2c_hal.c
|
components/hal/i2c_hal.c
|
||||||
components/hal/i2c_hal_iram.c
|
components/hal/i2c_hal_iram.c
|
||||||
components/hal/i2s_hal.c
|
|
||||||
components/hal/include/hal/adc_hal.h
|
components/hal/include/hal/adc_hal.h
|
||||||
components/hal/include/hal/adc_types.h
|
components/hal/include/hal/adc_types.h
|
||||||
components/hal/include/hal/aes_hal.h
|
components/hal/include/hal/aes_hal.h
|
||||||
@@ -1689,7 +1685,6 @@ components/hal/include/hal/gpio_hal.h
|
|||||||
components/hal/include/hal/gpio_types.h
|
components/hal/include/hal/gpio_types.h
|
||||||
components/hal/include/hal/i2c_hal.h
|
components/hal/include/hal/i2c_hal.h
|
||||||
components/hal/include/hal/i2c_types.h
|
components/hal/include/hal/i2c_types.h
|
||||||
components/hal/include/hal/i2s_hal.h
|
|
||||||
components/hal/include/hal/i2s_types.h
|
components/hal/include/hal/i2s_types.h
|
||||||
components/hal/include/hal/interrupt_controller_hal.h
|
components/hal/include/hal/interrupt_controller_hal.h
|
||||||
components/hal/include/hal/interrupt_controller_types.h
|
components/hal/include/hal/interrupt_controller_types.h
|
||||||
|
Reference in New Issue
Block a user