# Inter-IC Sound (I2S)

[中文]

## Introduction

I2S (Inter-IC Sound) is a synchronous serial communication protocol usually used for transmitting audio data between two digital audio devices.

ESP32 contains two I2S peripheral(s). These peripherals can be configured to input and output sample data via the I2S driver.

An I2S bus that communicates in standard mode consists of the following lines:

- MCLK: Master clock line. It is an optional signal depending on the slave side, mainly used for offering a reference clock to the I2S slave device.

- BCLK: Bit clock line. The bit clock for data line.

- WS: Word (Slot) select line. It is usually used to identify the vocal tract except PDM mode.

- DIN/DOUT: Serial data input/output line. Data will loopback internally if DIN and DOUT are set to a same GPIO.

An I2S bus that communicates in PDM mode consists of the following lines:

- CLK: PDM clock line.

- DIN/DOUT: Serial data input/output line.

Each I2S controller has the following features that can be configured by the I2S driver:

- Operation as system master or slave

- Capable of acting as transmitter or receiver

- DMA controller that allows stream sampling of data without requiring the CPU to copy each data sample

Each controller supports single RX or TX simplex communication. As RX and TX channels share a clock, they can only be combined with the same configuration to establish a full-duplex communication.

## I2S Clock

### Clock Source

- `i2s_clock_src_t::I2S_CLK_SRC_DEFAULT`: Default clock source. The actual source clock depends on the chip. See chip's Technical Reference Manual for details.

- `i2s_clock_src_t::I2S_CLK_SRC_APLL`: Audio PLL clock. Its frequency is configurable according to the sample rate, which makes it more precise in high sample rate applications. However, if APLL has been occupied by EMAC or other channels, the APLL frequency cannot be changed, and the driver will try to work under this APLL frequency. If this frequency cannot meet the requirements of I2S, the clock configuration will fail.

### Clock Terminology

- Sample rate: The number of sampled data in one second per slot.

- SCLK: Source clock frequency. It is the frequency of the clock source.

- MCLK: Master clock frequency. BCLK is generated from this clock. The MCLK signal usually serves as a reference clock and is mostly needed to synchronize BCLK and WS between I2S master and slave roles.

- BCLK: Bit clock frequency. Every tick of this clock stands for one data bit on data pin. The slot bit width configured in `i2s_std_slot_config_t::slot_bit_width` is equal to the number of BCLK ticks, which means there will be 8/16/24/32 BCLK ticks in one slot.

- LRCK / WS: Left/right clock or word select clock. For non-PDM mode, its frequency is equal to the sample rate.

Note

Normally, MCLK should be the multiple of `sample rate` and BCLK at the same time. The field `i2s_std_clk_config_t::mclk_multiple` indicates the multiple of MCLK to the `sample rate`. In most cases, `I2S_MCLK_MULTIPLE_256` should be enough. However, if `slot_bit_width` is set to `I2S_SLOT_BIT_WIDTH_24BIT`, to keep MCLK a multiple to the BCLK, `i2s_std_clk_config_t::mclk_multiple` should be set to multiples that are divisible by 3 such as `I2S_MCLK_MULTIPLE_384`. Otherwise, WS will be inaccurate.

Note

On ESP32, the MCLK pin must use GPIO0, GPIO1, or GPIO3. The other clock pins (e.g., BCLK, WS) can use any valid GPIO. Note that GPIO0 is generally not recommended for other functions because it is a strapping pin.

## I2S Communication Mode

### Overview of All Modes

Target | Standard | PCM-to-PDM | PDM-to-PCM | PDM | TDM | ADC/DAC | LCD/Camera
--- | --- | --- | --- | --- | --- | --- | ---
ESP32 | I2S 0/1 | I2S 0 | I2S 0 | I2S 0/1 | none | I2S 0 | I2S 0
ESP32-S2 | I2S 0 | none | none | none | none | none | I2S 0
ESP32-S3 | I2S 0/1 | I2S 0 | I2S 0 | I2S 0/1 | I2S 0/1 | none | none
ESP32-P4 | I2S 0~2 | I2S 0 | I2S 0 | I2S 0~2 | I2S 0~2 | none | none
others | I2S 0 | I2S 0 | none | I2S 0 | I2S 0 | none | none

Note

If you are using PDM mode, note that not all I2S ports support conversion between raw PDM and PCM formats, because these ports do not have PCM-to-PDM data format converter in TX direction, or PDM-to-PCM data format converter in RX direction. Ports without the converter can only read/write raw PDM data. To read/write PCM format data on these ports, you may need an extra software filter for PDM-to-PCM conversion.

### Standard Mode

In standard mode, there are always two sound channels, i.e., the left and right channels, which are called "slots". These slots support 8/16/24/32-bit width sample data. The communication format for the slots mainly includes the following:

- Philips Format: Data signal has one-bit shift comparing to the WS signal, and the duty of WS signal is 50%.

- MSB Format: Basically the same as Philips format, but without data shift.

- PCM Short Format: Data has one-bit shift and meanwhile the WS signal becomes a pulse lasting for one BCLK cycle.

### PDM Mode

PDM (Pulse-density Modulation) digitalizes the analog signal by oversampling with 1-bit resolution. It represents the analog signal by the pulse density, the higher the pulse density, the larger the corresponding analog quantity. The PDM timing diagram is shown as follow:

The PDM format data can be transferred into PCM format by the following steps:

1. Low-pass filtering: To restore the analog wave. It is usually a FIR filter;

2. Down-sampling: To reduce the PDM sample rate to the expected PCM sample rate. Normally we decimate one sample every specific number of samples;

3. High-pass filtering: To remove the DC offset of the analog wave;

4. Amplifying: To adjust the final gain of the converted PCM format data. It can be done by simply amplifying a coefficient.

For I2S ports with a `PCM-to-PDM` converter, the hardware can convert PCM format data to PDM format when sending the data. For I2S ports with a `PDM-to-PCM` converter, the hardware can convert PDM format data to PCM format when receiving the data. If the hardware does not have the converters above, then the PDM mode can only read/write raw PDM format data. You need to realize a software filter to convert the raw PDM data into PCM format.

Note

In PDM mode, regardless of whether you are using raw PDM or PCM format, the data unit width is always 16 bits. For example, if you are sending data in raw PDM format, the data in the buffer is supposed to be arranged as follows: CH0 0x1234, CH1 0x5678, CH0 0x9abc, CH1 0xdef0. Same in the RX direction.

#### PDM TX Mode in Raw PDM Format

To use the PDM TX mode in raw PDM format, set `i2s_pdm_tx_slot_config_t::data_fmt` to `i2s_pdm_data_fmt_t::I2S_PDM_DATA_FMT_RAW`. Be cautious when setting `i2s_pdm_tx_clk_config_t::sample_rate_hz`, as the PDM sample rate is normally in the MHz range, typically between 1.024 MHz and 6.144 MHz. Adjust it according to your needs.

As for the slot configuration of raw PDM format, you can use the helper macros like `I2S_PDM_TX_SLOT_RAW_FMT_DEFAULT_CONFIG` or `I2S_PDM_TX_SLOT_RAW_FMT_DAC_DEFAULT_CONFIG`.

#### PDM TX Mode in PCM Format (with PCM-to-PDM Converter)

ESP32 supports PCM-to-PDM converter on `I2S0`. To send PCM format data in the PDM TX mode, you need to set `i2s_pdm_tx_slot_config_t::data_fmt` to `i2s_pdm_data_fmt_t::I2S_PDM_DATA_FMT_PCM`. And then please take care when setting the `i2s_pdm_tx_clk_config_t::sample_rate_hz`, the PCM sample rate is normally below 100KHz, typically, it ranges from 16KHz to 48KHz, you can set it according to your needs.

And the up-sampling parameters can be set for the PCM-to-PDM converter, i.e., `i2s_pdm_tx_clk_config_t::up_sample_fp` and `i2s_pdm_tx_clk_config_t::up_sample_fs`. The up-sampling rate can be calculated by `up_sample_rate = i2s_pdm_tx_clk_config_t::up_sample_fp / i2s_pdm_tx_clk_config_t::up_sample_fs`. There are two up-sampling modes for PCM-to-PDM converter. The relation of the PDM clock on CLK pin and the PCM sample rate that set in the driver are shown as follow:

- Fixed Clock Frequency: In this mode, the up-sampling rate changes according to the sample rate. Setting `fp = 960` and `fs = (PCM)sample_rate / 100`, then the PDM clock frequency on the CLK pin will be fixed to `128 * 48 KHz = 6.144 MHz`.

- Fixed Up-sampling Rate: In this mode, the up-sampling rate is fixed to 2. Setting `fp = 960` and `fs = 480`, then the PDM clock frequency on CLK pin will be `128 * (PCM)sample_rate`.

As for the slot configuration of PCM format, you can use the helper macros like `I2S_PDM_TX_SLOT_PCM_FMT_DEFAULT_CONFIG` or `I2S_PDM_TX_SLOT_PCM_FMT_DAC_DEFAULT_CONFIG`.

#### PDM RX Mode in Raw PDM Format

To use the PDM RX mode in raw PDM format, you need to set `i2s_pdm_rx_slot_config_t::data_fmt` to `i2s_pdm_data_fmt_t::I2S_PDM_DATA_FMT_RAW`. And then please take care when setting the `i2s_pdm_rx_clk_config_t::sample_rate_hz`, the PDM sample rate is normally several MHz, typically, it ranges from 1.024MHz to 6.144MHz, you can set it according to your needs.

As for the slot configuration of raw PDM format, you can use the helper macro `I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG`.

#### PDM RX Mode in PCM Format (with PDM-to-PCM Converter)

ESP32 supports PDM-to-PCM converter on `I2S0`. To receive PCM format data in the PDM RX mode, you need to set `i2s_pdm_rx_slot_config_t::data_fmt` to `i2s_pdm_data_fmt_t::I2S_PDM_DATA_FMT_PCM`. And then please take care when setting the `i2s_pdm_rx_clk_config_t::sample_rate_hz`, the PCM sample rate is normally below 100KHz, typically, it ranges from 16KHz to 48KHz, you can set it according to your needs.

The down-sampling parameter can be set to the PDM-to-PCM converter, which is `i2s_pdm_rx_clk_config_t::dn_sample_mode`. There are two down-sampling modes for PDM-to-PCM converter, the relation of the PDM clock on CLK pin and the PCM sample rate that set in the driver are shown as follow:

