refactor(i2s_es8311): refactor es8311 example

This commit is contained in:
laokaiyao
2025-03-21 17:15:57 +08:00
parent 84fca56744
commit 92f3faff41
11 changed files with 192 additions and 145 deletions

View File

@@ -61,40 +61,11 @@ menu "Example Configuration"
default 24 if BIT_WIDTH_24BIT
default 32 if BIT_WIDTH_32BIT
choice EXAMPLE_SELECT_MIC_GAIN
prompt "Set MIC gain"
default MIC_GAIN_18DB
help
Select the default microphone gain
config MIC_GAIN_0DB
bool "0dB"
config MIC_GAIN_6DB
bool "6dB"
config MIC_GAIN_12DB
bool "12dB"
config MIC_GAIN_18DB
bool "18dB"
config MIC_GAIN_24DB
bool "24dB"
config MIC_GAIN_30DB
bool "30dB"
config MIC_GAIN_36DB
bool "36dB"
config MIC_GAIN_42DB
bool "42dB"
endchoice
config EXAMPLE_CODEC_MIC_GAIN
int
default 0 if MIC_GAIN_0DB
default 1 if MIC_GAIN_6DB
default 2 if MIC_GAIN_12DB
default 3 if MIC_GAIN_18DB
default 4 if MIC_GAIN_24DB
default 5 if MIC_GAIN_30DB
default 6 if MIC_GAIN_36DB
default 7 if MIC_GAIN_42DB
int "Set MIC gain (unit: dB)"
default 18
help
Select mic gain for echo mode
config EXAMPLE_CODEC_VOLUME
int "Voice volume"

View File

@@ -1,3 +1,3 @@
idf_component_register(SRCS "i2s_es8311_example.c"
PRIV_REQUIRES esp_driver_i2s esp_driver_gpio
PRIV_REQUIRES esp_driver_i2s esp_driver_i2c esp_driver_gpio
EMBED_FILES "canon.pcm")

View File

