refactor(i2s): make i2s driver as component

This commit is contained in:
laokaiyao 2023-11-07 21:06:07 +08:00
parent f0129e17a8
commit 74441d14ab
68 changed files with 297 additions and 177 deletions

View File

@ -12,7 +12,6 @@ set(includes "include"
"deprecated"
"dac/include"
"i2c/include"
"i2s/include"
"ledc/include"
"parlio/include"
"rmt/include"
@ -73,16 +72,7 @@ endif()
# I2S related source files
if(CONFIG_SOC_I2S_SUPPORTED)
list(APPEND srcs "i2s/i2s_common.c"
"i2s/i2s_platform.c"
"i2s/i2s_std.c"
"deprecated/i2s_legacy.c")
if(CONFIG_SOC_I2S_SUPPORTS_PDM)
list(APPEND srcs "i2s/i2s_pdm.c")
endif()
if(CONFIG_SOC_I2S_SUPPORTS_TDM)
list(APPEND srcs "i2s/i2s_tdm.c")
endif()
list(APPEND srcs "deprecated/i2s_legacy.c")
endif()
# LEDC related source files
@ -183,7 +173,7 @@ else()
# for backward compatibility, the driver component needs to
# have a public dependency on other "esp_driver_foo" components
esp_driver_gpio esp_driver_pcnt esp_driver_gptimer esp_driver_spi esp_driver_mcpwm
esp_driver_sdmmc esp_driver_ana_cmpr
esp_driver_sdmmc esp_driver_ana_cmpr esp_driver_i2s
LDFRAGMENTS ${ldfragments}
)
endif()

View File

@ -122,29 +122,6 @@ menu "Driver Configurations"
orsource "./rmt/Kconfig.rmt"
menu "I2S Configuration"
depends on SOC_I2S_SUPPORTED
config I2S_ISR_IRAM_SAFE
bool "I2S ISR IRAM-Safe"
default n
help
Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be
executable when the cache is disabled (e.g. SPI Flash write).
config I2S_SUPPRESS_DEPRECATE_WARN
bool "Suppress leagcy driver deprecated warning"
default n
help
Enable this option will suppress the deprecation warnings of using APIs in legacy I2S driver.
config I2S_ENABLE_DEBUG_LOG
bool "Enable I2S debug log"
default n
help
Wether to enable the debug log message for I2S driver.
Note that, this option only controls the I2S driver log, will not affect other drivers.
endmenu # I2S Configuration
menu "DAC Configuration"
depends on SOC_DAC_SUPPORTED
config DAC_CTRL_FUNC_IN_IRAM

View File

@ -12,31 +12,6 @@ components/driver/test_apps/i2c_test_apps:
disable:
- if: SOC_I2C_SUPPORTED != 1 # TODO: IDF-8070
components/driver/test_apps/i2s_test_apps:
disable:
- if: SOC_I2S_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/i2s_test_apps/i2s:
disable:
- if: SOC_I2S_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/i2s_test_apps/i2s_multi_dev:
disable:
- if: SOC_I2S_SUPPORTED != 1
- if: SOC_I2S_HW_VERSION_2 != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac:
disable:
- if: SOC_I2S_SUPPORTS_ADC_DAC != 1

View File

@ -8,5 +8,6 @@ endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity esp_driver_pcnt driver esp_adc
PRIV_REQUIRES unity esp_driver_pcnt esp_adc
driver # TODO: IDF-8370 remove driver when esp_driver_dac created
WHOLE_ARCHIVE)

View File

@ -155,14 +155,14 @@ static void example_i2s_init(void)
};
//install and start i2s driver
TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) );
TEST_ESP_OK(i2s_driver_install(i2s_num, &i2s_config, 0, NULL));
//init ADC pad
TEST_ESP_OK( i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL) );
TEST_ESP_OK(i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL));
}
static void example_i2s_deinit(void)
{
TEST_ESP_OK( i2s_driver_uninstall(EXAMPLE_I2S_NUM) );
TEST_ESP_OK(i2s_driver_uninstall(EXAMPLE_I2S_NUM));
}
/**
@ -172,9 +172,11 @@ static void example_disp_buf(uint8_t *buf, int length)
{
printf("\n======");
for (int i = 0; i < length; i += 2) {
uint16_t data = ((uint16_t)buf[i+1] << 8) | (uint16_t)buf[i];
uint16_t data = ((uint16_t)buf[i + 1] << 8) | (uint16_t)buf[i];
adc_digi_output_data_t *p = (adc_digi_output_data_t *)&data;
if ((i) % 16 == 0) printf("\n");
if ((i) % 16 == 0) {
printf("\n");
}
printf("[%d_%d] ", p->type1.channel, p->type1.data);
}
printf("\n======\n");
@ -183,17 +185,17 @@ static void example_disp_buf(uint8_t *buf, int length)
static esp_err_t adc_dma_data_check(uint8_t *buf, int length, int ideal_level)
{
for (int i = 0; i < length; i += 2) {
uint16_t data = ((uint16_t)buf[i+1] << 8) | (uint16_t)buf[i];
uint16_t data = ((uint16_t)buf[i + 1] << 8) | (uint16_t)buf[i];
adc_digi_output_data_t *p = (adc_digi_output_data_t *)&data;
if (p->type1.channel != I2S_ADC_CHANNEL) {
TEST_FAIL_MESSAGE("I2S-DMA data channel error!");
}
if (ideal_level == 1) { // high level 3.3v
TEST_ASSERT_EQUAL( 0xFFF, p->type1.data );
TEST_ASSERT_EQUAL(0xFFF, p->type1.data);
} else if (ideal_level == 0) { // low level 0v
TEST_ASSERT_LESS_THAN( 10, p->type1.data );
TEST_ASSERT_LESS_THAN(10, p->type1.data);
} else if (ideal_level == 2) { // middle level 1.4v
TEST_ASSERT_INT_WITHIN( 128, 1586, p->type1.data );
TEST_ASSERT_INT_WITHIN(128, 1586, p->type1.data);
} else if (ideal_level == 3) { // normal level
} else { // no check
}
@ -209,7 +211,7 @@ static void adc_dma_read(uint8_t *buf, int length)
vTaskDelay(pdTICKS_TO_MS(100));
while (flash_wr_size < length) {
//read data from I2S bus, in this case, from ADC.
TEST_ESP_OK( i2s_read(EXAMPLE_I2S_NUM, (void *) buf + flash_wr_size, length - flash_wr_size, &bytes_read, portMAX_DELAY) );
TEST_ESP_OK(i2s_read(EXAMPLE_I2S_NUM, (void *) buf + flash_wr_size, length - flash_wr_size, &bytes_read, portMAX_DELAY));
flash_wr_size += bytes_read;
example_disp_buf((uint8_t *) buf, 128);
}
@ -221,7 +223,7 @@ TEST_CASE("ADC_DMA_read", "[adc dma]")
char *i2s_read_buff = (char *) calloc(i2s_read_len, sizeof(char));
example_i2s_init();
TEST_ESP_OK( i2s_adc_enable(EXAMPLE_I2S_NUM) );
TEST_ESP_OK(i2s_adc_enable(EXAMPLE_I2S_NUM));
adc_fake_tie_low(I2S_ADC_UNIT, I2S_ADC_CHANNEL);
adc_dma_read((uint8_t *)i2s_read_buff, i2s_read_len);
@ -237,7 +239,7 @@ TEST_CASE("ADC_DMA_read", "[adc dma]")
adc_io_normal(I2S_ADC_UNIT, I2S_ADC_CHANNEL);
TEST_ESP_OK( i2s_adc_disable(EXAMPLE_I2S_NUM) );
TEST_ESP_OK(i2s_adc_disable(EXAMPLE_I2S_NUM));
if (i2s_read_buff) {
free(i2s_read_buff);
i2s_read_buff = NULL;

View File

@ -62,15 +62,15 @@ static void example_i2s_init(void)
.use_apll = 0,
};
//install and start i2s driver
TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) );
TEST_ESP_OK(i2s_driver_install(i2s_num, &i2s_config, 0, NULL));
//init DAC pad
TEST_ESP_OK( i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN) );
TEST_ESP_OK(i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN));
}
static void example_i2s_deinit(void)
{
TEST_ESP_OK( i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE) );
TEST_ESP_OK( i2s_driver_uninstall(EXAMPLE_I2S_NUM) );
TEST_ESP_OK(i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE));
TEST_ESP_OK(i2s_driver_uninstall(EXAMPLE_I2S_NUM));
}
/**
@ -78,7 +78,7 @@ static void example_i2s_deinit(void)
*/
static void example_set_file_play_mode(void)
{
TEST_ESP_OK( i2s_set_clk(EXAMPLE_I2S_NUM, 16000, EXAMPLE_I2S_SAMPLE_BITS, 1) );
TEST_ESP_OK(i2s_set_clk(EXAMPLE_I2S_NUM, 16000, EXAMPLE_I2S_SAMPLE_BITS, 1));
}
/**
@ -125,7 +125,7 @@ static void example_disp_buf(uint8_t *buf, int length)
*/
static void example_reset_play_mode(void)
{
TEST_ESP_OK( i2s_set_clk(EXAMPLE_I2S_NUM, EXAMPLE_I2S_SAMPLE_RATE, EXAMPLE_I2S_SAMPLE_BITS, EXAMPLE_I2S_CHANNEL_NUM) );
TEST_ESP_OK(i2s_set_clk(EXAMPLE_I2S_NUM, EXAMPLE_I2S_SAMPLE_RATE, EXAMPLE_I2S_SAMPLE_BITS, EXAMPLE_I2S_CHANNEL_NUM));
}
TEST_CASE("DAC_DMA_output", "[dac]")