- `i2s_pdm_dsr_t::I2S_PDM_DSR_8S`: In this mode, the PDM clock frequency on the CLK pin is `(PCM) sample_rate * 64`.

- `i2s_pdm_dsr_t::I2S_PDM_DSR_16S`: In this mode, the PDM clock frequency on the CLK pin is `(PCM) sample_rate * 128`.

As for the slot configuration of PCM format, you can use the helper macro like `I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG`

### LCD/Camera Mode

LCD/Camera mode is only supported on I2S0 over a parallel bus. For LCD mode, I2S0 should work at master TX mode. For camera mode, I2S0 should work at slave RX mode. These two modes are not implemented by the I2S driver. Please refer to I80 Interfaced LCD for details about the LCD implementation. For more information, see ESP32 Technical Reference Manual > I2S Controller (I2S) > LCD Mode [PDF].

### ADC/DAC Mode

ADC and DAC modes only exist on ESP32 and are only supported on I2S0. Actually, they are two sub-modes of LCD/Camera mode. I2S0 can be routed directly to the internal analog-to-digital converter (ADC) and digital-to-analog converter (DAC). In other words, ADC and DAC peripherals can read or write continuously via I2S0 DMA. As they are not actual communication modes, the I2S driver does not implement them.

## Functional Overview

The I2S driver offers the following services:

### Resource Management

There are three levels of resources in the I2S driver:

- `platform level`: Resources of all I2S controllers in the current target.

- `controller level`: Resources in one I2S controller.

- `channel level`: Resources of TX or RX channel in one I2S controller.

The public APIs are all channel-level APIs. The channel handle `i2s_chan_handle_t` can help users to manage the resources under a specific channel without considering the other two levels. The other two upper levels' resources are private and are managed by the driver automatically. Users can call `i2s_new_channel()` to allocate a channel handle and call `i2s_del_channel()` to delete it.

### Power Management

When the power management is enabled (i.e., CONFIG_PM_ENABLE is on), the system will adjust or stop the source clock of I2S before entering Light-sleep, thus potentially changing the I2S signals and leading to transmitting or receiving invalid data.

The I2S driver can prevent the system from changing or stopping the source clock by acquiring a power management lock. When the source clock is generated from APB, the lock type will be set to `esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX` and when the source clock is APLL (if supported), it will be set to `esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`. The driver guarantees that the power management lock is acquired when the channel is enabled by `i2s_channel_enable()`. Likewise, the driver releases the lock when the channel is disabled by `i2s_channel_disable()`, which keeps the I2S source clock stable while the channel is running.

### Finite State Machine

There are three states for an I2S channel, namely, `registered`, `ready`, and `running`. Their relationship is shown in the following diagram:

I2S Finite State Machine

The `<mode>` in the diagram can be replaced by corresponding I2S communication modes, e.g., `std` for standard two-slot mode. For more information about communication modes, please refer to the I2S Communication Mode section.

### Data Transport

The data transport of the I2S peripheral, including sending and receiving, is realized by DMA. Before transporting data, please call `i2s_channel_enable()` to enable the specific channel. When the sent or received data reaches the size of one DMA buffer, the `I2S_OUT_EOF` or `I2S_IN_SUC_EOF` interrupt will be triggered. Note that the DMA buffer size is not equal to `i2s_chan_config_t::dma_frame_num`. One frame here refers to all the sampled data in one WS circle. Therefore, `dma_buffer_size = dma_frame_num * slot_num * slot_bit_width / 8`. For the data transmitting, users can input the data by calling `i2s_channel_write()`. This function helps users to copy the data from the source buffer to the DMA TX buffer and wait for the transmission to finish. Then it will repeat until the sent bytes reach the given size. For the data receiving, the function `i2s_channel_read()` waits to receive the message queue which contains the DMA buffer address. It helps users copy the data from the DMA RX buffer to the destination buffer.

Both `i2s_channel_write()` and `i2s_channel_read()` are blocking functions. They keeps waiting until the whole source buffer is sent or the whole destination buffer is loaded, unless they exceed the max blocking time, where the error code `ESP_ERR_TIMEOUT` returns. To send or receive data asynchronously, callbacks can be registered by `i2s_channel_register_event_callback()`. Users are able to access the DMA buffer directly in the callback function instead of transmitting or receiving by the two blocking functions. However, please be aware that it is an interrupt callback, so do not add complex logic, run floating operation, or call non-reentrant functions in the callback.

### Configuration

Users can initialize a channel by calling corresponding functions (i.e., `i2s_channel_init_std_mode()`, `i2s_channel_init_pdm_rx_mode()`, `i2s_channel_init_pdm_tx_mode()`, or `i2s_channel_init_tdm_mode()`) to a specific mode. If the configurations need to be updated after initialization, users have to first call `i2s_channel_disable()` to ensure that the channel has stopped, and then call corresponding `reconfig` functions, like `i2s_channel_reconfig_std_slot()`, `i2s_channel_reconfig_std_clock()`, and `i2s_channel_reconfig_std_gpio()`.

### Advanced API

To satisfy the high quality audio requirement, following advanced APIs are provided:

- `i2s_channel_preload_data()`: Preloading audio data into the I2S internal cache, enabling the TX channel to immediately send data upon activation, thereby reducing the initial audio output delay.

- `i2s_channel_tune_rate()`: Dynamically fine-tuning the audio rate at runtime to match the speed of the audio data producer and consumer, thereby preventing the accumulation or shortage of intermediate buffered data that caused by rate mismatches.

### IRAM Safe

By default, the I2S interrupt will be deferred when the cache is disabled for reasons like writing/erasing flash. Thus the EOF interrupt will not get executed in time.

To avoid such case in real-time applications, you can enable the Kconfig option CONFIG_I2S_ISR_IRAM_SAFE that:

1. Keeps the interrupt being serviced even when the cache is disabled.

2. Places driver object into DRAM (in case it is linked to PSRAM by accident).

This allows the interrupt to run while the cache is disabled, but comes at the cost of increased IRAM consumption.

### Thread Safety

All the public I2S APIs are guaranteed to be thread safe by the driver, which means users can call them from different RTOS tasks without protection by extra locks. Notice that the I2S driver uses mutex lock to ensure the thread safety, thus these APIs are not allowed to be used in ISR.

### Kconfig Options

- CONFIG_I2S_ISR_IRAM_SAFE controls whether the default ISR handler can work when the cache is disabled. See IRAM Safe for more information.

- CONFIG_I2S_ENABLE_DEBUG_LOG is used to enable the debug log output. Enable this option increases the firmware binary size.

## Application Example

The examples of the I2S driver can be found in the directory peripherals/i2s. Here are some simple usages of each mode:

### Standard TX/RX Usage

- peripherals/i2s/i2s_codec/i2s_es8311 demonstrates how to use the I2S ES8311 audio codec with ESP32 to play music or echo sounds, featuring high performance and low power multi-bit delta-sigma audio ADC and DAC, with options to customize music and adjust mic gain and volume.

- peripherals/i2s/i2s_basic/i2s_std demonstrates how to use the I2S standard mode in either simplex or full-duplex mode on ESP32.

- peripherals/i2s/mic_recorder demonstrates how to record audio from an analog microphone connected to an ES8389 codec through the I2S STD interface.

Different slot communication formats can be generated by the following helper macros for standard mode. As described above, there are three formats in standard mode, and their helper macros are:

- `I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG`

- `I2S_STD_PCM_SLOT_DEFAULT_CONFIG`

- `I2S_STD_MSB_SLOT_DEFAULT_CONFIG`

Note

The standard mode slot helper macros set `i2s_std_slot_config_t::ws_width` according to the `bits_per_sample` argument. If `i2s_std_slot_config_t::slot_bit_width` is manually changed after using a helper macro, update `i2s_std_slot_config_t::ws_width` as needed. For Philips and MSB formats, set `ws_width` to the slot bit width to keep the WS duty cycle at 50%. For PCM short format, `ws_width` should remain 1 BCLK.

The clock config helper macro is:

- `I2S_STD_CLK_DEFAULT_CONFIG`

Please refer to Standard Mode for information about STD API. And for more details, please refer to esp_driver_i2s/include/driver/i2s_std.h.

#### STD TX Mode

Take 16-bit data width for example. When the data in a `uint16_t` writing buffer are:

data 0 | data 1 | data 2 | data 3 | data 4 | data 5 | data 6 | data 7 | ...
--- | --- | --- | --- | --- | --- | --- | --- | ---
0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | ...

Here is the table of the real data on the line with different `i2s_std_slot_config_t::slot_mode` and `i2s_std_slot_config_t::slot_mask`.

data bit width | slot mode | slot mask | WS low | WS high | WS low | WS high | WS low | WS high | WS low | WS high
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
16 bit | mono | left | 0x0002 | 0x0000 | 0x0001 | 0x0000 | 0x0004 | 0x0000 | 0x0003 | 0x0000
right | 0x0000 | 0x0002 | 0x0000 | 0x0001 | 0x0000 | 0x0004 | 0x0000 | 0x0003
both | 0x0002 | 0x0002 | 0x0001 | 0x0001 | 0x0004 | 0x0004 | 0x0003 | 0x0003
stereo | left | 0x0001 | 0x0001 | 0x0003 | 0x0003 | 0x0005 | 0x0005 | 0x0007 | 0x0007
right | 0x0002 | 0x0002 | 0x0004 | 0x0004 | 0x0006 | 0x0006 | 0x0008 | 0x0008
both | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008

Note

It is similar when the data is 32-bit width, but take care when using 8-bit and 24-bit data width. For 8-bit width, the written buffer should still use `uint16_t` (i.e., align with 2 bytes), and only the high 8 bits are valid while the low 8 bits are dropped. For 24-bit width, the buffer is supposed to use `uint32_t` (i.e., align with 4 bytes), and only the high 24 bits are valid while the low 8 bits are dropped.