@@ -1,5 +1,54 @@
menu "Example Configuration"
menu "Example IO Configuration"
config EXAMPLE_PA_CTRL_IO
int "Power Amplifier control IO"
default 53 if IDF_TARGET_ESP32P4
default -1
help
Set GPIO number for PA control. Set -1 to disable PA control.
config EXAMPLE_I2C_SDA_IO
int "I2C SDA IO"
default 17 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 9 if IDF_TARGET_ESP32H2
default 7
config EXAMPLE_I2C_SCL_IO
int "I2C SCL IO"
default 16 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 8 if IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32P4
default 6
config EXAMPLE_I2S_MCLK_IO
int "I2S MCLK IO"
default 13 if IDF_TARGET_ESP32P4
default 0
config EXAMPLE_I2S_BCLK_IO
int "I2S BCLK IO"
default 12 if IDF_TARGET_ESP32P4
default 4
config EXAMPLE_I2S_WS_IO
int "I2S WS IO"
default 10 if IDF_TARGET_ESP32P4
default 5
config EXAMPLE_I2S_DIN_IO
int "I2S DIN IO"
default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 11 if IDF_TARGET_ESP32P4
default 3
config EXAMPLE_I2S_DOUT_IO
int "I2S DOUT IO"
default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 9 if IDF_TARGET_ESP32P4
default 2
endmenu
choice EXAMPLE_MODE
prompt "Example mode"
default EXAMPLE_MODE_MUSIC
@@ -13,42 +62,13 @@ menu "Example Configuration"
bool "echo"
endchoice
choice EXAMPLE_SELECT_MIC_GAIN
prompt "Set MIC gain"
config EXAMPLE_MIC_GAIN
int "Set MIC gain (unit: dB)"
depends on EXAMPLE_MODE_ECHO
default MIC_GAIN_18DB
default 18
help
Select mic gain for echo mode
config MIC_GAIN_0DB
bool "0dB"
config MIC_GAIN_6DB
bool "6dB"
config MIC_GAIN_12DB
bool "12dB"
config MIC_GAIN_18DB
bool "18dB"
config MIC_GAIN_24DB
bool "24dB"
config MIC_GAIN_30DB
bool "30dB"
config MIC_GAIN_36DB
bool "36dB"
config MIC_GAIN_42DB
bool "42dB"
endchoice
config EXAMPLE_MIC_GAIN
int
default 0 if MIC_GAIN_0DB
default 1 if MIC_GAIN_6DB
default 2 if MIC_GAIN_12DB
default 3 if MIC_GAIN_18DB
default 4 if MIC_GAIN_24DB
default 5 if MIC_GAIN_30DB
default 6 if MIC_GAIN_36DB
default 7 if MIC_GAIN_42DB
config EXAMPLE_VOICE_VOLUME
int "Voice volume"
range 0 100
@@ -56,16 +76,10 @@ menu "Example Configuration"
help
Set voice volume
config EXAMPLE_PA_CTRL_IO
int "Power Amplifier control IO"
default 53 if IDF_TARGET_ESP32P4
default -1
help
Set GPIO number for PA control. Set -1 to disable PA control.
config EXAMPLE_BSP
bool "Enable Board Support Package (BSP) support"
default n
select CODEC_I2C_BACKWARD_COMPATIBLE
help
Use BSP to setup all hardware settings. Specific board must be selected in main/idf_component.yml file.
endmenu

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
@@ -19,47 +19,23 @@
#define EXAMPLE_MIC_GAIN CONFIG_EXAMPLE_MIC_GAIN
#endif
#if !defined(CONFIG_EXAMPLE_BSP)
#ifndef CONFIG_EXAMPLE_BSP
/* I2C port and GPIOs */
#define I2C_NUM (0)
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define I2C_SCL_IO (GPIO_NUM_16)
#define I2C_SDA_IO (GPIO_NUM_17)
#elif CONFIG_IDF_TARGET_ESP32H2
#define I2C_SCL_IO (GPIO_NUM_8)
#define I2C_SDA_IO (GPIO_NUM_9)
#elif CONFIG_IDF_TARGET_ESP32P4
#define I2C_SCL_IO (GPIO_NUM_8)
#define I2C_SDA_IO (GPIO_NUM_7)
#else
#define I2C_SCL_IO (GPIO_NUM_6)
#define I2C_SDA_IO (GPIO_NUM_7)
#endif
#define I2C_SCL_IO CONFIG_EXAMPLE_I2C_SCL_IO
#define I2C_SDA_IO CONFIG_EXAMPLE_I2C_SDA_IO
/* I2S port and GPIOs */
#define I2S_NUM (0)
#if CONFIG_IDF_TARGET_ESP32P4
#define I2S_MCK_IO (GPIO_NUM_13)
#define I2S_BCK_IO (GPIO_NUM_12)
#define I2S_WS_IO (GPIO_NUM_10)
#define I2S_DO_IO (GPIO_NUM_9)
#define I2S_DI_IO (GPIO_NUM_11)
#else
#define I2S_MCK_IO (GPIO_NUM_0)
#define I2S_BCK_IO (GPIO_NUM_4)
#define I2S_WS_IO (GPIO_NUM_5)
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define I2S_DO_IO (GPIO_NUM_18)
#define I2S_DI_IO (GPIO_NUM_19)
#else
#define I2S_DO_IO (GPIO_NUM_2)
#define I2S_DI_IO (GPIO_NUM_3)
#endif
#endif
#define I2S_MCK_IO CONFIG_EXAMPLE_I2S_MCLK_IO
#define I2S_BCK_IO CONFIG_EXAMPLE_I2S_BCLK_IO
#define I2S_WS_IO CONFIG_EXAMPLE_I2S_WS_IO
#define I2S_DO_IO CONFIG_EXAMPLE_I2S_DOUT_IO
#define I2S_DI_IO CONFIG_EXAMPLE_I2S_DIN_IO
#else // CONFIG_EXAMPLE_BSP
#include "bsp/esp-bsp.h"
#define I2C_NUM BSP_I2C_NUM
#define I2S_NUM (0)
#endif // CONFIG_EXAMPLE_BSP

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
@@ -10,10 +10,15 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_std.h"
#ifndef CONFIG_EXAMPLE_BSP
#include "driver/i2c_master.h"
#endif
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_codec_dev_defaults.h"
#include "esp_codec_dev.h"
#include "esp_codec_dev_vol.h"
#include "esp_check.h"
#include "es8311.h"
#include "example_config.h"
static const char *TAG = "i2s_es8311";
@@ -32,45 +37,101 @@ extern const uint8_t music_pcm_end[] asm("_binary_canon_pcm_end");
static esp_err_t es8311_codec_init(void)
{
/* Initialize I2C peripheral */
#if !defined(CONFIG_EXAMPLE_BSP)
const i2c_config_t es_i2c_cfg = {
#ifndef CONFIG_EXAMPLE_BSP
i2c_master_bus_handle_t i2c_bus_handle = NULL;
i2c_master_bus_config_t i2c_mst_cfg = {
.i2c_port = I2C_NUM,
.sda_io_num = I2C_SDA_IO,
.scl_io_num = I2C_SCL_IO,
.mode = I2C_MODE_MASTER,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
/* Pull-up internally for no external pull-up case.
Suggest to use external pull-up to ensure a strong enough pull-up. */
.flags.enable_internal_pullup = true,
};
ESP_RETURN_ON_ERROR(i2c_param_config(I2C_NUM, &es_i2c_cfg), TAG, "config i2c failed");
ESP_RETURN_ON_ERROR(i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0), TAG, "install i2c driver failed");
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_cfg, &i2c_bus_handle));
#else
ESP_ERROR_CHECK(bsp_i2c_init());
#endif
/* Initialize es8311 codec */
es8311_handle_t es_handle = es8311_create(I2C_NUM, ES8311_ADDRRES_0);
ESP_RETURN_ON_FALSE(es_handle, ESP_FAIL, TAG, "es8311 create failed");
const es8311_clock_config_t es_clk = {
.mclk_inverted = false,
.sclk_inverted = false,
.mclk_from_mclk_pin = true,
.mclk_frequency = EXAMPLE_MCLK_FREQ_HZ,
.sample_frequency = EXAMPLE_SAMPLE_RATE
/* Create control interface with I2C bus handle */
audio_codec_i2c_cfg_t i2c_cfg = {
.port = I2C_NUM,
.addr = ES8311_CODEC_DEFAULT_ADDR,
#ifndef CONFIG_EXAMPLE_BSP
.bus_handle = i2c_bus_handle,
#endif
};
const audio_codec_ctrl_if_t *ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);
assert(ctrl_if);
ESP_ERROR_CHECK(es8311_init(es_handle, &es_clk, ES8311_RESOLUTION_16, ES8311_RESOLUTION_16));
ESP_RETURN_ON_ERROR(es8311_sample_frequency_config(es_handle, EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE, EXAMPLE_SAMPLE_RATE), TAG, "set es8311 sample frequency failed");
ESP_RETURN_ON_ERROR(es8311_voice_volume_set(es_handle, EXAMPLE_VOICE_VOLUME, NULL), TAG, "set es8311 volume failed");
ESP_RETURN_ON_ERROR(es8311_microphone_config(es_handle, false), TAG, "set es8311 microphone failed");
/* Create data interface with I2S bus handle */
audio_codec_i2s_cfg_t i2s_cfg = {
.port = I2S_NUM,
.rx_handle = rx_handle,
.tx_handle = tx_handle,
};
const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg);
assert(data_if);
/* Create ES8311 interface handle */
const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();
assert(gpio_if);
es8311_codec_cfg_t es8311_cfg = {
.ctrl_if = ctrl_if,
.gpio_if = gpio_if,
.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH,
.master_mode = false,
.use_mclk = true,
.pa_pin = EXAMPLE_PA_CTRL_IO,
.pa_reverted = false,
.hw_gain = {
.pa_voltage = 5.0,
.codec_dac_voltage = 3.3,
},
.mclk_div = EXAMPLE_MCLK_MULTIPLE,
};
const audio_codec_if_t *es8311_if = es8311_codec_new(&es8311_cfg);
assert(es8311_if);
/* Create the top codec handle with ES8311 interface handle and data interface */
esp_codec_dev_cfg_t dev_cfg = {
.dev_type = ESP_CODEC_DEV_TYPE_IN_OUT,
.codec_if = es8311_if,
.data_if = data_if,
};
esp_codec_dev_handle_t codec_handle = esp_codec_dev_new(&dev_cfg);
assert(codec_handle);
/* Specify the sample configurations and open the device */
esp_codec_dev_sample_info_t sample_cfg = {
.bits_per_sample = I2S_DATA_BIT_WIDTH_16BIT,
.channel = 2,
.channel_mask = 0x03,
.sample_rate = EXAMPLE_SAMPLE_RATE,
};
if (esp_codec_dev_open(codec_handle, &sample_cfg) != ESP_CODEC_DEV_OK) {
ESP_LOGE(TAG, "Open codec device failed");
return ESP_FAIL;
}
/* Set the initial volume and gain */
if (esp_codec_dev_set_out_vol(codec_handle, EXAMPLE_VOICE_VOLUME) != ESP_CODEC_DEV_OK) {
ESP_LOGE(TAG, "set output volume failed");
return ESP_FAIL;
}
#if CONFIG_EXAMPLE_MODE_ECHO
ESP_RETURN_ON_ERROR(es8311_microphone_gain_set(es_handle, EXAMPLE_MIC_GAIN), TAG, "set es8311 microphone gain failed");
if (esp_codec_dev_set_in_gain(codec_handle, EXAMPLE_MIC_GAIN) != ESP_CODEC_DEV_OK) {
ESP_LOGE(TAG, "set input gain failed");
return ESP_FAIL;
}
#endif
return ESP_OK;
}
static esp_err_t i2s_driver_init(void)
{
#if !defined(CONFIG_EXAMPLE_BSP)
#ifndef CONFIG_EXAMPLE_BSP
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER);
chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
@@ -200,16 +261,6 @@ void app_main(void)
ESP_LOGI(TAG, "es8311 codec init success");
}
#if EXAMPLE_PA_CTRL_IO >= 0
/* Enable PA by setting the PA_CTRL_IO to high, because the power amplifier on some dev-kits are disabled by default */
gpio_config_t gpio_cfg = {
.pin_bit_mask = 1ULL << EXAMPLE_PA_CTRL_IO,
.mode = GPIO_MODE_OUTPUT,
};
ESP_ERROR_CHECK(gpio_config(&gpio_cfg));
ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PA_CTRL_IO, 1));
#endif
#if CONFIG_EXAMPLE_MODE_MUSIC
/* Play a piece of music in music mode */
xTaskCreate(i2s_music, "i2s_music", 4096, NULL, 5, NULL);