View File

@ -223,8 +223,8 @@ static bool whether_contains_exapected_data(uint16_t *src, uint32_t src_len, uin
if (src[i] == val) {
if (val == start_val && i < src_len - 8) {
printf("start index: %d ---> \n%d %d %d %d %d %d %d %d\n", i,
src[i], src[i+1], src[i+2], src[i+3],
src[i+4], src[i+5], src[i+6], src[i+7]);
src[i], src[i + 1], src[i + 2], src[i + 3],
src[i + 4], src[i + 5], src[i + 6], src[i + 7]);
}
index_step = src_step;
val += val_step;
@ -299,7 +299,7 @@ TEST_CASE("I2S_legacy_mono_stereo_loopback_test", "[i2s_legacy]")
uint32_t retry = 0;
bool is_failed = false;
for (int n = 0; n < WRITE_BUF_LEN / 2; n++) {
w_buf[n] = n%100;
w_buf[n] = n % 100;
}
/* rx right mono test
* tx format: 0x00[L] 0x01[R] 0x02[L] 0x03[R] ...
@ -307,14 +307,14 @@ TEST_CASE("I2S_legacy_mono_stereo_loopback_test", "[i2s_legacy]")
TEST_ESP_OK(i2s_write(I2S_NUM_0, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
for (retry = 0; retry < RETEY_TIMES; retry++) {
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32
/* The data of tx/rx channels are flipped on ESP32 */
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
int16_t temp = r_buf[n];
r_buf[n] = r_buf[n+1];
r_buf[n+1] = temp;
r_buf[n] = r_buf[n + 1];
r_buf[n + 1] = temp;
}
#endif
#endif
/* Expected: 1 3 5 7 9 ... 97 99 */
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 1, 2)) {
break;
@ -385,14 +385,14 @@ TEST_CASE("I2S_legacy_mono_stereo_loopback_test", "[i2s_legacy]")
TEST_ESP_OK(i2s_write(I2S_NUM_0, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
for (retry = 0; retry < RETEY_TIMES; retry++) {
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32
/* The data of tx/rx channels are flipped on ESP32 */
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
int16_t temp = r_buf[n];
r_buf[n] = r_buf[n+1];
r_buf[n+1] = temp;
r_buf[n] = r_buf[n + 1];
r_buf[n + 1] = temp;
}
#endif
#endif
/* Expected: 2 4 6 8 10 ... 96 98 */
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 2, 2)) {
break;
@ -877,7 +877,8 @@ static void i2s_test_common_sample_rate(i2s_port_t id)
const uint32_t test_freq[] = {
8000, 10000, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000, 64000, 88200,
96000, 128000, 144000,196000};
96000, 128000, 144000, 196000
};
int real_pulse = 0;
#if CONFIG_IDF_ENV_FPGA
// Limit the test sample rate on FPGA platform due to the low frequency it supports.

View File

@ -7,7 +7,6 @@ components/esp_adc/test_apps/adc:
depends_components:
- esp_adc
- esp_driver_gpio
- esp_driver_i2s # ADC continuous driver relies on I2S on ESP32
- efuse
- esp_driver_spi # ADC continuous driver relies on SPI on ESP32S2
depends_filepatterns:
- components/driver/i2s/**/* # ADC continuous driver relies on I2S on ESP32
- esp_driver_spi # ADC continuous driver relies on SPI on ESP32S2

View File

@ -0,0 +1,26 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs)
set(include "include")
# I2S related source files
if(CONFIG_SOC_I2S_SUPPORTED)
list(APPEND srcs "i2s_common.c"
"i2s_platform.c"
"i2s_std.c")
if(CONFIG_SOC_I2S_SUPPORTS_PDM)
list(APPEND srcs "i2s_pdm.c")
endif()
if(CONFIG_SOC_I2S_SUPPORTS_TDM)
list(APPEND srcs "i2s_tdm.c")
endif()
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include}
PRIV_REQUIRES esp_driver_gpio esp_pm esp_mm
)

View File