Besides, for 8-bit and 16-bit mono modes, the real data on the line is swapped. To get the correct data sequence, the writing buffer needs to swap the data every two bytes.

    #include "driver/i2s_std.h"
    #include "driver/gpio.h"

    i2s_chan_handle_t tx_handle;
    /* Get the default channel configuration by the helper macro.
     * This helper macro is defined in `i2s_common.h` and shared by all the I2S communication modes.
     * It can help to specify the I2S role and port ID */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
    /* Allocate a new TX channel and get the handle of this channel */
    i2s_new_channel(&chan_cfg, &tx_handle, NULL);

    /* Setting the configurations, the slot configuration and clock configuration can be generated by the macros
     * These two helper macros are defined in `i2s_std.h` which can only be used in STD mode.
     * They can help to specify the slot and clock configurations for initialization or updating */
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(48000),
        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = GPIO_NUM_4,
            .ws = GPIO_NUM_5,
            .dout = GPIO_NUM_18,
            .din = I2S_GPIO_UNUSED,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    /* Initialize the channel */
    i2s_channel_init_std_mode(tx_handle, &std_cfg);

    /* Before writing data, start the TX channel first */
    i2s_channel_enable(tx_handle);
    i2s_channel_write(tx_handle, src_buf, bytes_to_write, bytes_written, ticks_to_wait);

    /* If the configurations of slot or clock need to be updated,
     * stop the channel first and then update it */
    // i2s_channel_disable(tx_handle);
    // std_cfg.slot_cfg.slot_mode = I2S_SLOT_MODE_MONO; // Default is stereo
    // i2s_channel_reconfig_std_slot(tx_handle, &std_cfg.slot_cfg);
    // std_cfg.clk_cfg.sample_rate_hz = 96000;
    // i2s_channel_reconfig_std_clock(tx_handle, &std_cfg.clk_cfg);

    /* Have to stop the channel before deleting it */
    i2s_channel_disable(tx_handle);
    /* If the handle is not needed any more, delete it to release the channel resources */
    i2s_del_channel(tx_handle);

#### STD RX Mode

Taking 16-bit data width for example, when the data on the line are:

WS low | WS high | WS low | WS high | WS low | WS high | WS low | WS high | ...
--- | --- | --- | --- | --- | --- | --- | --- | ---
0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | ...

Here is the table of the data received in the buffer with different `i2s_std_slot_config_t::slot_mode` and `i2s_std_slot_config_t::slot_mask`.

data bit width | slot mode | slot mask | data 0 | data 1 | data 2 | data 3 | data 4 | data 5 | data 6 | data 7
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
16 bit | mono | left | 0x0001 | 0x0000 | 0x0005 | 0x0003 | 0x0009 | 0x0007 | 0x000d | 0x000b
right | 0x0002 | 0x0000 | 0x0006 | 0x0004 | 0x000a | 0x0008 | 0x000e | 0x000c
stereo | any | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008

Note

The receive case is a little bit complicated on ESP32. Firstly, when the data width is 8-bit or 24-bit, the received data will still align with two bytes or four bytes, which means that the valid data are put in the high 8 bits in every two bytes and high 24 bits in every four bytes. For example, the received data will be `0x5A00` when the data on the line is `0x5A` in 8-bit width, and `0x0000 5A00` if the data on the line is `0x00 005A`. Secondly, for the 8-bit or 16-bit mono case, the data in buffer is swapped every two data, so it may be necessary to manually swap the data back to the correct order.

    #include "driver/i2s_std.h"
    #include "driver/gpio.h"

    i2s_chan_handle_t rx_handle;
    /* Get the default channel configuration by helper macro.
     * This helper macro is defined in `i2s_common.h` and shared by all the I2S communication modes.
     * It can help to specify the I2S role and port ID */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
    /* Allocate a new RX channel and get the handle of this channel */
    i2s_new_channel(&chan_cfg, NULL, &rx_handle);

    /* Setting the configurations, the slot configuration and clock configuration can be generated by the macros
     * These two helper macros are defined in `i2s_std.h` which can only be used in STD mode.
     * They can help to specify the slot and clock configurations for initialization or updating */
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(48000),
        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = GPIO_NUM_4,
            .ws = GPIO_NUM_5,
            .dout = I2S_GPIO_UNUSED,
            .din = GPIO_NUM_19,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    /* Initialize the channel */
    i2s_channel_init_std_mode(rx_handle, &std_cfg);

    /* Before reading data, start the RX channel first */
    i2s_channel_enable(rx_handle);
    i2s_channel_read(rx_handle, desc_buf, bytes_to_read, bytes_read, ticks_to_wait);

    /* Have to stop the channel before deleting it */
    i2s_channel_disable(rx_handle);
    /* If the handle is not needed any more, delete it to release the channel resources */
    i2s_del_channel(rx_handle);

### PDM TX Usage

- peripherals/i2s/i2s_basic/i2s_pdm demonstrates how to use the PDM TX mode on ESP32, including the necessary hardware setup and configuration.

For PDM mode in TX channel, the slot configuration helper macro is:

- `I2S_PDM_TX_SLOT_DEFAULT_CONFIG`

The clock configuration helper macro is:

- `I2S_PDM_TX_CLK_DEFAULT_CONFIG`

Please refer to PDM Mode for information about PDM TX API. And for more details, please refer to 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:

data 0 | data 1 | data 2 | data 3 | data 4 | data 5 | data 6 | data 7 | ...
--- | --- | --- | --- | --- | --- | --- | --- | ---
0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | ...

Here is the table of the real data on the line with different `i2s_pdm_tx_slot_config_t::slot_mode` and `i2s_pdm_tx_slot_config_t::slot_mask` (The PDM format on the line is transferred to PCM format for better comprehension).

slot mode | slot mask | left | right | left | right | left | right | left | right
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
mono | left | 0x0001 | 0x0000 | 0x0002 | 0x0000 | 0x0003 | 0x0000 | 0x0004 | 0x0000
right | 0x0000 | 0x0001 | 0x0000 | 0x0002 | 0x0000 | 0x0003 | 0x0000 | 0x0004
both | 0x0001 | 0x0001 | 0x0002 | 0x0002 | 0x0003 | 0x0003 | 0x0004 | 0x0004
stereo | left | 0x0001 | 0x0001 | 0x0003 | 0x0003 | 0x0005 | 0x0005 | 0x0007 | 0x0007
right | 0x0002 | 0x0002 | 0x0004 | 0x0004 | 0x0006 | 0x0006 | 0x0008 | 0x0008
both | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008

    #include "driver/i2s_pdm.h"
    #include "driver/gpio.h"

    /* Allocate an I2S TX channel */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
    i2s_new_channel(&chan_cfg, &tx_handle, NULL);

    /* Init the channel into PDM TX mode */
    i2s_pdm_tx_config_t pdm_tx_cfg = {
        .clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG(36000),
        .slot_cfg = I2S_PDM_TX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
        .gpio_cfg = {
            .clk = GPIO_NUM_5,
            .dout = GPIO_NUM_18,
            .invert_flags = {
                .clk_inv = false,
            },
        },
    };
    i2s_channel_init_pdm_tx_mode(tx_handle, &pdm_tx_cfg);

    ...

### PDM RX Usage

- peripherals/i2s/mic_recorder demonstrates how to record audio from either PDM digital MEMS microphones (using the I2S PDM RX mode) or an analog microphone through an ES8389 codec, and streams the recorded PCM data over the console so that the `.wav` file can be reconstructed on the host PC.

- peripherals/i2s/i2s_basic/i2s_pdm demonstrates how to use the PDM RX mode on ESP32, including the necessary hardware setup and configuration.

For PDM mode in RX channel, the slot configuration helper macro are:

- `I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG` It provides some default configurations for receiving the raw PDM format data.

- `I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG` It provides some default configurations for receiving the converted PCM format data.

The clock configuration helper macro is:

- `I2S_PDM_RX_CLK_DEFAULT_CONFIG`

Please refer to PDM Mode for information about PDM RX API. And for more details, please refer to 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:

left | right | left | right | left | right | left | right | ...
--- | --- | --- | --- | --- | --- | --- | --- | ---
0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | ...

Here is the table of the data received in a `int16_t` buffer with different `i2s_pdm_rx_slot_config_t::slot_mode` and `i2s_pdm_rx_slot_config_t::slot_mask`.

slot mode | slot mask | data 0 | data 1 | data 2 | data 3 | data 4 | data 5 | data 6 | data 7
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
mono | left | 0x0001 | 0x0003 | 0x0005 | 0x0007 | 0x0009 | 0x000b | 0x000d | 0x000f
right | 0x0002 | 0x0004 | 0x0006 | 0x0008 | 0x000a | 0x000c | 0x000e | 0x0010
stereo | both | 0x0001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008

    #include "driver/i2s_pdm.h"
    #include "driver/gpio.h"

    i2s_chan_handle_t rx_handle;

    /* Allocate an I2S RX channel */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
    i2s_new_channel(&chan_cfg, NULL, &rx_handle);

    /* Init the channel into PDM RX mode */
    i2s_pdm_rx_config_t pdm_rx_cfg = {
        .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(36000),
        // If PDM-to-PCM converter is not supported, please use raw PDM format
        // .slot_cfg = I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
        .slot_cfg = I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
        .gpio_cfg = {
            .clk = GPIO_NUM_5,
            .din = GPIO_NUM_19,
            .invert_flags = {
                .clk_inv = false,
            },
        },
    };
    i2s_channel_init_pdm_rx_mode(rx_handle, &pdm_rx_cfg);

    ...

### Full-duplex

Full-duplex mode registers TX and RX channel in an I2S port at the same time, and the channels share the BCLK and WS signals. Currently, standard communication modes supports full-duplex mode in the following way, but PDM full-duplex is not supported because due to different PDM TX and RX clocks.

Note that one handle can only stand for one channel. Therefore, it is still necessary to configure the slot and clock for both TX and RX channels one by one.

Note

In full-duplex mode, only one channel can work as the master that generates BCLK and WS. If both paired handles are configured as `I2S_ROLE_MASTER`, the handle initialized later is automatically switched to `I2S_ROLE_SLAVE`.

There are two methods to allocate a pair of full-duplex channels:

1. Allocate both TX and RX handles in a single call of `i2s_new_channel()`.

    #include "driver/i2s_std.h"
    #include "driver/gpio.h"

    i2s_chan_handle_t tx_handle;
    i2s_chan_handle_t rx_handle;

    /* Allocate a pair of I2S channel */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
    /* Allocate for TX and RX channel at the same time, then they will work in full-duplex mode */
    i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle);

    /* Set the configurations for both channels. BCLK/WS and frame timing must match in full-duplex mode. */
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(32000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = GPIO_NUM_4,
            .ws = GPIO_NUM_5,
            .dout = GPIO_NUM_18,
            .din = GPIO_NUM_19,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    i2s_channel_init_std_mode(tx_handle, &std_cfg);
    i2s_channel_init_std_mode(rx_handle, &std_cfg);

    i2s_channel_enable(tx_handle);
    i2s_channel_enable(rx_handle);

    ...

2. Allocate TX and RX handles separately, and initialize them with compatible configurations.

    #include "driver/i2s_std.h"
    #include "driver/gpio.h"

    i2s_chan_handle_t tx_handle;
    i2s_chan_handle_t rx_handle;

    /* Allocate a pair of I2S channels on a same port */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
    /* Allocate for TX and RX channel separately, they are not full-duplex yet */
    ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL));

    /* Set compatible configurations for both channels, then they will constitute in full-duplex mode automatically */
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(32000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = GPIO_NUM_4,
            .ws = GPIO_NUM_5,
            .dout = GPIO_NUM_18,
            .din = GPIO_NUM_19,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
    ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));
    // ...
    ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &rx_handle));
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
    ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));

    ...

### Simplex Mode

To allocate a channel handle in simplex mode, `i2s_new_channel()` should be called for each channel. The clock and GPIO pins of TX/RX channel on ESP32 are not independent, so the TX and RX channel cannot coexist on the same I2S port in simplex mode.

    #include "driver/i2s_std.h"
    #include "driver/gpio.h"

    i2s_chan_handle_t tx_handle;
    i2s_chan_handle_t rx_handle;

    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
    ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL));
    i2s_std_config_t std_tx_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(48000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = GPIO_NUM_0,
            .bclk = GPIO_NUM_4,
            .ws = GPIO_NUM_5,
            .dout = GPIO_NUM_18,
            .din = I2S_GPIO_UNUSED,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    /* Initialize the channel */
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_tx_cfg));
    ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));

    /* RX channel will be registered on another I2S, if no other available I2S unit found
     * it will return ESP_ERR_NOT_FOUND */
    ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &rx_handle));
    i2s_std_config_t std_rx_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = GPIO_NUM_6,
            .ws = GPIO_NUM_7,
            .dout = I2S_GPIO_UNUSED,
            .din = GPIO_NUM_19,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_rx_cfg));
    ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));

## Application Notes

### How to Prevent Data Lost

For applications that need a high frequency sample rate, the massive data throughput may cause data lost. Users can receive data lost event by registering the ISR callback function to receive the event queue:

>     static IRAM_ATTR bool i2s_rx_queue_overflow_callback(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx)
>     {
>         // handle RX queue overflow event ...
>         return false;
>     }

>     i2s_event_callbacks_t cbs = {
>         .on_recv = NULL,
>         .on_recv_q_ovf = i2s_rx_queue_overflow_callback,
>         .on_sent = NULL,
>         .on_send_q_ovf = NULL,
>     };
>     TEST_ESP_OK(i2s_channel_register_event_callback(rx_handle, &cbs, NULL));

Please follow these steps to prevent data lost:

1. Determine the interrupt interval. Generally, when data lost happens, the bigger the interval, the better, which helps to reduce the interrupt times. This means `dma_frame_num` should be as big as possible while the DMA buffer size is below the maximum value of 4092. The relationships are:

       interrupt_interval(unit: sec) = dma_frame_num / sample_rate
       dma_buffer_size = dma_frame_num * slot_num * data_bit_width / 8 <= 4092

2. Determine `dma_desc_num`. `dma_desc_num` is decided by the maximum time of `i2s_channel_read` polling cycle. All the received data is supposed to be stored between two `i2s_channel_read`. This cycle can be measured by a timer or an outputting GPIO signal. The relationship is:

       dma_desc_num > polling_cycle / interrupt_interval

3. Determine the receiving buffer size. The receiving buffer offered by users in `i2s_channel_read` should be able to take all the data in all DMA buffers, which means that it should be larger than the total size of all the DMA buffers:

       recv_buffer_size > dma_desc_num * dma_buffer_size

For example, if there is an I2S application, and the known values are:

    sample_rate = 144000 Hz
    data_bit_width = 32 bits
    slot_num = 2
    polling_cycle = 10 ms

Then the parameters `dma_frame_num`, `dma_desc_num`, and `recv_buf_size` can be calculated as follows:

    dma_frame_num * slot_num * data_bit_width / 8 = dma_buffer_size <= 4092
    dma_frame_num <= 511
    interrupt_interval = dma_frame_num / sample_rate = 511 / 144000 = 0.003549 s = 3.549 ms
    dma_desc_num > polling_cycle / interrupt_interval = cell(10 / 3.549) = cell(2.818) = 3
    recv_buffer_size > dma_desc_num * dma_buffer_size = 3 * 4092 = 12276 bytes

## API Reference

### Standard Mode

### Header File

- components/esp_driver_i2s/include/driver/i2s_std.h

- This header file can be included with:

  >     #include "driver/i2s_std.h"

- This header file is a part of the API provided by the `esp_driver_i2s` component. To declare that your component depends on `esp_driver_i2s`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_i2s

  > or

  >     PRIV_REQUIRES esp_driver_i2s

### Functions

esp_err_t i2s_channel_init_std_mode(i2s_chan_handle_t handle, const i2s_std_config_t *std_cfg)

  Initialize I2S channel to standard mode.

  Note

  Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized) and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.

  Note

  When initializing the STD mode on a channel that shares the same BCLK/WS configuration and the same frame timing (sample rate and total bits per frame) as the other channel on the same port, these two channels can constitute full-duplex mode automatically. The slot layout, clock source, external clock frequency, and MCLK configuration may differ (e.g. an STD channel can pair with a TDM channel) as long as the total bits per frame are equal and the BCLK/WS frequency matches.

  Parameters:

    - handle -- [in] I2S channel handler

    - std_cfg -- [in] Configurations for standard mode, including clock, slot and GPIO The clock configuration can be generated by the helper macro `I2S_STD_CLK_DEFAULT_CONFIG` The slot configuration can be generated by the helper macro `I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG`, `I2S_STD_PCM_SLOT_DEFAULT_CONFIG` or `I2S_STD_MSB_SLOT_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Initialize successfully

    - ESP_ERR_NO_MEM No memory for storing the channel information

    - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration

    - ESP_ERR_INVALID_STATE This channel is not registered

esp_err_t i2s_channel_reconfig_std_clock(i2s_chan_handle_t handle, const i2s_std_clk_config_t *clk_cfg)

  Reconfigure the I2S clock for standard mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to standard mode, i.e., `i2s_channel_init_std_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S channel handler

    - clk_cfg -- [in] Standard mode clock configuration, can be generated by `I2S_STD_CLK_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not standard mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_reconfig_std_slot(i2s_chan_handle_t handle, const i2s_std_slot_config_t *slot_cfg)

  Reconfigure the I2S slot for standard mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to standard mode, i.e., `i2s_channel_init_std_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S channel handler

    - slot_cfg -- [in] Standard mode slot configuration, can be generated by `I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG`, `I2S_STD_PCM_SLOT_DEFAULT_CONFIG` and `I2S_STD_MSB_SLOT_DEFAULT_CONFIG`.

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_NO_MEM No memory for DMA buffer

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not standard mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_reconfig_std_gpio(i2s_chan_handle_t handle, const i2s_std_gpio_config_t *gpio_cfg)

  Reconfigure the I2S GPIO for standard mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to standard mode, i.e., `i2s_channel_init_std_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S channel handler

    - gpio_cfg -- [in] Standard mode GPIO configuration, specified by user

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not standard mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

### Structures

struct i2s_std_slot_config_t

  I2S slot configuration for standard mode.

  Public Members

  i2s_data_bit_width_t data_bit_width

    I2S sample data bit width (valid data bits per sample)

  i2s_slot_bit_width_t slot_bit_width

    I2S slot bit width (total bits per slot)

  i2s_slot_mode_t slot_mode

    Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO In TX direction, mono means the written buffer contains only one slot data and stereo means the written buffer contains both left and right data

  i2s_std_slot_mask_t slot_mask

    Select the left, right or both slot

  uint32_t ws_width

    WS signal width (i.e. the number of BCLK ticks that WS signal is high)

  bool ws_pol

    WS signal polarity, set true to enable high lever first

  bool bit_shift

    Set to enable bit shift in Philips mode

  bool msb_right

    Set to place right channel data at the MSB in the FIFO

struct i2s_std_clk_config_t

  I2S clock configuration for standard mode.

  Public Members

  uint32_t sample_rate_hz

    I2S sample rate

  i2s_clock_src_t clk_src

    Choose clock source, see `soc_periph_i2s_clk_src_t` for the supported clock sources. selected `I2S_CLK_SRC_EXTERNAL` (if supports) to enable the external source clock input via MCLK pin,

  i2s_mclk_multiple_t mclk_multiple

    The multiple of MCLK to the sample rate Default is 256 in the helper macro, it can satisfy most of cases, but please set this field a multiple of `3` (like 384) when using 24-bit data width, otherwise the sample rate might be inaccurate

  uint32_t bclk_div

    The division from MCLK to BCLK, only take effect for slave role, it shouldn't be smaller than 8. Increase this field when data sent by slave lag behind

struct i2s_std_gpio_config_t

  I2S standard mode GPIO pins configuration.

  Public Members

  gpio_num_t mclk

    MCK pin, output by default, input if the clock source is selected to `I2S_CLK_SRC_EXTERNAL`

  gpio_num_t bclk

    BCK pin, input in slave role, output in master role

  gpio_num_t ws

    WS pin, input in slave role, output in master role

  gpio_num_t dout

    DATA pin, output

  gpio_num_t din

    DATA pin, input

  uint32_t mclk_inv

    Set 1 to invert the MCLK input/output

  uint32_t bclk_inv

    Set 1 to invert the BCLK input/output

  uint32_t ws_inv

    Set 1 to invert the WS input/output

  struct i2s_std_gpio_config_t invert_flags

    GPIO pin invert flags

struct i2s_std_config_t

  I2S standard mode major configuration that including clock/slot/GPIO configuration.

  Public Members

  i2s_std_clk_config_t clk_cfg

    Standard mode clock configuration, can be generated by macro I2S_STD_CLK_DEFAULT_CONFIG

  i2s_std_slot_config_t slot_cfg

    Standard mode slot configuration, can be generated by macros I2S_STD_[mode]_SLOT_DEFAULT_CONFIG, [mode] can be replaced with PHILIPS/MSB/PCM

  i2s_std_gpio_config_t gpio_cfg

    Standard mode GPIO configuration, specified by user

### Macros

I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  Philips format in 2 slots.

  This file is specified for I2S standard communication mode Features:

  - Philips/MSB/PCM are supported in standard mode

  - Fixed to 2 slots

  Parameters:

    - bits_per_sample -- I2S data bit width

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_STD_PCM_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  PCM(short) format in 2 slots.

  Note

  PCM(long) is same as Philips in 2 slots

  Parameters:

    - bits_per_sample -- I2S data bit width

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  MSB format in 2 slots.

  Parameters:

    - bits_per_sample -- I2S data bit width

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_STD_CLK_DEFAULT_CONFIG(rate)

  I2S default standard clock configuration.

  Note

  Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while using 24 bits data width Otherwise the sample rate might be imprecise since the BCLK division is not a integer

  Parameters:

    - rate -- sample rate

### PDM Mode

### Header File

- components/esp_driver_i2s/include/driver/i2s_pdm.h

- This header file can be included with:

  >     #include "driver/i2s_pdm.h"

- This header file is a part of the API provided by the `esp_driver_i2s` component. To declare that your component depends on `esp_driver_i2s`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_i2s

  > or

  >     PRIV_REQUIRES esp_driver_i2s

### Functions

esp_err_t i2s_channel_init_pdm_rx_mode(i2s_chan_handle_t handle, const i2s_pdm_rx_config_t *pdm_rx_cfg)

  Initialize I2S channel to PDM RX mode.

  Note

  Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized) and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.

  Parameters:

    - handle -- [in] I2S RX channel handler

    - pdm_rx_cfg -- [in] Configurations for PDM RX mode, including clock, slot and GPIO The clock configuration can be generated by the helper macro `I2S_PDM_RX_CLK_DEFAULT_CONFIG` The slot configuration can be generated by the helper macro `I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG` or `I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Initialize successfully

    - ESP_ERR_NO_MEM No memory for storing the channel information

    - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration

    - ESP_ERR_INVALID_STATE This channel is not registered