View File

@@ -1,7 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
idf: "^5.0"
espressif/es8311: "^1.0.0"
espressif/esp_codec_dev: ^1.3.4
# After enabling Board Support Packages support in menuconfig, you can pick you specific BSP here
espressif/esp-box:

View File

@@ -14,7 +14,30 @@ from pytest_embedded_idf.utils import idf_parametrize
def test_i2s_es8311_example_generic(dut: Dut) -> None:
dut.expect('i2s es8311 codec example start')
dut.expect('-----------------------------')
dut.expect('I \\(([0-9]+)\\) i2s_es8311: i2s driver init success')
dut.expect('i2s_es8311: i2s driver init success')
@pytest.mark.es8311
@pytest.mark.parametrize(
'config',
[
's3_korvo2_v3',
],
indirect=True,
)
@idf_parametrize('target', ['esp32s3'], indirect=['target'])
def test_i2s_es8311_example_korvo2_v3(dut: Dut) -> None:
dut.expect(r'i2s es8311 codec example start')
dut.expect(r'-----------------------------')
dut.expect(r'i2s_es8311: i2s driver init success')
dut.expect(r'ES8311: Work in Slave mode')
dut.expect(r'I2S_IF: channel mode [0-9]+ bits:[0-9]+/[0-9]+ channel:[0-9]+ mask:[0-9]+')
dut.expect(r'I2S_IF: STD Mode [0-9]+ bits:[0-9]+/[0-9]+ channel:[0-9]+ sample_rate:[0-9]+ mask:[0-9]+')
dut.expect(r'I2S_IF: channel mode [0-9]+ bits:[0-9]+/[0-9]+ channel:[0-9]+ mask:[0-9]+')
dut.expect(r'I2S_IF: STD Mode [0-9]+ bits:[0-9]+/[0-9]+ channel:[0-9]+ sample_rate:[0-9]+ mask:[0-9]+')
dut.expect(r'Adev_Codec: Open codec device OK')
dut.expect(r'i2s_es8311: es8311 codec init success')
dut.expect(r'Returned from app_main\(\)')
@pytest.mark.generic
@@ -30,4 +53,4 @@ def test_i2s_es8311_example_bsp(dut: Dut) -> None:
dut.expect('i2s es8311 codec example start')
dut.expect('-----------------------------')
dut.expect('Using BSP for HW configuration')
dut.expect('I \\(([0-9]+)\\) i2s_es8311: i2s driver init success')
dut.expect('i2s_es8311: i2s driver init success')