@ -0,0 +1,22 @@
menu "ESP-Driver:I2S Configurations"
depends on SOC_I2S_SUPPORTED
config I2S_ISR_IRAM_SAFE
bool "I2S ISR IRAM-Safe"
default n
help
Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be
executable when the cache is disabled (e.g. SPI Flash write).
config I2S_SUPPRESS_DEPRECATE_WARN
bool "Suppress legacy driver deprecated warning"
default n
help
Enable this option will suppress the deprecation warnings of using APIs in legacy I2S driver.
config I2S_ENABLE_DEBUG_LOG
bool "Enable I2S debug log"
default n
help
Wether to enable the debug log message for I2S driver.
Note that, this option only controls the I2S driver log, will not affect other drivers.
endmenu # I2S Configuration

View File

@ -32,7 +32,6 @@
#if SOC_I2S_SUPPORTS_ADC_DAC
#include "hal/adc_ll.h"
#include "driver/adc_i2s_legacy.h"
#endif
#if SOC_I2S_SUPPORTS_APLL
#include "hal/clk_tree_ll.h"
@ -70,7 +69,8 @@
static const char *TAG = "i2s_common";
__attribute__((always_inline))
inline void *i2s_dma_calloc(size_t num, size_t size, uint32_t caps, size_t *actual_size) {
inline void *i2s_dma_calloc(size_t num, size_t size, uint32_t caps, size_t *actual_size)
{
void *ptr = NULL;
esp_dma_calloc(num, size, caps, &ptr, actual_size);
return ptr;
@ -205,7 +205,7 @@ static i2s_controller_t *i2s_acquire_controller_obj(int id)
portEXIT_CRITICAL(&g_i2s.spinlock);
#if SOC_I2S_SUPPORTS_ADC_DAC
if (id == I2S_NUM_0) {
adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_IO_SIG);
adc_ll_digi_set_data_source(0);
}
#endif
} else {
@ -703,12 +703,12 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
/* Initialize I2S module interrupt */
if (handle->dir == I2S_DIR_TX) {
esp_intr_alloc_intrstatus(i2s_periph_signal[port_id].irq, intr_flag,
(uint32_t)i2s_ll_get_interrupt_status_reg(handle->controller->hal.dev), I2S_LL_TX_EVENT_MASK,
i2s_dma_tx_callback, handle, &handle->dma.dma_chan);
(uint32_t)i2s_ll_get_interrupt_status_reg(handle->controller->hal.dev), I2S_LL_TX_EVENT_MASK,
i2s_dma_tx_callback, handle, &handle->dma.dma_chan);
} else {
esp_intr_alloc_intrstatus(i2s_periph_signal[port_id].irq, intr_flag,
(uint32_t)i2s_ll_get_interrupt_status_reg(handle->controller->hal.dev), I2S_LL_RX_EVENT_MASK,
i2s_dma_rx_callback, handle, &handle->dma.dma_chan);
(uint32_t)i2s_ll_get_interrupt_status_reg(handle->controller->hal.dev), I2S_LL_RX_EVENT_MASK,
i2s_dma_rx_callback, handle, &handle->dma.dma_chan);
}
/* Start DMA */
i2s_ll_enable_dma(handle->controller->hal.dev, true);
@ -957,7 +957,7 @@ esp_err_t i2s_channel_get_info(i2s_chan_handle_t handle, i2s_chan_info_t *chan_i
for (int i = 0; i < SOC_I2S_NUM; i++) {
if (g_i2s.controller[i] != NULL) {
if (g_i2s.controller[i]->tx_chan == handle ||
g_i2s.controller[i]->rx_chan == handle) {
g_i2s.controller[i]->rx_chan == handle) {
goto found;
}
}
@ -984,7 +984,6 @@ found:
return ESP_OK;
}
esp_err_t i2s_channel_enable(i2s_chan_handle_t handle)
{
I2S_NULL_POINTER_CHECK(TAG, handle);
@ -1064,7 +1063,7 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
/* Loop until no bytes in source buff remain or the descriptors are full */
while (remain_bytes) {
size_t bytes_can_load = remain_bytes > (tx_handle->dma.buf_size - tx_handle->dma.rw_pos) ?
(tx_handle->dma.buf_size - tx_handle->dma.rw_pos) : remain_bytes;
(tx_handle->dma.buf_size - tx_handle->dma.rw_pos) : remain_bytes;
/* When all the descriptors has loaded data, no more bytes can be loaded, break directly */
if (bytes_can_load == 0) {
break;
@ -1085,7 +1084,7 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
* will remain at the end of the last dma buffer */
if (STAILQ_NEXT((lldesc_t *)tx_handle->dma.curr_desc, qe) != tx_handle->dma.desc[0]) {
tx_handle->dma.curr_desc = STAILQ_NEXT((lldesc_t *)tx_handle->dma.curr_desc, qe);
tx_handle->dma.curr_ptr = (void *)(((lldesc_t *)tx_handle->dma.curr_desc)->buf);
tx_handle->dma.curr_ptr = (void *)(((lldesc_t *)tx_handle->dma.curr_desc)->buf);
tx_handle->dma.rw_pos = 0;
} else {
break;

View File

@ -320,7 +320,6 @@ err:
#endif
/*---------------------------------------------------------------
PDM RX
---------------------------------------------------------------*/

View File

@ -15,8 +15,8 @@ static const char *TAG = "i2s_platform";
*/
i2s_platform_t g_i2s = {
.spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED,
.controller[0 ... (SOC_I2S_NUM - 1)] = NULL, // groups will be lazy installed
.comp_name[0 ... (SOC_I2S_NUM - 1)] = NULL,
.controller[0 ...(SOC_I2S_NUM - 1)] = NULL, // groups will be lazy installed
.comp_name[0 ...(SOC_I2S_NUM - 1)] = NULL,
};
/*---------------------------------------------------------------------------
@ -74,5 +74,5 @@ size_t i2s_platform_get_dma_buffer_offset(void)
{
/* Force to transfer address '0' into 'i2s_chan_handle_t' type,
* then find the corresponding field , the address of this field is the offset of this type */
return (size_t)&(((i2s_chan_handle_t)0)->dma.bufs);
return (size_t) & (((i2s_chan_handle_t)0)->dma.bufs);
}

View File

@ -147,8 +147,8 @@ struct i2s_channel_obj_t {
QueueHandle_t msg_queue; /*!< Message queue handler, used for transporting data between interrupt and read/write task */
i2s_event_callbacks_internal_t callbacks; /*!< Callback functions */
void *user_data; /*!< User data for callback functions */
void (*start)(i2s_chan_handle_t); /*!< start tx/rx channel */
void (*stop)(i2s_chan_handle_t); /*!< stop tx/rx channel */
void (*start)(i2s_chan_handle_t); /*!< start tx/rx channel */
void (*stop)(i2s_chan_handle_t); /*!< stop tx/rx channel */
};
/**

View File

@ -147,8 +147,7 @@ static esp_err_t i2s_std_set_gpio(i2s_chan_handle_t handle, const i2s_std_gpio_c
i2s_std_config_t *std_cfg = (i2s_std_config_t *)(handle->mode_info);
/* Loopback if dout = din */
if (gpio_cfg->dout != -1 &&
gpio_cfg->dout == gpio_cfg->din) {
if (gpio_cfg->dout != -1 && gpio_cfg->dout == gpio_cfg->din) {
i2s_gpio_loopback_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, i2s_periph_signal[id].data_in_sig);
} else if (handle->dir == I2S_DIR_TX) {
/* Set data output GPIO */

View File

@ -152,7 +152,7 @@ static esp_err_t i2s_tdm_set_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_c
i2s_tdm_config_t *tdm_cfg = (i2s_tdm_config_t *)(handle->mode_info);
/* Loopback if dout = din */
if (gpio_cfg->dout != -1 &&
gpio_cfg->dout == gpio_cfg->din) {
gpio_cfg->dout == gpio_cfg->din) {
i2s_gpio_loopback_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, i2s_periph_signal[id].data_in_sig);
} else if (handle->dir == I2S_DIR_TX) {
/* Set data output GPIO */
@ -198,7 +198,6 @@ static esp_err_t i2s_tdm_set_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_c
return ESP_OK;
}
esp_err_t i2s_channel_init_tdm_mode(i2s_chan_handle_t handle, const i2s_tdm_config_t *tdm_cfg)
{
#if CONFIG_I2S_ENABLE_DEBUG_LOG

View File

@ -66,8 +66,6 @@ extern "C" {
.bclk_div = 8, \
}
/**
* @brief I2S slot configuration for PDM RX mode
*/
@ -190,10 +188,8 @@ esp_err_t i2s_channel_reconfig_pdm_rx_slot(i2s_chan_handle_t handle, const i2s_p
*/
esp_err_t i2s_channel_reconfig_pdm_rx_gpio(i2s_chan_handle_t handle, const i2s_pdm_rx_gpio_config_t *gpio_cfg);
#endif // SOC_I2S_SUPPORTS_PDM_RX
#if SOC_I2S_SUPPORTS_PDM_TX
#if SOC_I2S_HW_VERSION_2
/**

View File

@ -113,7 +113,6 @@ extern "C" {
I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) // Alias
/** @endcond */
/**
* @brief I2S default TDM clock configuration
* @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while the data width in slot configuration is set to 24 bits
@ -258,7 +257,6 @@ esp_err_t i2s_channel_reconfig_tdm_slot(i2s_chan_handle_t handle, const i2s_tdm_
*/
esp_err_t i2s_channel_reconfig_tdm_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_config_t *gpio_cfg);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,25 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/esp_driver_i2s/test_apps/i2s:
disable:
- if: SOC_I2S_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
- esp_driver_gpio
- esp_driver_pcnt
components/esp_driver_i2s/test_apps/i2s_multi_dev:
disable:
- if: SOC_I2S_SUPPORTED != 1
- if: SOC_I2S_HW_VERSION_2 != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
- esp_driver_gpio

View File

@ -10,7 +10,7 @@ project(i2s_test)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_i2s/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--elf-file ${CMAKE_BINARY_DIR}/i2s_test.elf
find-refs
--from-sections=.iram0.text

View File

@ -145,7 +145,7 @@ static void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_
// test the read data right or not
for (int i = 0, j = 0; i < (I2S_RECV_BUF_LEN - I2S_SEND_BUF_LEN); i++) {
if (recv_buf[i] == 1) {
for (j = 1; (j < I2S_SEND_BUF_LEN) && (recv_buf[i+j] == j + 1); j++) {}
for (j = 1; (j < I2S_SEND_BUF_LEN) && (recv_buf[i + j] == j + 1); j++) {}
if (j == I2S_SEND_BUF_LEN) {
is_success = true;
goto finish;
@ -217,7 +217,8 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]")
static volatile bool task_run_flag;
static void i2s_read_task(void *args) {
static void i2s_read_task(void *args)
{
i2s_chan_handle_t rx_handle = (i2s_chan_handle_t)args;
uint8_t *recv_buf = (uint8_t *)calloc(1, 2000);
TEST_ASSERT(recv_buf);
@ -236,7 +237,8 @@ static void i2s_read_task(void *args) {
vTaskDelete(NULL);
}
static void i2s_write_task(void *args) {
static void i2s_write_task(void *args)
{
i2s_chan_handle_t tx_handle = (i2s_chan_handle_t)args;
uint8_t *send_buf = (uint8_t *)calloc(1, 2000);
TEST_ASSERT(send_buf);
@ -255,7 +257,8 @@ static void i2s_write_task(void *args) {
vTaskDelete(NULL);
}
static void i2s_reconfig_task(void *args) {
static void i2s_reconfig_task(void *args)
{
i2s_chan_handle_t tx_handle = (i2s_chan_handle_t)args;
i2s_chan_info_t chan_info;
TEST_ESP_OK(i2s_channel_get_info(tx_handle, &chan_info));
@ -374,8 +377,8 @@ static bool whether_contains_exapected_data(uint16_t *src, uint32_t src_len, uin
if (src[i] == val) {
if (val == start_val && i < src_len - 8) {
printf("start index: %d ---> \n%d %d %d %d %d %d %d %d\n", i,
src[i], src[i+1], src[i+2], src[i+3],
src[i+4], src[i+5], src[i+6], src[i+7]);
src[i], src[i + 1], src[i + 2], src[i + 3],
src[i + 4], src[i + 5], src[i + 6], src[i + 7]);
}
index_step = src_step;
val += val_step;
@ -443,7 +446,7 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
size_t r_bytes = 0;
uint32_t retry = 0;
for (int n = 0; n < WRITE_BUF_LEN / 2; n++) {
w_buf[n] = n%100;
w_buf[n] = n % 100;
}
/* rx right mono test
@ -456,8 +459,8 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
/* The data of tx/rx channels are flipped on ESP32 */
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
int16_t temp = r_buf[n];
r_buf[n] = r_buf[n+1];
r_buf[n+1] = temp;
r_buf[n] = r_buf[n + 1];
r_buf[n + 1] = temp;
}
#endif
/* Expected: 1 3 5 7 9 ... 97 99 */
@ -488,8 +491,8 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
/* The data of tx/rx channels are flipped on ESP32 */
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
int16_t temp = r_buf[n];
r_buf[n] = r_buf[n+1];
r_buf[n+1] = temp;
r_buf[n] = r_buf[n + 1];
r_buf[n + 1] = temp;
}
#endif
/* Expected: 2 4 6 8 10 ... 96 98 */
@ -750,7 +753,8 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c
const uint32_t test_freq[] = {
8000, 10000, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000, 64000, 88200,
96000, 128000,144000,196000};
96000, 128000, 144000, 196000
};
int real_pulse = 0;
int case_cnt = sizeof(test_freq) / sizeof(uint32_t);
#if SOC_I2S_SUPPORTS_PLL_F96M
@ -853,7 +857,7 @@ TEST_CASE("I2S_package_lost_test", "[i2s]")
* interrupt_interval = dma_frame_num / sample_rate = 3.549 ms
* 2. dma_desc_num > polling_cycle / interrupt_interval = cell(2.818) = 3
* 3. recv_buffer_size > dma_desc_num * dma_buffer_size = 3 * 4092 = 12276 bytes */
#define TEST_RECV_BUF_LEN 12276
#define TEST_RECV_BUF_LEN 12276
i2s_chan_handle_t rx_handle;
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);

View File

@ -208,8 +208,7 @@ static void test_i2s_tdm_slave_48k_32bits_4slots(void)
}
TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_48k_32bits_4slots", "[I2S_TDM]",
test_i2s_tdm_master_48k_32bits_4slots, test_i2s_tdm_slave_48k_32bits_4slots);
test_i2s_tdm_master_48k_32bits_4slots, test_i2s_tdm_slave_48k_32bits_4slots);
static void test_i2s_tdm_master_48k_16bits_4slots(void)
{
@ -222,8 +221,7 @@ static void test_i2s_tdm_slave_48k_16bits_4slots(void)
}
TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_48k_16bits_4slots", "[I2S_TDM]",
test_i2s_tdm_master_48k_16bits_4slots, test_i2s_tdm_slave_48k_16bits_4slots);
test_i2s_tdm_master_48k_16bits_4slots, test_i2s_tdm_slave_48k_16bits_4slots);
static void test_i2s_tdm_master_48k_8bits_4slots(void)
{
@ -236,7 +234,7 @@ static void test_i2s_tdm_slave_48k_8bits_4slots(void)
}
TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_48k_8bits_4slots", "[I2S_TDM]",
test_i2s_tdm_master_48k_8bits_4slots, test_i2s_tdm_slave_48k_8bits_4slots);
test_i2s_tdm_master_48k_8bits_4slots, test_i2s_tdm_slave_48k_8bits_4slots);
/* The I2S source clock can only reach 96Mhz on ESP32H2,
which can't satisfy the following configurations in slave mode */
@ -250,12 +248,11 @@ static void test_i2s_tdm_master_48k_16bits_8slots(void)
static void test_i2s_tdm_slave_48k_16bits_8slots(void)
{
test_i2s_tdm_slave(48000, I2S_DATA_BIT_WIDTH_16BIT, I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 |
I2S_TDM_SLOT4 | I2S_TDM_SLOT5 | I2S_TDM_SLOT6 | I2S_TDM_SLOT7);
I2S_TDM_SLOT4 | I2S_TDM_SLOT5 | I2S_TDM_SLOT6 | I2S_TDM_SLOT7);
}
TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_48k_16bits_8slots", "[I2S_TDM]",
test_i2s_tdm_master_48k_16bits_8slots, test_i2s_tdm_slave_48k_16bits_8slots);
test_i2s_tdm_master_48k_16bits_8slots, test_i2s_tdm_slave_48k_16bits_8slots);
static void test_i2s_tdm_master_96k_16bits_4slots(void)
{
@ -268,7 +265,7 @@ static void test_i2s_tdm_slave_96k_16bits_4slots(void)
}
TEST_CASE_MULTIPLE_DEVICES("I2S_TDM_full_duplex_test_in_96k_16bits_4slots", "[I2S_TDM]",
test_i2s_tdm_master_96k_16bits_4slots, test_i2s_tdm_slave_96k_16bits_4slots);
test_i2s_tdm_master_96k_16bits_4slots, test_i2s_tdm_slave_96k_16bits_4slots);
#endif // !CONFIG_IDF_TARGET_ESP32H2
static void test_i2s_external_clk_src(bool is_master, bool is_external)
@ -344,7 +341,7 @@ static void test_i2s_external_clk_src(bool is_master, bool is_external)
// Check the data
for (int i = 0; i < TEST_I2S_ARRAY_LENGTH; i++) {
if (recv_buff[i] == 0x12 && recv_buff[i + 1] == 0x34 &&
recv_buff[i + 2] == 0x56 && recv_buff[i + 3] == 0x78) {
recv_buff[i + 2] == 0x56 && recv_buff[i + 3] == 0x78) {
is_success = true;
break;
}
@ -378,7 +375,7 @@ static void test_i2s_slave_clock_in(void)
}
TEST_CASE_MULTIPLE_DEVICES("I2S_external_clock_master_output_slave_input", "[I2S]",
test_i2s_master_clock_out, test_i2s_slave_clock_in);
test_i2s_master_clock_out, test_i2s_slave_clock_in);
static void test_i2s_master_clock_in(void)
{
@ -391,4 +388,4 @@ static void test_i2s_slave_clock_out(void)
}
TEST_CASE_MULTIPLE_DEVICES("I2S_external_clock_master_input_slave_output", "[I2S]",
test_i2s_master_clock_in, test_i2s_slave_clock_out);
test_i2s_master_clock_in, test_i2s_slave_clock_out);