esp_err_t i2s_channel_reconfig_pdm_rx_clock(i2s_chan_handle_t handle, const i2s_pdm_rx_clk_config_t *clk_cfg)

  Reconfigure the I2S clock for PDM RX mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to PDM RX mode, i.e., `i2s_channel_init_pdm_rx_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S RX channel handler

    - clk_cfg -- [in] PDM RX mode clock configuration, can be generated by `I2S_PDM_RX_CLK_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_reconfig_pdm_rx_slot(i2s_chan_handle_t handle, const i2s_pdm_rx_slot_config_t *slot_cfg)

  Reconfigure the I2S slot for PDM RX mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to PDM RX mode, i.e., `i2s_channel_init_pdm_rx_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S RX channel handler

    - slot_cfg -- [in] PDM RX mode slot configuration, can be generated by `I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG` or `I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_NO_MEM No memory for DMA buffer

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_reconfig_pdm_rx_gpio(i2s_chan_handle_t handle, const i2s_pdm_rx_gpio_config_t *gpio_cfg)

  Reconfigure the I2S GPIO for PDM RX mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to PDM RX mode, i.e., `i2s_channel_init_pdm_rx_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S RX channel handler

    - gpio_cfg -- [in] PDM RX mode GPIO configuration, specified by user

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_init_pdm_tx_mode(i2s_chan_handle_t handle, const i2s_pdm_tx_config_t *pdm_tx_cfg)

  Initialize I2S channel to PDM TX mode.

  Note

  Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized) and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.

  Parameters:

    - handle -- [in] I2S TX channel handler

    - pdm_tx_cfg -- [in] Configurations for PDM TX mode, including clock, slot and GPIO The clock configuration can be generated by the helper macro `I2S_PDM_TX_CLK_DEFAULT_CONFIG` The slot configuration can be generated by the helper macro `I2S_PDM_TX_SLOT_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Initialize successfully

    - ESP_ERR_NO_MEM No memory for storing the channel information

    - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration

    - ESP_ERR_INVALID_STATE This channel is not registered

