mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-23 09:13:11 +00:00
doc/i2s: update i2s programming guide on s3 & c3
This commit is contained in:
@@ -1,24 +1,14 @@
|
||||
I2S
|
||||
===
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
.. warning::
|
||||
|
||||
This document is not updated for ESP32-C3 yet.
|
||||
{IDF_TARGET_I2S_NUM:default="two", esp32s2="one", esp32c3="one"}
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
I2S (Inter-IC Sound) is a serial, synchronous communication protocol that is usually used for transmitting audio data between two digital audio devices.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
{IDF_TARGET_NAME} contains two I2S peripherals. These peripherals can be configured to input and output sample data via the I2S driver.
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
{IDF_TARGET_NAME} contains one I2S peripheral. These peripherals can be configured to input and output sample data via the I2S driver.
|
||||
{IDF_TARGET_NAME} contains {IDF_TARGET_I2S_NUM} I2S peripheral(s). These peripherals can be configured to input and output sample data via the I2S driver.
|
||||
|
||||
An I2S bus consists of the following lines:
|
||||
|
||||
@@ -30,20 +20,22 @@ Each I2S controller has the following features that can be configured using the
|
||||
|
||||
- Operation as system master or slave
|
||||
- Capable of acting as transmitter or receiver
|
||||
- Dedicated DMA controller that allows for streaming sample data without requiring the CPU to copy each data sample
|
||||
- DMA controller that allows for streaming sample data without requiring the CPU to copy each data sample
|
||||
|
||||
Each controller can operate in half-duplex communication mode. Thus, the two controllers can be combined to establish full-duplex communication.
|
||||
|
||||
I2S0 output can be routed directly to the digital-to-analog converter's (DAC) output channels (GPIO 25 & GPIO 26) to produce direct analog output without involving any external I2S codecs. I2S0 can also be used for transmitting PDM (Pulse-density modulation) signals.
|
||||
|
||||
The I2S peripherals also support LCD mode for communicating data over a parallel bus, as used by some LCD displays and camera modules. LCD mode has the following operational modes:
|
||||
|
||||
- LCD master transmitting mode
|
||||
- Camera slave receiving mode
|
||||
- ADC/DAC mode
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
I2S0 output can be routed directly to the digital-to-analog converter's (DAC) output channels (GPIO 25 & GPIO 26) to produce direct analog output without involving any external I2S codecs. I2S0 can also be used for transmitting PDM (Pulse-density modulation) signals.
|
||||
|
||||
.. only:: esp32 or esp32s2
|
||||
|
||||
The I2S peripherals also support LCD mode for communicating data over a parallel bus, as used by some LCD displays and camera modules. LCD mode has the following operational modes:
|
||||
|
||||
- LCD master transmitting mode
|
||||
- Camera slave receiving mode
|
||||
- ADC/DAC mode
|
||||
|
||||
For more information, see *{IDF_TARGET_NAME} Technical Reference Manual* > *I2S Controller (I2S)* > LCD Mode [`PDF <{IDF_TARGET_TRM_EN_URL}#camlcdctrl>`__].
|
||||
|
||||
.. note::
|
||||
@@ -68,26 +60,50 @@ Install the I2S driver by calling the function :cpp:func`i2s_driver_install` and
|
||||
- The structure :cpp:type:`i2s_config_t` with defined communication parameters
|
||||
- Event queue size and handle
|
||||
|
||||
I2S will start automatically once :cpp:func`i2s_driver_install` returns ``ESP_OK``.
|
||||
|
||||
Configuration example:
|
||||
|
||||
.. code-block:: c
|
||||
.. only:: not SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
.. code-block:: c
|
||||
|
||||
static const i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0, // default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false
|
||||
};
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1, default 0
|
||||
};
|
||||
|
||||
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
|
||||
|
||||
.. only:: SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.bits_per_chan = I2S_BITS_PER_SAMPLE_16BIT
|
||||
};
|
||||
|
||||
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
|
||||
|
||||
Setting Communication Pins
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -100,15 +116,14 @@ Once the driver is installed, configure physical GPIO pins to which signals will
|
||||
.. code-block:: c
|
||||
|
||||
static const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 26,
|
||||
.ws_io_num = 25,
|
||||
.data_out_num = 22,
|
||||
.bck_io_num = 4,
|
||||
.ws_io_num = 5,
|
||||
.data_out_num = 18,
|
||||
.data_in_num = I2S_PIN_NO_CHANGE
|
||||
};
|
||||
|
||||
i2s_set_pin(i2s_num, &pin_config);
|
||||
|
||||
|
||||
Running I2S Communication
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -117,14 +132,17 @@ To perform a transmission:
|
||||
- Prepare the data for sending
|
||||
- Call the function :cpp:func:`i2s_write` and pass the data buffer address and data length to it
|
||||
|
||||
The function will write the data to the I2S DMA Tx buffer, and then the data will be transmitted automatically.
|
||||
The function will write the data to the DMA Tx buffer, and then the data will be transmitted automatically.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100);
|
||||
|
||||
To retrieve received data, use the function :cpp:func:`i2s_read`. It will retrieve the data from the DMA Rx buffer, once the data is received by the I2S controller.
|
||||
|
||||
To retrieve received data, use the function :cpp:func:`i2s_read`. It will retrieve the data from the I2S DMA Rx buffer, once the data is received by the I2S controller.
|
||||
.. code-block:: c
|
||||
|
||||
i2s_read(I2S_NUM, data_recv, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_read, 100);
|
||||
|
||||
You can temporarily stop the I2S driver by calling the function :cpp:func:`i2s_stop`, which will disable the I2S Tx/Rx units until the function :cpp:func:`i2s_start` is called. If the function :cpp:func`i2s_driver_install` is used, the driver will start up automatically eliminating the need to call :cpp:func:`i2s_start`.
|
||||
|
||||
@@ -140,87 +158,184 @@ Application Example
|
||||
|
||||
A code example for the I2S driver can be found in the directory :example:`peripherals/i2s`.
|
||||
|
||||
In addition, there are two short configuration examples for the I2S driver.
|
||||
.. only:: SOC_I2S_SUPPORTS_ADC_DAC
|
||||
|
||||
In addition, there are two short configuration examples for the I2S driver.
|
||||
|
||||
.. only:: not SOC_I2S_SUPPORTS_ADC_DAC
|
||||
|
||||
In addition, there is a short configuration examples for the I2S driver.
|
||||
|
||||
I2S configuration
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: c
|
||||
Example for general usage.
|
||||
|
||||
#include "driver/i2s.h"
|
||||
#include "freertos/queue.h"
|
||||
.. only:: not SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
.. code-block:: c
|
||||
|
||||
static const i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
#include "driver/i2s.h"
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.slot_bits_cfg = 16,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
},
|
||||
.intr_alloc_flags = 0, // default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false
|
||||
};
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1, default 0
|
||||
};
|
||||
|
||||
static const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 26,
|
||||
.ws_io_num = 25,
|
||||
.data_out_num = 22,
|
||||
.data_in_num = I2S_PIN_NO_CHANGE
|
||||
};
|
||||
|
||||
...
|
||||
static const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 4,
|
||||
.ws_io_num = 5,
|
||||
.data_out_num = 18,
|
||||
.data_in_num = I2S_PIN_NO_CHANGE
|
||||
};
|
||||
|
||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
|
||||
i2s_set_pin(i2s_num, &pin_config);
|
||||
|
||||
i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
...
|
||||
/* You can reset parameters by calling 'i2s_set_clk'
|
||||
*
|
||||
* The low 16 bits are the valid data bits in one chan and the high 16 bits are
|
||||
* the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will
|
||||
* be set to a same value as low 16 bits.
|
||||
*/
|
||||
uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2s_set_clk(i2s_num, 22050, bits_cfg, I2S_CHANNEL_STEREO);
|
||||
...
|
||||
|
||||
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
|
||||
.. only:: SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
Configuring I2S to use internal DAC for analog output
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. code-block:: c
|
||||
|
||||
.. code-block:: c
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#include "driver/i2s.h"
|
||||
#include "freertos/queue.h"
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
static const i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.slot_bits_cfg = 16, /* the DAC module will only take the 8bits from MSB */
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
},
|
||||
.intr_alloc_flags = 0, // default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false
|
||||
};
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64
|
||||
};
|
||||
|
||||
...
|
||||
static const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 4,
|
||||
.ws_io_num = 5,
|
||||
.data_out_num = 18,
|
||||
.data_in_num = I2S_PIN_NO_CHANGE
|
||||
};
|
||||
|
||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
i2s_set_pin(i2s_num, &pin_config);
|
||||
|
||||
i2s_set_pin(i2s_num, NULL); //for internal DAC, this will enable both of the internal channels
|
||||
|
||||
//You can call i2s_set_dac_mode to set built-in DAC output mode.
|
||||
//i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
||||
|
||||
i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
...
|
||||
/* You can reset parameters by calling 'i2s_set_clk'
|
||||
*
|
||||
* The low 16 bits are the valid data bits in one chan and the high 16 bits are
|
||||
* the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will
|
||||
* be set to a same value as low 16 bits.
|
||||
*/
|
||||
uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2s_set_clk(i2s_num, 22050, bits_cfg, I2S_CHANNEL_STEREO);
|
||||
...
|
||||
|
||||
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
|
||||
I2S on {IDF_TARGET_NAME} support TDM mode, up to 16 channels are available in TDM mode. If you want to use TDM mode, set field ``channel_format`` of :cpp:type:`i2s_config_t` to ``I2S_CHANNEL_FMT_TDM``. Then enable the channels by setting ``tdm_chan_cfg.chan_mask`` using masks in :cpp:type:`i2s_channel_t`, the number of active channels and total channels will be calculate automatically. Also you can set a particular total channel number for it, but it shouldn't be smaller than the largest channel you use.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "driver/i2s.h"
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_TDM,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH2
|
||||
};
|
||||
|
||||
static const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 4,
|
||||
.ws_io_num = 5,
|
||||
.data_out_num = 18,
|
||||
.data_in_num = I2S_PIN_NO_CHANGE
|
||||
};
|
||||
|
||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
i2s_set_pin(i2s_num, &pin_config);
|
||||
|
||||
...
|
||||
/* You can reset parameters by calling 'i2s_set_clk'
|
||||
*
|
||||
* The low 16 bits are the valid data bits in one chan and the high 16 bits are
|
||||
* the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will
|
||||
* be set to a same value as low 16 bits.
|
||||
*/
|
||||
uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2s_set_clk(i2s_port_t i2s_num, 22050, bits_cfg, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1); // set clock
|
||||
...
|
||||
|
||||
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
|
||||
.. only:: SOC_I2S_SUPPORTS_ADC_DAC
|
||||
|
||||
Configuring I2S to use internal DAC for analog output
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "driver/i2s.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
static const i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = 16, /* the DAC module will only take the 8bits from MSB */
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.intr_alloc_flags = 0, // default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
|
||||
i2s_set_pin(i2s_num, NULL); //for internal DAC, this will enable both of the internal channels
|
||||
|
||||
//You can call i2s_set_dac_mode to set built-in DAC output mode.
|
||||
//i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
||||
|
||||
i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
|
||||
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
Reference in New Issue
Block a user