View File

@@ -1,2 +1,3 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_EXAMPLE_BSP=y
CONFIG_CODEC_I2C_BACKWARD_COMPATIBLE=y

View File

@@ -0,0 +1,8 @@
CONFIG_EXAMPLE_PA_CTRL_IO=48
CONFIG_EXAMPLE_I2C_SDA_IO=17
CONFIG_EXAMPLE_I2C_SCL_IO=18
CONFIG_EXAMPLE_I2S_MCLK_IO=16
CONFIG_EXAMPLE_I2S_BCLK_IO=9
CONFIG_EXAMPLE_I2S_WS_IO=45
CONFIG_EXAMPLE_I2S_DIN_IO=10
CONFIG_EXAMPLE_I2S_DOUT_IO=8

View File

@@ -0,0 +1 @@
CONFIG_CODEC_I2C_BACKWARD_COMPATIBLE=n

View File

@@ -123,6 +123,8 @@ ENV_MARKERS = {
'httpbin': 'runner for tests that need to access the httpbin service',
'flash_4mb': 'C2 runners with 4 MB flash',
'jtag_re_enable': 'Runner to re-enable jtag which is softly disabled by burning bit SOFT_DIS_JTAG on eFuse',
'es8311': 'Development board that carries es8311 codec',
'es7210': 'Development board that carries es7210 codec',
# multi-dut markers
'multi_dut_modbus_rs485': 'a pair of runners connected by RS485 bus',
'ieee802154': 'ieee802154 related tests should run on ieee802154 runners.',