esp_err_t i2s_channel_reconfig_pdm_tx_clock(i2s_chan_handle_t handle, const i2s_pdm_tx_clk_config_t *clk_cfg)

  Reconfigure the I2S clock for PDM TX mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to PDM TX mode, i.e., `i2s_channel_init_pdm_tx_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S TX channel handler

    - clk_cfg -- [in] PDM TX mode clock configuration, can be generated by `I2S_PDM_TX_CLK_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_reconfig_pdm_tx_slot(i2s_chan_handle_t handle, const i2s_pdm_tx_slot_config_t *slot_cfg)

  Reconfigure the I2S slot for PDM TX mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to PDM TX mode, i.e., `i2s_channel_init_pdm_tx_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S TX channel handler

    - slot_cfg -- [in] PDM TX mode slot configuration, can be generated by `I2S_PDM_TX_SLOT_DEFAULT_CONFIG`

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_NO_MEM No memory for DMA buffer

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

esp_err_t i2s_channel_reconfig_pdm_tx_gpio(i2s_chan_handle_t handle, const i2s_pdm_tx_gpio_config_t *gpio_cfg)

  Reconfigure the I2S GPIO for PDM TX mode.

  Note

  Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started this function won't change the state. `i2s_channel_disable` should be called before calling this function if I2S has started.

  Note

  The input channel handle has to be initialized to PDM TX mode, i.e., `i2s_channel_init_pdm_tx_mode` has been called before reconfiguring

  Parameters:

    - handle -- [in] I2S TX channel handler

    - gpio_cfg -- [in] PDM TX mode GPIO configuration, specified by user

  Returns:

    - ESP_OK Set clock successfully

    - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode

    - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped

### Structures

struct i2s_pdm_rx_slot_config_t

  I2S slot configuration for PDM RX mode.

  Public Members

  i2s_data_bit_width_t data_bit_width

    I2S sample data bit width (valid data bits per sample), only support 16 bits for PDM mode

  i2s_slot_bit_width_t slot_bit_width

    I2S slot bit width (total bits per slot) , only support 16 bits for PDM mode

  i2s_slot_mode_t slot_mode

    Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

  i2s_pdm_slot_mask_t slot_mask

    Choose the slots to activate

  i2s_pdm_data_fmt_t data_fmt

    The data format of PDM RX mode. It determines what kind of data format is read in software. Typically, set this field to I2S_PDM_DATA_FMT_PCM when PDM2PCM filter is supported in the hardware, so that the hardware PDM2PCM filter will help to convert the raw PDM data on the line into PCM format, And then you can read PCM format data in software. Otherwise if this field is set to I2S_PDM_DATA_FMT_RAW, The data read in software are still in raw PDM format, you may need to convert the raw PDM data into PCM format manually by a software filter.

struct i2s_pdm_rx_clk_config_t

  I2S clock configuration for PDM RX mode.

  Public Members

  uint32_t sample_rate_hz

    I2S sample rate.

    - For raw PDM mode, it typically ranges 1.024MHz ~ 6.144MHz.

    - For PCM mode (PDM2PCM filter enabled), it usually ranges 16KHz ~ 48KHz

  i2s_clock_src_t clk_src

    Choose clock source

  i2s_mclk_multiple_t mclk_multiple

    The multiple of MCLK to the sample rate

  i2s_pdm_dsr_t dn_sample_mode

    Down-sampling rate mode

  uint32_t bclk_div

    The division from MCLK to BCLK. The typical and minimum value is I2S_PDM_RX_BCLK_DIV_MIN. It will be set to I2S_PDM_RX_BCLK_DIV_MIN by default if it is smaller than I2S_PDM_RX_BCLK_DIV_MIN

struct i2s_pdm_rx_gpio_config_t

  I2S PDM RX mode GPIO pins configuration.

  Public Members

  gpio_num_t clk

    PDM clk pin, output

  gpio_num_t din

    DATA pin 0, input

  gpio_num_t dins[(1U)]

    DATA pins, input, only take effect when corresponding I2S_PDM_RX_LINEx_SLOT_xxx is enabled in i2s_pdm_rx_slot_config_t::slot_mask

  uint32_t clk_inv

    Set 1 to invert the clk output

  struct i2s_pdm_rx_gpio_config_t invert_flags

    GPIO pin invert flags

struct i2s_pdm_rx_config_t

  I2S PDM RX mode major configuration that including clock/slot/GPIO configuration.

  Public Members

  i2s_pdm_rx_clk_config_t clk_cfg

    PDM RX clock configurations, can be generated by macro I2S_PDM_RX_CLK_DEFAULT_CONFIG

  i2s_pdm_rx_slot_config_t slot_cfg

    PDM RX slot configurations, can be generated by macro I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG or I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG

  i2s_pdm_rx_gpio_config_t gpio_cfg

    PDM RX slot configurations, specified by user

struct i2s_pdm_tx_slot_config_t

  I2S slot configuration for PDM TX mode.

  Public Members

  i2s_data_bit_width_t data_bit_width

    I2S sample data bit width (valid data bits per sample), only support 16 bits for PDM mode

  i2s_slot_bit_width_t slot_bit_width

    I2S slot bit width (total bits per slot), only support 16 bits for PDM mode

  i2s_slot_mode_t slot_mode

    Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO For PDM TX mode, mono means the data buffer only contains one slot data, Stereo means the data buffer contains two slots data

  i2s_pdm_slot_mask_t slot_mask

    Slot mask to choose left or right slot

  i2s_pdm_data_fmt_t data_fmt

    The data format of PDM TX mode. It determines what kind of data format is written in software. Typically, set this field to I2S_PDM_DATA_FMT_PCM when PCM2PDM filter is supported in the hardware, so that you can write PCM format data in software, and then the hardware PCM2PDM filter will help to convert it into PDM format on the line. Otherwise if this field is set to I2S_PDM_DATA_FMT_RAW, The data written in software are supposed to be the raw PDM format.

  uint32_t sd_prescale

    Sigma-delta filter prescale

  i2s_pdm_sig_scale_t sd_scale

    Sigma-delta filter scaling value

  i2s_pdm_sig_scale_t hp_scale

    High pass filter scaling value

  i2s_pdm_sig_scale_t lp_scale

    Low pass filter scaling value

  i2s_pdm_sig_scale_t sinc_scale

    Sinc filter scaling value

struct i2s_pdm_tx_clk_config_t

  I2S clock configuration for PDM TX mode.

  Public Members

  uint32_t sample_rate_hz

    I2S sample rate.

    - For raw PDM mode, it typically ranges 1.024MHz ~ 6.144MHz.

    - For PCM mode (PCM2PDM filter enabled), it usually ranges 16KHz ~ 48KHz

  i2s_clock_src_t clk_src

    Choose clock source

  i2s_mclk_multiple_t mclk_multiple

    The multiple of MCLK to the sample rate

  uint32_t up_sample_fp

    Up-sampling param fp

  uint32_t up_sample_fs

    Up-sampling param fs, not allowed to be greater than 480

  uint32_t bclk_div

    The division from MCLK to BCLK. The minimum value is I2S_PDM_TX_BCLK_DIV_MIN. It will be set to I2S_PDM_TX_BCLK_DIV_MIN by default if it is smaller than I2S_PDM_TX_BCLK_DIV_MIN

struct i2s_pdm_tx_gpio_config_t

  I2S PDM TX mode GPIO pins configuration.

  Public Members

  gpio_num_t clk

    PDM clk pin, output

  gpio_num_t dout

    DATA pin, output

  uint32_t clk_inv

    Set 1 to invert the clk output

  struct i2s_pdm_tx_gpio_config_t invert_flags

    GPIO pin invert flags

struct i2s_pdm_tx_config_t

  I2S PDM TX mode major configuration that including clock/slot/GPIO configuration.

  Public Members

  i2s_pdm_tx_clk_config_t clk_cfg

    PDM TX clock configurations, can be generated by macro I2S_PDM_TX_CLK_DEFAULT_CONFIG

  i2s_pdm_tx_slot_config_t slot_cfg

    PDM TX slot configurations, can be generated by macro I2S_PDM_TX_SLOT_DEFAULT_CONFIG

  i2s_pdm_tx_gpio_config_t gpio_cfg

    PDM TX GPIO configurations, specified by user

### Macros

I2S_PDM_RX_SLOT_PCM_FMT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  PDM format in 2 slots(RX). Read data in PCM format.

  This file is specified for I2S PDM communication mode Features:

  - Only support PDM TX/RX mode

  - Fixed to 2 slots

  - Data bit width only support 16 bits

  Parameters:

    - bits_per_sample -- I2S data bit width, only support 16 bits for PDM mode

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_PDM_RX_SLOT_RAW_FMT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  PDM mode in 2 slots(RX). Read data in raw PDM format.

  Parameters:

    - bits_per_sample -- I2S data bit width, only support 16 bits for PDM mode

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_PDM_RX_CLK_DEFAULT_CONFIG(rate)

  I2S default PDM RX clock configuration.

  Parameters:

    - rate -- sample rate

I2S_PDM_TX_SLOT_PCM_FMT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  PDM style in 2 slots(TX) for codec line mode. Write PCM data.

  Parameters:

    - bits_per_sample -- I2S data bit width, only support 16 bits for PDM mode

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_PDM_TX_SLOT_RAW_FMT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo)

  PDM style in 2 slots(TX) for codec line mode. Write PDM data.

  Parameters:

    - bits_per_sample -- I2S data bit width, only support 16 bits for PDM mode

    - mono_or_stereo -- I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO

I2S_PDM_TX_CLK_DEFAULT_CONFIG(rate)

  I2S default PDM TX clock configuration for codec line mode.

  Note

  TX PDM can only be set to the following two up-sampling rate configurations: 1: fp = 960, fs = sample_rate_hz / 100, in this case, Fpdm = 128*48000 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate_hz If the PDM receiver do not care the PDM serial clock, it's recommended set Fpdm = 128*48000. Otherwise, the second configuration should be adopted.

  Parameters:

    - rate -- sample rate (not suggest to exceed 48000 Hz, otherwise more glitches and noise may appear)

I2S_PDM_TX_CLK_DAC_DEFAULT_CONFIG(rate)

  I2S default PDM TX clock configuration for DAC line mode.

  Note

  TX PDM can only be set to the following two up-sampling rate configurations: 1: fp = 960, fs = sample_rate_hz / 100, in this case, Fpdm = 128*48000 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate_hz If the PDM receiver do not care the PDM serial clock, it's recommended set Fpdm = 128*48000. Otherwise, the second configuration should be adopted.

  Note

  The noise might be different with different configurations, this macro provides a set of configurations that have relatively high SNR (Signal Noise Ratio), you can also adjust them to fit your case.

  Parameters:

    - rate -- sample rate (not suggest to exceed 48000 Hz, otherwise more glitches and noise may appear)

### I2S Driver

### Header File

- components/esp_driver_i2s/include/driver/i2s_common.h

- This header file can be included with:

  >     #include "driver/i2s_common.h"

- This header file is a part of the API provided by the `esp_driver_i2s` component. To declare that your component depends on `esp_driver_i2s`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_i2s

  > or

  >     PRIV_REQUIRES esp_driver_i2s

### Functions

esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *ret_tx_handle, i2s_chan_handle_t *ret_rx_handle)

  Allocate new I2S channel(s)

  Note

  The new created I2S channel handle will be REGISTERED state after it is allocated successfully.

  Note

  When the port id in channel configuration is I2S_NUM_AUTO, driver will allocate I2S port automatically on one of the I2S controller, otherwise driver will try to allocate the new channel on the selected port.

  Note

  If both tx_handle and rx_handle are not NULL, it means this I2S controller will work at full-duplex mode, the RX and TX channels will be allocated on a same I2S port in this case. Note that some configurations of TX/RX channel are shared on ESP32 and ESP32S2, so please make sure they are working at same condition and under same status(start/stop). Currently, full-duplex mode can't guarantee TX/RX channels write/read synchronously, they can only share the clock signals for now.

  Note

  If tx_handle OR rx_handle is NULL, it means this I2S controller will work at simplex mode. For ESP32 and ESP32S2, the whole I2S controller (i.e. both RX and TX channel) will be occupied, even if only one of RX or TX channel is registered. For the other targets, another channel on this controller will still available.

  Note

  `tx_destination` / `rx_destination` select the DMA memory path or Bluetooth data path when supported. Requesting an unsupported destination or port returns an error.

  Parameters:

    - chan_cfg -- [in] I2S controller channel configurations

    - ret_tx_handle -- [out] I2S channel handler used for managing the sending channel(optional)

    - ret_rx_handle -- [out] I2S channel handler used for managing the receiving channel(optional)

  Returns:

    - ESP_OK Allocate new channel(s) success

    - ESP_ERR_NOT_SUPPORTED The communication mode or data path is not supported on the current chip, or Bluetooth data path is requested on an unsupported port

    - ESP_ERR_INVALID_ARG NULL pointer or illegal parameter in i2s_chan_config_t

    - ESP_ERR_NOT_FOUND No available I2S channel found

esp_err_t i2s_del_channel(i2s_chan_handle_t handle)

  Delete the I2S channel.

  Note

  Only allowed to be called when the I2S channel is at REGISTERED or READY state (i.e., it should stop before deleting it).

  Note

  Resource will be free automatically if all channels in one port are deleted

  Parameters:

    handle -- [in] I2S channel handler

    - ESP_OK Delete successfully

    - ESP_ERR_INVALID_ARG NULL pointer

esp_err_t i2s_channel_get_info(i2s_chan_handle_t handle, i2s_chan_info_t *chan_info)

  Get I2S channel information.

  Parameters:

    - handle -- [in] I2S channel handler

    - chan_info -- [out] I2S channel basic information

  Returns:

    - ESP_OK Get I2S channel information success

    - ESP_ERR_NOT_FOUND The input handle doesn't match any registered I2S channels, it may not an I2S channel handle or not available any more

    - ESP_ERR_INVALID_ARG The input handle or chan_info pointer is NULL

esp_err_t i2s_channel_enable(i2s_chan_handle_t handle)

  Enable the I2S channel.

  Note

  Only allowed to be called when the channel state is READY, (i.e., channel has been initialized, but not started) the channel will enter RUNNING state once it is enabled successfully.

  Note

  Enable the channel can start the I2S communication on hardware. It will start outputting BCLK and WS signal. For MCLK signal, it will start to output when initialization is finished

  Parameters:

    handle -- [in] I2S channel handler

    - ESP_OK Start successfully

    - ESP_ERR_INVALID_ARG NULL pointer

    - ESP_ERR_INVALID_STATE This channel has not initialized or already started

esp_err_t i2s_channel_disable(i2s_chan_handle_t handle)

  Disable the I2S channel.

  Note

  Only allowed to be called when the channel state is RUNNING, (i.e., channel has been started) the channel will enter READY state once it is disabled successfully.

  Note

  Disable the channel can stop the I2S communication on hardware. It will stop BCLK and WS signal but not MCLK signal

  Parameters:

    handle -- [in] I2S channel handler

  Returns:

    - ESP_OK Stop successfully

    - ESP_ERR_INVALID_ARG NULL pointer

    - ESP_ERR_INVALID_STATE This channel has not stated

esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t size, size_t *bytes_written, uint32_t timeout_ms)

  I2S write data.

  Note

  Only allowed to be called when the channel state is RUNNING, (i.e., TX channel has been started and is not writing now) but the RUNNING only stands for the software state, it doesn't mean there is no the signal transporting on line.

  Parameters:

    - handle -- [in] I2S channel handler

    - src -- [in] The pointer of sent data buffer

    - size -- [in] Max data buffer length

    - bytes_written -- [out] Byte number that actually be sent, can be NULL if not needed

    - timeout_ms -- [in] Max block time

  Returns:

    - ESP_OK Write successfully

    - ESP_ERR_INVALID_ARG NULL pointer or this handle is not TX handle

    - ESP_ERR_TIMEOUT Writing timeout, no writing event received from ISR within ticks_to_wait

    - ESP_ERR_INVALID_STATE I2S is not ready to write

esp_err_t i2s_channel_read(i2s_chan_handle_t handle, void *dest, size_t size, size_t *bytes_read, uint32_t timeout_ms)

  I2S read data.

  Note

  Only allowed to be called when the channel state is RUNNING but the RUNNING only stands for the software state, it doesn't mean there is no the signal transporting on line.

  Parameters:

    - handle -- [in] I2S channel handler

    - dest -- [in] The pointer of receiving data buffer

    - size -- [in] Max data buffer length

    - bytes_read -- [out] Byte number that actually be read, can be NULL if not needed

    - timeout_ms -- [in] Max block time

  Returns:

    - ESP_OK Read successfully

    - ESP_ERR_INVALID_ARG NULL pointer or this handle is not RX handle

    - ESP_ERR_TIMEOUT Reading timeout, no reading event received from ISR within ticks_to_wait

    - ESP_ERR_INVALID_STATE I2S is not ready to read

esp_err_t i2s_channel_register_event_callback(i2s_chan_handle_t handle, const i2s_event_callbacks_t *callbacks, void *user_data)

  Set event callbacks for I2S channel.

  Note

  DMA event callbacks can only be registered or deregistered before the channel is enabled.

  Note

  The TX FIFO sync callback can be registered, updated, or deregistered while the channel is running.

  Note

  Registering the TX FIFO sync callback only updates the handler; the TX sync interrupt is controlled by i2s_channel_enable_tx_fifo_sync().

  Note

  User can deregister a previously registered callback by calling this function and setting the callback member in the `callbacks` structure to NULL.

  Note

  When CONFIG_I2S_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. The variables used in the function should be in the SRAM as well. The `user_data` should also reside in SRAM or internal RAM as well.

  Parameters:

    - handle -- [in] I2S channel handler

    - callbacks -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  Returns:

    - ESP_OK Set event callbacks successfully

    - ESP_ERR_INVALID_ARG Set event callbacks failed because of invalid argument

    - ESP_ERR_INVALID_STATE Set event callbacks failed because DMA event callbacks are changed while the channel is running

    - ESP_ERR_NOT_SUPPORTED Set event callbacks failed because the requested event is not supported by this channel

esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src, size_t size, size_t *bytes_loaded)

  Preload the data into TX DMA buffer.

  Note

  Only allowed to be called when the channel state is READY, (i.e., channel has been initialized, but not started)

  Note

  As the initial DMA buffer has no data inside, it will transmit the empty buffer after enabled the channel, this function is used to preload the data into the DMA buffer, so that the valid data can be transmitted immediately after the channel is enabled.

  Note

  This function can be called multiple times before enabling the channel, the buffer that loaded later will be concatenated behind the former loaded buffer. But when all the DMA buffers have been loaded, no more data can be preload then, please check the `bytes_loaded` parameter to see how many bytes are loaded successfully, when the `bytes_loaded` is smaller than the `size`, it means the DMA buffers are full.

  Parameters:

    - tx_handle -- [in] I2S TX channel handler

    - src -- [in] The pointer of the source buffer to be loaded

    - size -- [in] The source buffer size

    - bytes_loaded -- [out] The bytes that successfully been loaded into the TX DMA buffer

  Returns:

    - ESP_OK Load data successful

    - ESP_FAIL Failed to push the message queue

    - ESP_ERR_INVALID_ARG NULL pointer or not TX direction

    - ESP_ERR_INVALID_STATE This channel has not stated

esp_err_t i2s_channel_tune_rate(i2s_chan_handle_t handle, const i2s_tuning_config_t *tune_cfg, i2s_tuning_info_t *tune_info)

  Tune the I2S clock rate.

  Note

  Only allowed to be called when the channel state is READY, (i.e., channel has been initialized, but not started)

  Note

  This function is mainly to fine-tuning the mclk to match the speed of producer and consumer. So that to avoid exsaust of the memory to store the data from producer. Please take care the how different the frequency error can be tolerant by your codec, otherwise the codec might stop working if the frequency changes a lot.

  Parameters:

    - handle -- [in] I2S channel handler

    - tune_cfg -- [in] The clock tuning configuration, can be NULL if only need the current clock result

    - tune_info -- [out] The clock tuning information, can be NULL if not needed

  Returns:

    - ESP_OK Tune the clock successfully

    - ESP_ERR_INVALID_ARG Tune the clock failed because of the invalid argument like NULL pointer or out of range

    - ESP_ERR_NOT_SUPPORTED Tune the clock failed because this function does not support to tune the external clock source

### Structures

struct i2s_event_callbacks_t

  Group of I2S callbacks.

  Note

  The callbacks are all running under ISR environment

  Note

  When CONFIG_I2S_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. The variables used in the function should be in the SRAM as well.

  Public Members

  i2s_isr_callback_t on_recv

    Callback of data received event, only for RX channel The event data includes DMA buffer address and size that just finished receiving data

  i2s_isr_callback_t on_recv_q_ovf

    Callback of receiving queue overflowed event, only for RX channel The event data includes buffer size that has been overwritten

  i2s_isr_callback_t on_sent

    Callback of data sent event, only for TX channel The event data includes DMA buffer address and size that just finished sending data

  i2s_isr_callback_t on_send_q_ovf

    Callback of sending queue overflowed event, only for TX channel The event data includes buffer size that has been overwritten

struct i2s_chan_config_t

  I2S controller channel configuration.

  Public Members

  int id

    I2S port id

  i2s_role_t role

    I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE

  uint32_t dma_desc_num

    I2S DMA buffer number, it is also the number of DMA descriptor

  uint32_t dma_frame_num

    I2S frame number in one DMA buffer. One frame means one-time sample data in all slots, it should be the multiple of `3` when the data bit width is 24.

  bool auto_clear

    Alias of `auto_clear_after_cb`

  bool auto_clear_after_cb

    Set to auto clear DMA TX buffer after `on_sent` callback, I2S will always send zero automatically if no data to send. So that user can assign the data to the DMA buffers directly in the callback, and the data won't be cleared after quit the callback.

  bool auto_clear_before_cb

    Set to auto clear DMA TX buffer before `on_sent` callback, I2S will always send zero automatically if no data to send So that user can access data in the callback that just finished to send.

  bool allow_pd

    Set to allow power down. When this flag set, the driver will backup/restore the I2S registers before/after entering/exist sleep mode. By this approach, the system can power off I2S's power domain. This can save power, but at the expense of more RAM being consumed.

  int intr_priority

    I2S interrupt priority, range [0, 7], if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  i2s_destination_t tx_destination

    TX data path: DMA (memory) or Bluetooth (see `i2s_destination_t`). I2S0 only when set to `I2S_DESTINATION_BT`. Immutable after `i2s_new_channel`.

  i2s_destination_t rx_destination

    RX data path: DMA (memory) or Bluetooth. Same constraints as `tx_destination`.

struct i2s_chan_info_t

  I2S channel information.

  Public Members

  int id

    I2S port id

  i2s_role_t role

    I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE

  i2s_dir_t dir

    I2S channel direction

  i2s_comm_mode_t mode

    I2S channel communication mode

  bool is_enabled

    I2S channel is enabled or not

  i2s_chan_handle_t pair_chan

    I2S pair channel handle in duplex mode, always NULL in simplex mode

  uint32_t total_dma_buf_size

    Total size of all the allocated DMA buffers

    - 0 if the channel has not been initialized

    - non-zero if the channel has been initialized

  i2s_clock_src_t clk_src

    Clock source of I2S

  uint32_t sclk_hz

    Source clock frequency

  uint32_t mclk_hz

    MCLK frequency

  uint32_t bclk_hz

    BCLK frequency

  const void *mode_cfg

    Mode configuration, it need to be casted to the corresponding type according to the communication mode

    - I2S_COMM_MODE_STD: i2s_std_config_t*

    - I2S_COMM_MODE_TDM: i2s_tdm_config_t*

    - I2S_COMM_MODE_PDM + I2S_DIR_RX: i2s_pdm_rx_config_t*

    - I2S_COMM_MODE_PDM + I2S_DIR_TX: i2s_pdm_tx_config_t*

### Macros

I2S_CHANNEL_DEFAULT_CONFIG(i2s_num, i2s_role)

  get default I2S property

I2S_GPIO_UNUSED

  Used in i2s_gpio_config_t for signals which are not used

### I2S Types

### Header File

- components/esp_driver_i2s/include/driver/i2s_types.h

- This header file can be included with:

  >     #include "driver/i2s_types.h"

- This header file is a part of the API provided by the `esp_driver_i2s` component. To declare that your component depends on `esp_driver_i2s`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_i2s

  > or

  >     PRIV_REQUIRES esp_driver_i2s

### Structures

struct lp_i2s_trans_t

  LP I2S transaction type.

  Public Members

  void *buffer

    Pointer to buffer.

  size_t buflen

    Buffer len, this should be in the multiple of 4.

  size_t received_size

    Received size.

struct i2s_event_data_t

  Event structure used in I2S event queue.

  Public Members

  void *dma_buf

    The first level pointer of DMA buffer that just finished sending or receiving for `on_recv` and `on_sent` callback NULL for `on_recv_q_ovf` and `on_send_q_ovf` callback

  size_t size

    The buffer size of DMA buffer when success to send or receive, also the buffer size that dropped when queue overflow. It is related to the dma_frame_num and data_bit_width, typically it is fixed when data_bit_width is not changed.

struct i2s_tuning_config_t

  I2S clock tuning configurations.

  Public Members

  i2s_tuning_mode_t tune_mode

    Tuning mode, which decides how to tune the MCLK with the tuning value

  int32_t tune_mclk_val

    Tuning value

  int32_t max_delta_mclk

    The maximum frequency that can be increased comparing to the initial MCLK freuqnecy

  int32_t min_delta_mclk

    The minimum frequency that can be decreased comparing to the initial MCLK freuqnecy

struct i2s_tuning_info_t

  I2S clock tuning result.

  Public Members

  int32_t curr_mclk_hz

    The current MCLK frequency after tuned

  int32_t delta_mclk_hz

    The current changed MCLK frequency comparing to the initial MCLK frequency

  uint32_t water_mark

    The water mark of the internal buffer, in percent

struct lp_i2s_evt_data_t

  Event data structure for LP I2S.

  Public Members

  lp_i2s_trans_t trans

    LP I2S transaction.

### Macros

I2S_NUM_0

  I2S controller port 0

I2S_NUM_1

  I2S controller port 1

I2S_NUM_2

  I2S controller port 2

I2S_NUM_AUTO

  Select an available port automatically

### Type Definitions

typedef struct i2s_channel_obj_t *i2s_chan_handle_t

  I2S channel object handle, the control unit of the I2S driver

typedef struct lp_i2s_channel_obj_t *lp_i2s_chan_handle_t

  I2S channel object handle, the control unit of the I2S driver

typedef bool (*i2s_isr_callback_t)(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx)

  I2S event callback.

  Param handle:

    [in] I2S channel handle, created from `i2s_new_channel()`

  Param event:

    [in] I2S event data

  Param user_ctx:

    [in] User registered context, passed from `i2s_channel_register_event_callback()`

  Return:

    Whether a high priority task has been waken up by this callback function

typedef bool (*lp_i2s_callback_t)(lp_i2s_chan_handle_t handle, lp_i2s_evt_data_t *event, void *user_ctx)

  LP I2S event callback type.

  Param handle:

    [in] LP I2S channel handle

  Param event:

    [in] Event data

  Param user_ctx:

    [in] User data

  Return:

    Whether a high priority task has been waken up by this callback function

### Enumerations

enum i2s_comm_mode_t

  I2S controller communication mode.

  Values:

  enumerator I2S_COMM_MODE_STD

    I2S controller using standard communication mode, support Philips/MSB/PCM format

  enumerator I2S_COMM_MODE_PDM

    I2S controller using PDM communication mode, support PDM output or input

  enumerator I2S_COMM_MODE_NONE

    Unspecified I2S controller mode

enum i2s_mclk_multiple_t

  The multiple of MCLK to sample rate.

  Note

  MCLK is the minimum resolution of the I2S clock. Increasing mclk multiple can reduce the clock jitter of BCLK and WS, which is also useful for the codec that don't require MCLK but have strict requirement to BCLK. For the 24-bit slot width, please choose a multiple that can be divided by 3 (i.e. 24-bit compatible).

  Values:

  enumerator I2S_MCLK_MULTIPLE_128

    MCLK = sample_rate * 128

  enumerator I2S_MCLK_MULTIPLE_192

    MCLK = sample_rate * 192 (24-bit compatible)

  enumerator I2S_MCLK_MULTIPLE_256

    MCLK = sample_rate * 256

  enumerator I2S_MCLK_MULTIPLE_384

    MCLK = sample_rate * 384 (24-bit compatible)

  enumerator I2S_MCLK_MULTIPLE_512

    MCLK = sample_rate * 512

  enumerator I2S_MCLK_MULTIPLE_576

    MCLK = sample_rate * 576 (24-bit compatible)

  enumerator I2S_MCLK_MULTIPLE_768

    MCLK = sample_rate * 768 (24-bit compatible)

  enumerator I2S_MCLK_MULTIPLE_1024

    MCLK = sample_rate * 1024

  enumerator I2S_MCLK_MULTIPLE_1152

    MCLK = sample_rate * 1152 (24-bit compatible)

enum i2s_tuning_mode_t

  I2S clock tuning operation.

  Values:

  enumerator I2S_TUNING_MODE_ADDSUB

    Add or subtract the tuning value based on the current clock

  enumerator I2S_TUNING_MODE_SET

    Set the tuning value to overwrite the current clock

  enumerator I2S_TUNING_MODE_RESET

    Set the clock to the initial value

### Header File

- components/esp_hal_i2s/include/hal/i2s_types.h

- This header file can be included with:

  >     #include "hal/i2s_types.h"

- This header file is a part of the API provided by the `esp_hal_i2s` component. To declare that your component depends on `esp_hal_i2s`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_hal_i2s

  > or

  >     PRIV_REQUIRES esp_hal_i2s

### Type Definitions

typedef int i2s_clock_src_t

  Define a default type to avoid compiling warnings

### Enumerations

enum i2s_slot_mode_t

  I2S channel slot mode.

  Values:

  enumerator I2S_SLOT_MODE_MONO

    I2S channel slot format mono, transmit same data in all slots for tx mode, only receive the data in the first slots for rx mode.

  enumerator I2S_SLOT_MODE_STEREO

    I2S channel slot format stereo, transmit different data in different slots for tx mode, receive the data in all slots for rx mode.

enum i2s_dir_t

  I2S channel direction.

  Values:

  enumerator I2S_DIR_RX

    I2S channel direction RX

  enumerator I2S_DIR_TX

    I2S channel direction TX

enum i2s_role_t

  I2S controller role.

  Values:

  enumerator I2S_ROLE_MASTER

    I2S controller master role, bclk and ws signal will be set to output

  enumerator I2S_ROLE_SLAVE

    I2S controller slave role, bclk and ws signal will be set to input

enum i2s_data_bit_width_t

  Available data bit width in one slot.

  Values:

  enumerator I2S_DATA_BIT_WIDTH_8BIT

    I2S channel data bit-width: 8

  enumerator I2S_DATA_BIT_WIDTH_16BIT

    I2S channel data bit-width: 16

  enumerator I2S_DATA_BIT_WIDTH_24BIT

    I2S channel data bit-width: 24

  enumerator I2S_DATA_BIT_WIDTH_32BIT

    I2S channel data bit-width: 32

enum i2s_slot_bit_width_t

  Total slot bit width in one slot.

  Values:

  enumerator I2S_SLOT_BIT_WIDTH_AUTO

    I2S channel slot bit-width equals to data bit-width

  enumerator I2S_SLOT_BIT_WIDTH_8BIT

    I2S channel slot bit-width: 8

  enumerator I2S_SLOT_BIT_WIDTH_16BIT

    I2S channel slot bit-width: 16

  enumerator I2S_SLOT_BIT_WIDTH_24BIT

    I2S channel slot bit-width: 24

  enumerator I2S_SLOT_BIT_WIDTH_32BIT

    I2S channel slot bit-width: 32

enum i2s_destination_t

  I2S data path destination.

  Values:

  enumerator I2S_DESTINATION_DMA

    Route I2S sample data through DMA to/from memory (default). On chips without GDMA, this is the legacy I2S DMA path.

  enumerator I2S_DESTINATION_BT

    Route I2S data to Bluetooth (I2S0 only; see `SOC_I2S_SUPPORTS_BT_DEST`)

enum i2s_pdm_data_fmt_t

  I2S PDM data format.

  Values:

  enumerator I2S_PDM_DATA_FMT_PCM

    PDM RX: Enable the hardware PDM to PCM filter to convert the inputted PDM data on the line into PCM format in software, so that the read data in software is PCM format data already, no need additional software filter. PCM data format is only available when PDM2PCM filter is supported in hardware. PDM TX: Enable the hardware PCM to PDM filter to convert the written PCM data in software into PDM format on the line, so that we only need to write the PCM data in software, no need to prepare raw PDM data in software. PCM data format is only available when PCM2PDM filter is supported in hardware.

  enumerator I2S_PDM_DATA_FMT_RAW

    PDM RX: Read the raw PDM data directly in software, without the hardware PDM to PCM filter. You may need a software PDM to PCM filter to convert the raw PDM data that read into PCM format. PDM TX: Write the raw PDM data directly in software, without the hardware PCM to PDM filter. You may need to prepare the raw PDM data in software to output the PDM format data on the line.

enum i2s_pdm_dsr_t

  I2S PDM RX down-sampling mode.

  Values:

  enumerator I2S_PDM_DSR_8S

    downsampling number is 8 for PDM RX mode

  enumerator I2S_PDM_DSR_16S

    downsampling number is 16 for PDM RX mode

  enumerator I2S_PDM_DSR_MAX

enum i2s_pdm_sig_scale_t

  pdm tx signal scaling mode

  Values:

  enumerator I2S_PDM_SIG_SCALING_DIV_2

    I2S TX PDM signal scaling: /2

  enumerator I2S_PDM_SIG_SCALING_MUL_1

    I2S TX PDM signal scaling: x1

  enumerator I2S_PDM_SIG_SCALING_MUL_2

    I2S TX PDM signal scaling: x2

  enumerator I2S_PDM_SIG_SCALING_MUL_4

    I2S TX PDM signal scaling: x4

enum i2s_std_slot_mask_t

  I2S slot select in standard mode.

  Note

  It has different meanings in tx/rx/mono/stereo mode, and it may have different behaviors on different targets For the details, please refer to the I2S API reference

  Values:

  enumerator I2S_STD_SLOT_LEFT

    I2S transmits or receives left slot

  enumerator I2S_STD_SLOT_RIGHT

    I2S transmits or receives right slot

  enumerator I2S_STD_SLOT_BOTH

    I2S transmits or receives both left and right slot

enum i2s_pdm_slot_mask_t

  I2S slot select in PDM mode.

  Values:

  enumerator I2S_PDM_SLOT_RIGHT

    I2S PDM only transmits or receives the PDM device whose 'select' pin is pulled up

  enumerator I2S_PDM_SLOT_LEFT

    I2S PDM only transmits or receives the PDM device whose 'select' pin is pulled down

  enumerator I2S_PDM_SLOT_BOTH

    I2S PDM transmits or receives both two slots

enum i2s_etm_event_type_t

  I2S channel events that supported by the ETM module.

  Values:

  enumerator I2S_ETM_EVENT_DONE

    Trigger condition: TX: no data to send in the TX FIFO, i.e., DMA need to stop (next desc is NULL) RX: 1. If rx_stop_mode = 0, this event will trigger when DMA is stopped (next desc is NULL)

    1. If rx_stop_mode = 1, this event will trigger when DMA in_suc_eof.

    2. If rx_stop_mode = 2, this event will trigger when RX FIFO is full. Event that I2S TX or RX stopped

  enumerator I2S_ETM_EVENT_REACH_THRESH

    Trigger condition: TX: the sent words(in 32-bit) number reach the threshold that configured in `etm_tx_send_word_num` RX: the received words(in 32-bit) number reach the threshold that configured in `etm_rx_receive_word_num` and `etm_rx_receive_word_num` should be smaller than the size of the DMA buffer in one `in_suc_eof` event. Event that the I2S sent or received data reached the threshold

  enumerator I2S_ETM_EVENT_MAX

    Maximum number of events

enum i2s_etm_task_type_t

  I2S channel tasks that supported by the ETM module.

  Values:

  enumerator I2S_ETM_TASK_START

    Start the I2S channel

  enumerator I2S_ETM_TASK_STOP

    Stop the I2S channel

  enumerator I2S_ETM_TASK_MAX

    Maximum number of tasks

Was this page helpful?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.