View File

@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SAMPLE_RATE (48000)
#define SAMPLE_BITS (16)
#if CONFIG_IDF_TARGET_ESP32
#define MASTER_MCK_IO 0
#define MASTER_BCK_IO 4
#define MASTER_WS_IO 5
#define SLAVE_BCK_IO 21
#define SLAVE_WS_IO 22
#define DATA_IN_IO 19
#define DATA_OUT_IO 18
#elif CONFIG_IDF_TARGET_ESP32S2
#define MASTER_MCK_IO 0
#define MASTER_BCK_IO 4
#define MASTER_WS_IO 5
#define SLAVE_BCK_IO 14
#define SLAVE_WS_IO 15
#define DATA_IN_IO 19
#define DATA_OUT_IO 18
#elif CONFIG_IDF_TARGET_ESP32C3
#define MASTER_MCK_IO 0
#define MASTER_BCK_IO 4
#define MASTER_WS_IO 5
#define SLAVE_BCK_IO 14
#define SLAVE_WS_IO 15
#define DATA_IN_IO 19
#define DATA_OUT_IO 18
#elif CONFIG_IDF_TARGET_ESP32S3
#define MASTER_MCK_IO 0
#define MASTER_BCK_IO 4
#define MASTER_WS_IO 5
#define SLAVE_BCK_IO 14
#define SLAVE_WS_IO 15
#define DATA_IN_IO 19
#define DATA_OUT_IO 18
#elif CONFIG_IDF_TARGET_ESP32P4
#define MASTER_MCK_IO 34
#define MASTER_BCK_IO 35
#define MASTER_WS_IO 48
#define SLAVE_BCK_IO 10
#define SLAVE_WS_IO 11
#define DATA_IN_IO 12
#define DATA_OUT_IO 49
#else
#define MASTER_MCK_IO 0
#define MASTER_BCK_IO 4
#define MASTER_WS_IO 5
#define SLAVE_BCK_IO 2
#define SLAVE_WS_IO 3
#define DATA_IN_IO 6
#define DATA_OUT_IO 7
#endif
#ifdef __cplusplus
}
#endif

