I2S¶
Overview¶
I2S (Inter-IC Sound) is a serial, synchronous communication protocol that is usually used for transmitting audio data between two digital audio devices.
ESP32 integrates two I2S controllers, referred to as I2S0 and I2S1, both of which can be used for streaming audio and video digital data.
An I2S bus consists of the following lines:
- Bit clock line
- Channel select line
- Serial data line
Each I2S controller has the following features that can be configured using the I2S driver:
- 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
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
For more information, see the ESP32 Technical Reference Manual.
Note
For high accuracy clock applications, use the APLL_CLK clock source, which has the frequency range of 16 ~ 128 MHz. You can enable the APLL_CLK clock source by setting i2s_config_t::use_apll
to TRUE
.
If i2s_config_t::use_apll
= TRUE
and i2s_config_t::fixed_mclk
> 0
, then the master clock output frequency for I2S will be equal to the value of i2s_config_t::fixed_mclk
, which means that the mclk frequency is provided by the user, instead of being calculated by the driver.
The clock rate of the word select line, which is called audio left-right clock rate (LRCK) here, is always the divisor of the master clock output frequency and for which the following is always true: 0 < MCLK/LRCK/channels/bits_per_sample < 64.
Functional Overview¶
Installing the Driver¶
Install the I2S driver by calling the function :cpp:func`i2s_driver_install` and passing the following arguments:
- Port number
- The structure
i2s_config_t
with defined communication parameters - Event queue size and handle
Configuration example:
static const int i2s_num = 0; // i2s port number
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_I2S | I2S_COMM_FORMAT_I2S_MSB,
.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);
Setting Communication Pins¶
Once the driver is installed, configure physical GPIO pins to which signals will be routed. For this, call the function :cpp:func`i2s_set_pin` and pass the following arguments to it:
- Port number
- The structure
i2s_pin_config_t
defining the GPIO pin numbers to which the driver should route the BCK, WS, DATA out, and DATA in signals. If you want to keep a currently allocated pin number for a specific signal, or if this signal is unused, then pass the macroI2S_PIN_NO_CHANGE
. See the example below.
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
};
i2s_set_pin(i2s_num, &pin_config);
Running I2S Communication¶
To perform a transmission:
- Prepare the data for sending
- Call the function
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.
i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100);
To retrieve received data, use the function i2s_read()
. It will retrieve the data from the I2S DMA Rx buffer, once the data is received by the I2S controller.
You can temporarily stop the I2S driver by calling the function i2s_stop()
, which will disable the I2S Tx/Rx units until the function 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 i2s_start()
.
Deleting the Driver¶
If the established communication is no longer required, the driver can be removed to free allocated resources by calling i2s_driver_uninstall()
.
Application Example¶
A code example for the I2S driver can be found in the directory peripherals/i2s.
In addition, there are two short configuration examples for the I2S driver.
I2S configuration¶
#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,
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = 0, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false
};
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
};
...
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
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
Configuring I2S to use internal DAC for analog output¶
#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,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.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¶
Header File¶
Functions¶
-
esp_err_t
i2s_set_pin
(i2s_port_t i2s_num, const i2s_pin_config_t *pin)¶ Set I2S pin number.
Inside the pin configuration structure, set I2S_PIN_NO_CHANGE for any pin where the current configuration should not be changed.
- Note
- The I2S peripheral output signals can be connected to multiple GPIO pads. However, the I2S peripheral input signal can only be connected to one GPIO pad.
- Parameters
i2s_num
: I2S_NUM_0 or I2S_NUM_1pin
: I2S Pin structure, or NULL to set 2-channel 8-bit internal DAC pin configuration (GPIO25 & GPIO26)
- Note
- if *pin is set as NULL, this function will initialize both of the built-in DAC channels by default. if you don’t want this to happen and you want to initialize only one of the DAC channels, you can call i2s_set_dac_mode instead.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL IO error
-
esp_err_t
i2s_set_dac_mode
(i2s_dac_mode_t dac_mode)¶ Set I2S dac mode, I2S built-in DAC is disabled by default.
- Note
- Built-in DAC functions are only supported on I2S0 for current ESP32 chip. If either of the built-in DAC channel are enabled, the other one can not be used as RTC DAC function at the same time.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
dac_mode
: DAC mode configurations - see i2s_dac_mode_t
-
esp_err_t
i2s_driver_install
(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue)¶ Install and start I2S driver.
This function must be called before any I2S driver read/write operations.
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1i2s_config
: I2S configurations - see i2s_config_t structqueue_size
: I2S event queue size/depth.i2s_queue
: I2S event queue handle, if set NULL, driver will not use an event queue.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NO_MEM Out of memory
-
esp_err_t
i2s_driver_uninstall
(i2s_port_t i2s_num)¶ Uninstall I2S driver.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
-
esp_err_t
i2s_write
(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait)¶ Write data to I2S DMA transmit buffer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1src
: Source address to write fromsize
: Size of data in bytesbytes_written
: Number of bytes written, if timeout, the result will be less than the size passed in.ticks_to_wait
: TX buffer wait timeout in RTOS ticks. If this many ticks pass without space becoming available in the DMA transmit buffer, then the function will return (note that if the data is written to the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
-
esp_err_t
i2s_write_expand
(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)¶ Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM.
Format of the data in source buffer is determined by the I2S configuration (see
i2s_config_t).- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1src
: Source address to write fromsize
: Size of data in bytessrc_bits
: Source audio bitaim_bits
: Bit wanted, no more than 32, and must be greater than src_bitsbytes_written
: Number of bytes written, if timeout, the result will be less than the size passed in.ticks_to_wait
: TX buffer wait timeout in RTOS ticks. If this many ticks pass without space becoming available in the DMA transmit buffer, then the function will return (note that if the data is written to the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t
i2s_read
(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)¶ Read data from I2S DMA receive buffer.
- Note
- If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process, to prevent the data getting corrupted.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1dest
: Destination address to read intosize
: Size of data in bytesbytes_read
: Number of bytes read, if timeout, bytes read will be less than the size passed in.ticks_to_wait
: RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
-
esp_err_t
i2s_set_sample_rates
(i2s_port_t i2s_num, uint32_t rate)¶ Set sample rate used for I2S RX and TX.
The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample).
bit_clock = rate * (number of channels) * bits_per_sample
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NO_MEM Out of memory
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1rate
: I2S sample rate (ex: 8000, 44100…)
-
esp_err_t
i2s_stop
(i2s_port_t i2s_num)¶ Stop I2S driver.
There is no need to call i2s_stop() before calling i2s_driver_uninstall().
Disables I2S TX/RX, until i2s_start() is called.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
-
esp_err_t
i2s_start
(i2s_port_t i2s_num)¶ Start I2S driver.
It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop().
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
-
esp_err_t
i2s_zero_dma_buffer
(i2s_port_t i2s_num)¶ Zero the contents of the TX DMA buffer.
Pushes zero-byte samples into the TX DMA buffer, until it is full.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
-
esp_err_t
i2s_set_clk
(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch)¶ Set clock & bit width used for I2S RX and TX.
Similar to i2s_set_sample_rates(), but also sets bit width.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NO_MEM Out of memory
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1rate
: I2S sample rate (ex: 8000, 44100…)bits
: I2S bit width (I2S_BITS_PER_SAMPLE_16BIT, I2S_BITS_PER_SAMPLE_24BIT, I2S_BITS_PER_SAMPLE_32BIT)ch
: I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO)
-
float
i2s_get_clk
(i2s_port_t i2s_num)¶ get clock set on particular port number.
- Return
- actual clock set by i2s driver
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
-
esp_err_t
i2s_set_adc_mode
(adc_unit_t adc_unit, adc1_channel_t adc_channel)¶ Set built-in ADC mode for I2S DMA, this function will initialize ADC pad, and set ADC parameters.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
adc_unit
: SAR ADC unit indexadc_channel
: ADC channel index
-
esp_err_t
i2s_adc_enable
(i2s_port_t i2s_num)¶ Start to use I2S built-in ADC mode.
- Note
- This function would acquire the lock of ADC to prevent the data getting corrupted during the I2S peripheral is being used to do fully continuous ADC sampling.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_INVALID_STATE Driver state error
- Parameters
i2s_num
: i2s port index
Type Definitions¶
-
typedef intr_handle_t
i2s_isr_handle_t
¶