View File

@ -18,6 +18,7 @@ set(priv_requires "esp_mm" "esp_psram")
if(CONFIG_SOC_I2S_LCD_I80_VARIANT)
list(APPEND srcs "src/esp_lcd_panel_io_i2s.c")
list(APPEND priv_requires "esp_driver_i2s")
endif()
if(CONFIG_SOC_LCDCAM_SUPPORTED)

View File

@ -27,8 +27,7 @@ components/esp_lcd/test_apps/i2c_lcd_legacy:
components/esp_lcd/test_apps/i80_lcd:
depends_components:
- esp_lcd
depends_filepatterns:
- components/driver/i2s/**/* # i80 IO driver relies on I2S on esp32 and esp32s2
- esp_driver_i2s
disable:
- if: SOC_LCD_I80_SUPPORTED != 1

View File

@ -4,5 +4,5 @@ set(srcs "test_app_main.c"
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES esp_lcd unity driver
PRIV_REQUIRES esp_lcd unity driver esp_driver_i2s
WHOLE_ARCHIVE)

View File

@ -80,11 +80,6 @@ INPUT = \
$(PROJECT_PATH)/components/driver/i2c/include/driver/i2c_master.h \
$(PROJECT_PATH)/components/driver/i2c/include/driver/i2c_slave.h \
$(PROJECT_PATH)/components/driver/i2c/include/driver/i2c_types.h \
$(PROJECT_PATH)/components/driver/i2s/include/driver/i2s_common.h \
$(PROJECT_PATH)/components/driver/i2s/include/driver/i2s_pdm.h \
$(PROJECT_PATH)/components/driver/i2s/include/driver/i2s_std.h \
$(PROJECT_PATH)/components/driver/i2s/include/driver/i2s_tdm.h \
$(PROJECT_PATH)/components/driver/i2s/include/driver/i2s_types.h \
$(PROJECT_PATH)/components/driver/ledc/include/driver/ledc.h \
$(PROJECT_PATH)/components/driver/parlio/include/driver/parlio_tx.h \
$(PROJECT_PATH)/components/driver/parlio/include/driver/parlio_types.h \
@ -142,6 +137,11 @@ INPUT = \
$(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_sync.h \
$(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_timer.h \
$(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_types.h \
$(PROJECT_PATH)/components/esp_driver_i2s/include/driver/i2s_common.h \
$(PROJECT_PATH)/components/esp_driver_i2s/include/driver/i2s_pdm.h \
$(PROJECT_PATH)/components/esp_driver_i2s/include/driver/i2s_std.h \
$(PROJECT_PATH)/components/esp_driver_i2s/include/driver/i2s_tdm.h \
$(PROJECT_PATH)/components/esp_driver_i2s/include/driver/i2s_types.h \
$(PROJECT_PATH)/components/esp_driver_pcnt/include/driver/pulse_cnt.h \
$(PROJECT_PATH)/components/esp_eth/include/esp_eth_com.h \
$(PROJECT_PATH)/components/esp_eth/include/esp_eth_driver.h \

View File

@ -297,7 +297,7 @@ The clock config helper macro is:
- :c:macro:`I2S_STD_CLK_DEFAULT_CONFIG`
Please refer to :ref:`i2s-api-reference-i2s_std` for information about STD API. And for more details, please refer to :component_file:`driver/i2s/include/driver/i2s_std.h`.
Please refer to :ref:`i2s-api-reference-i2s_std` for information about STD API. And for more details, please refer to :component_file:`esp_driver_i2s/include/driver/i2s_std.h`.
STD TX Mode
~~~~~~~~~~~
@ -551,7 +551,7 @@ Here is the table of the data received in the buffer with different :cpp:member:
- :c:macro:`I2S_PDM_TX_CLK_DEFAULT_CONFIG`
Please refer to :ref:`i2s-api-reference-i2s_pdm` for information about PDM TX API. And for more details, please refer to :component_file:`driver/i2s/include/driver/i2s_pdm.h`.
Please refer to :ref:`i2s-api-reference-i2s_pdm` for information about PDM TX API. And for more details, please refer to :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h`.
The PDM data width is fixed to 16-bit. When the data in an ``int16_t`` writing buffer is:
@ -647,7 +647,7 @@ Here is the table of the data received in the buffer with different :cpp:member:
- :c:macro:`I2S_PDM_RX_CLK_DEFAULT_CONFIG`
Please refer to :ref:`i2s-api-reference-i2s_pdm` for information about PDM RX API. And for more details, please refer to :component_file:`driver/i2s/include/driver/i2s_pdm.h`.
Please refer to :ref:`i2s-api-reference-i2s_pdm` for information about PDM RX API. And for more details, please refer to :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h`.
The PDM data width is fixed to 16-bit. When the data on the line (The PDM format on the line is transferred to PCM format for easier comprehension) is:
@ -733,7 +733,7 @@ Here is the table of the data received in the buffer with different :cpp:member:
- :c:macro:`I2S_TDM_CLK_DEFAULT_CONFIG`
Please refer to :ref:`i2s-api-reference-i2s_tdm` for information about TDM API. And for more details, please refer to :component_file:`driver/i2s/include/driver/i2s_tdm.h`.
Please refer to :ref:`i2s-api-reference-i2s_tdm` for information about TDM API. And for more details, please refer to :component_file:`esp_driver_i2s/include/driver/i2s_tdm.h`.
.. note::
@ -1070,5 +1070,5 @@ I2S Driver
I2S Types
^^^^^^^^^
.. include-build-file:: inc/components/driver/i2s/include/driver/i2s_types.inc
.. include-build-file:: inc/components/esp_driver_i2s/include/driver/i2s_types.inc
.. include-build-file:: inc/components/hal/include/hal/i2s_types.inc

View File

@ -459,7 +459,7 @@ LCD
I2S Driver
----------
The I2S driver has been redesigned (see :doc:`I2S Driver <../../../api-reference/peripherals/i2s>`), which aims to rectify the shortcomings of the driver that were exposed when supporting all the new features of ESP32-C3 & ESP32-S3. The new driver's APIs are available by including corresponding I2S mode's header files :component_file:`driver/i2s/include/driver/i2s_std.h`, :component_file:`driver/i2s/include/driver/i2s_pdm.h`, or :component_file:`driver/i2s/include/driver/i2s_tdm.h`.
The I2S driver has been redesigned (see :doc:`I2S Driver <../../../api-reference/peripherals/i2s>`), which aims to rectify the shortcomings of the driver that were exposed when supporting all the new features of ESP32-C3 & ESP32-S3. The new driver's APIs are available by including corresponding I2S mode's header files :component_file:`esp_driver_i2s/include/driver/i2s_std.h`, :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h`, or :component_file:`esp_driver_i2s/include/driver/i2s_tdm.h`.
Meanwhile, the old driver's APIs in :component_file:`driver/deprecated/driver/i2s.h` are still supported for backward compatibility. But there will be warnings if users keep using the old APIs in their projects, these warnings can be suppressed by the Kconfig option :ref:`CONFIG_I2S_SUPPRESS_DEPRECATE_WARN`.
@ -489,9 +489,9 @@ LCD
I2S communication modes are categorized into the following three modes. Note that:
- **Standard mode**: Standard mode always has two slots, it can support Philips, MSB, and PCM (short frame sync) formats. Please refer to :component_file:`driver/i2s/include/driver/i2s_std.h` for more details.
- **PDM mode**: PDM mode only supports two slots with 16-bit data width, but the configurations of PDM TX and PDM RX are slightly different. For PDM TX, the sample rate can be set by :cpp:member:`i2s_pdm_tx_clk_config_t::sample_rate`, and its clock frequency depends on the up-sampling configuration. For PDM RX, the sample rate can be set by :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate`, and its clock frequency depends on the down-sampling configuration. Please refer to :component_file:`driver/i2s/include/driver/i2s_pdm.h` for details.
- **TDM mode**: TDM mode can support up to 16 slots. It can work in Philips, MSB, PCM (short frame sync), and PCM (long frame sync) formats. Please refer to :component_file:`driver/i2s/include/driver/i2s_tdm.h` for details.
- **Standard mode**: Standard mode always has two slots, it can support Philips, MSB, and PCM (short frame sync) formats. Please refer to :component_file:`esp_driver_i2s/include/driver/i2s_std.h` for more details.
- **PDM mode**: PDM mode only supports two slots with 16-bit data width, but the configurations of PDM TX and PDM RX are slightly different. For PDM TX, the sample rate can be set by :cpp:member:`i2s_pdm_tx_clk_config_t::sample_rate`, and its clock frequency depends on the up-sampling configuration. For PDM RX, the sample rate can be set by :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate`, and its clock frequency depends on the down-sampling configuration. Please refer to :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h` for details.
- **TDM mode**: TDM mode can support up to 16 slots. It can work in Philips, MSB, PCM (short frame sync), and PCM (long frame sync) formats. Please refer to :component_file:`esp_driver_i2s/include/driver/i2s_tdm.h` for details.
When allocating a new channel in a specific mode, users should initialize that channel by its corresponding function. It is strongly recommended to use the helper macros to generate the default configurations in case the default values are changed in the future.

View File

@ -12,6 +12,7 @@ In order to control the dependence of other components on drivers at a smaller g
- `esp_driver_mcpwm` - Driver for Motor Control PWM
- `esp_driver_sdmmc` - Driver for SDMMC
- `esp_driver_ana_cmpr` - Driver for Analog Comparator
- `esp_driver_i2s` - Driver for I2S
For compatibility, the original `driver`` component is still treated as an all-in-one component by registering these `esp_driver_xyz`` components as its public dependencies. In other words, you do not need to modify the CMake file of an existing project, but you now have a way to specify the specific peripheral driver that your project depends on.

View File

@ -297,7 +297,7 @@ I2S 驱动例程请参考 :example:`peripherals/i2s` 目录。以下为每种模
- :c:macro:`I2S_STD_CLK_DEFAULT_CONFIG`
请参考 :ref:`i2s-api-reference-i2s_std` 了解 STD API 的相关信息。更多细节请参考 :component_file:`driver/i2s/include/driver/i2s_std.h`
请参考 :ref:`i2s-api-reference-i2s_std` 了解 STD API 的相关信息。更多细节请参考 :component_file:`esp_driver_i2s/include/driver/i2s_std.h`
STD TX 模式
~~~~~~~~~~~~~
@ -551,7 +551,7 @@ STD RX 模式
- :c:macro:`I2S_PDM_TX_CLK_DEFAULT_CONFIG`
PDM TX API 的相关信息,可参考 :ref:`i2s-api-reference-i2s_pdm`。更多细节请参阅 :component_file:`driver/i2s/include/driver/i2s_pdm.h`
PDM TX API 的相关信息,可参考 :ref:`i2s-api-reference-i2s_pdm`。更多细节请参阅 :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h`
PDM 数据位宽固定为 16 位。如果 ``int16_t`` 写缓冲区中的数据如下:
@ -647,7 +647,7 @@ STD RX 模式
- :c:macro:`I2S_PDM_RX_CLK_DEFAULT_CONFIG`
PDM RX API 的相关信息,可参考 :ref:`i2s-api-reference-i2s_pdm`。更多细节请参阅 :component_file:`driver/i2s/include/driver/i2s_pdm.h`
PDM RX API 的相关信息,可参考 :ref:`i2s-api-reference-i2s_pdm`。更多细节请参阅 :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h`
PDM 数据位宽固定为 16 位。如果线路上的数据如下所示。为方便理解,已将线路上的数据格式由 PDM 转为 PCM。
@ -733,7 +733,7 @@ STD RX 模式
- :c:macro:`I2S_TDM_CLK_DEFAULT_CONFIG`
有关 TDM API 的信息,请参阅 :ref:`i2s-api-reference-i2s_tdm`。更多细节请参阅 :component_file:`driver/i2s/include/driver/i2s_tdm.h`
有关 TDM API 的信息,请参阅 :ref:`i2s-api-reference-i2s_tdm`。更多细节请参阅 :component_file:`esp_driver_i2s/include/driver/i2s_tdm.h`
.. note::
@ -1070,5 +1070,5 @@ I2S 驱动
I2S 类型
^^^^^^^^
.. include-build-file:: inc/components/driver/i2s/include/driver/i2s_types.inc
.. include-build-file:: inc/components/esp_driver_i2s/include/driver/i2s_types.inc
.. include-build-file:: inc/components/hal/include/hal/i2s_types.inc

View File

@ -459,7 +459,7 @@ LCD
I2S 驱动
-----------------------
旧版 I2S 驱动在支持 ESP32-C3 和 ESP32-S3 新功能时暴露了很多缺点为解决这些缺点I2S 驱动已更新(请参考:doc:`I2S Driver <../../../api-reference/peripherals/i2s>`)。用户可以通过引用不同 I2S 模式对应的头文件来使用新版驱动的 API如 :component_file:`driver/i2s/include/driver/i2s_std.h` :component_file:`driver/i2s/include/driver/i2s_pdm.h` 以及 :component_file:`driver/i2s/include/driver/i2s_tdm.h`
旧版 I2S 驱动在支持 ESP32-C3 和 ESP32-S3 新功能时暴露了很多缺点为解决这些缺点I2S 驱动已更新(请参考:doc:`I2S Driver <../../../api-reference/peripherals/i2s>`)。用户可以通过引用不同 I2S 模式对应的头文件来使用新版驱动的 API如 :component_file:`esp_driver_i2s/include/driver/i2s_std.h` :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h` 以及 :component_file:`esp_driver_i2s/include/driver/i2s_tdm.h`
为保证前向兼容,旧版驱动的 API 仍然在 :component_file:`driver/deprecated/driver/i2s.h` 中可用。但使用旧版 API 会触发编译警告,该警告可通过配置 Kconfig 选项 :ref:`CONFIG_I2S_SUPPRESS_DEPRECATE_WARN` 来关闭。
@ -489,9 +489,9 @@ LCD
I2S 通信模式包括以下三种模式,请注意:
- **标准模式**:标准模式通常包括两个声道,支持 PhilipsMSB 和 PCM短帧同步格式详见 :component_file:`driver/i2s/include/driver/i2s_std.h`
- **PDM模式**PDM 模式仅支持两个声道16 bit 数据位宽,但是 PDM TX 和 PDM RX 的配置略有不同。对于 PDM TX采样率可通过 :cpp:member:`i2s_pdm_tx_clk_config_t::sample_rate` 进行设置,其时钟频率取决于上采样的配置。对于 PDM RX采样率可通过 :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate` 进行设置,其时钟频率取决于下采样的配置,详见 :component_file:`driver/i2s/include/driver/i2s_pdm.h`
- **TDM 模式**TDM 模式可支持高达 16 声道,该模式可工作在 PhilipsMSBPCM短帧同步和PCM长帧同步格式下详见 :component_file:`driver/i2s/include/driver/i2s_tdm.h`
- **标准模式**:标准模式通常包括两个声道,支持 PhilipsMSB 和 PCM短帧同步格式详见 :component_file:`esp_driver_i2s/include/driver/i2s_std.h`
- **PDM模式**PDM 模式仅支持两个声道16 bit 数据位宽,但是 PDM TX 和 PDM RX 的配置略有不同。对于 PDM TX采样率可通过 :cpp:member:`i2s_pdm_tx_clk_config_t::sample_rate` 进行设置,其时钟频率取决于上采样的配置。对于 PDM RX采样率可通过 :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate` 进行设置,其时钟频率取决于下采样的配置,详见 :component_file:`esp_driver_i2s/include/driver/i2s_pdm.h`
- **TDM 模式**TDM 模式可支持高达 16 声道,该模式可工作在 PhilipsMSBPCM短帧同步和PCM长帧同步格式下详见 :component_file:`esp_driver_i2s/include/driver/i2s_tdm.h`
在某个模式下分配新通道时,必须通过相应的函数初始化这个通道。我们强烈建议使用辅助宏来生成默认配置,以避免默认值被改动。

View File

@ -12,6 +12,7 @@
- `esp_driver_mcpwm` - 电机控制 PWM 驱动
- `esp_driver_sdmmc` - SDMMC 驱动
- `esp_driver_ana_cmpr` - 模拟比较器驱动
- `esp_driver_i2s` - I2S 驱动
为了兼容性,原来的 `driver` 组件仍然存在,并作为一个 “all-in-one" 的组件,将以上这些 `esp_driver_xyz` 组件注册成自己的公共依赖。换句话说,你无需修改既有项目的 CMake 文件,但是你现在多了一个途径去指定你项目依赖的具体的外设驱动。

View File

@ -42,9 +42,9 @@ examples/bluetooth/bluedroid/classic_bt:
- esp_console
- vfs
- esp_driver_gpio
- esp_driver_i2s
depends_filepatterns:
- components/driver/dac/**/*
- components/driver/i2s/**/*
- components/driver/uart/**/*
examples/bluetooth/bluedroid/coex/a2dp_gatts_coex:
@ -53,9 +53,10 @@ examples/bluetooth/bluedroid/coex/a2dp_gatts_coex:
- if: IDF_TARGET != "esp32"
temporary: true
reason: the other targets are not tested yet
depends_components:
- esp_driver_i2s
depends_filepatterns:
- components/driver/dac/**/*
- components/driver/i2s/**/*
examples/bluetooth/blufi:
disable:

View File

@ -1,4 +1,6 @@
idf_component_register(SRCS "bt_app_av.c"
"bt_app_core.c"
"main.c"
PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf
driver # TODO: IDF-8370 remove driver when esp_driver_dac created
INCLUDE_DIRS ".")

View File

@ -1,4 +1,6 @@
idf_component_register(SRCS "bt_app_av.c"
"bt_app_core.c"
"main.c"
PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf
driver # TODO: IDF-8370 remove driver when esp_driver_dac created
INCLUDE_DIRS ".")

View File

@ -66,6 +66,8 @@ examples/peripherals/i2s/i2s_basic/i2s_pdm:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
examples/peripherals/i2s/i2s_basic/i2s_std:
disable:
@ -74,6 +76,8 @@ examples/peripherals/i2s/i2s_basic/i2s_std:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
examples/peripherals/i2s/i2s_basic/i2s_tdm:
disable:
@ -82,6 +86,8 @@ examples/peripherals/i2s/i2s_basic/i2s_tdm:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm:
disable:
@ -91,6 +97,11 @@ examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
- esp_driver_spi
depends_filepatterns:
- components/driver/i2c/**/*
examples/peripherals/i2s/i2s_codec/i2s_es8311:
disable:
@ -100,12 +111,19 @@ examples/peripherals/i2s/i2s_codec/i2s_es8311:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
depends_components:
- esp_driver_i2s
depends_filepatterns:
- components/driver/i2c/**/*
examples/peripherals/i2s/i2s_recorder:
disable:
- if: SOC_SDMMC_HOST_SUPPORTED != 1 or IDF_TARGET == "esp32p4"
enable:
- if: SOC_I2S_SUPPORTS_PDM_RX > 0
depends_components:
- esp_driver_spi
- esp_driver_i2s
examples/peripherals/lcd/i2c_oled:
disable:
@ -120,8 +138,7 @@ examples/peripherals/lcd/i80_controller:
- if: SOC_LCD_I80_SUPPORTED != 1
depends_components:
- esp_lcd
depends_filepatterns:
- components/driver/i2s/**/* # i80 IO driver relies on I2S on esp32 and esp32s2
- esp_driver_i2s
examples/peripherals/lcd/rgb_panel:
disable:

View File

@ -3,4 +3,6 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(i2s_pdm_example)

View File

@ -9,4 +9,5 @@ if(CONFIG_SOC_I2S_SUPPORTS_PDM_RX AND CONFIG_EXAMPLE_PDM_RX)
endif()
idf_component_register(SRCS "${srcs}"
PRIV_REQUIRES esp_driver_i2s esp_driver_gpio
INCLUDE_DIRS ".")

View File

@ -3,4 +3,6 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(i2s_std_example)

View File

@ -1,2 +1,3 @@
idf_component_register(SRCS "i2s_std_example_main.c"
PRIV_REQUIRES esp_driver_i2s esp_driver_gpio
INCLUDE_DIRS ".")

View File

@ -3,4 +3,6 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(i2s_tdm_example)

View File

@ -1,2 +1,3 @@
idf_component_register(SRCS "i2s_tdm_example_main.c"
PRIV_REQUIRES esp_driver_i2s esp_driver_gpio
INCLUDE_DIRS ".")

View File

@ -3,4 +3,6 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(es7210_tdm_record_example)

View File

@ -1,3 +1,4 @@
idf_component_register(SRCS "i2s_es7210_record_example.c"
PRIV_REQUIRES esp_driver_i2s esp_driver_gpio fatfs
INCLUDE_DIRS "$ENV{IDF_PATH}/examples/peripherals/i2s/common"
)

View File

@ -3,4 +3,6 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(i2s-es8311-example)

View File

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

View File

@ -3,4 +3,6 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(esp32_i2s_driver_example)

View File

@ -1,2 +1,3 @@
idf_component_register(SRCS "i2s_recorder_main.c"
PRIV_REQUIRES esp_driver_i2s fatfs
INCLUDE_DIRS "$ENV{IDF_PATH}/examples/peripherals/i2s/common")