From ab6311c54896a7e470d91a7b217d675672aebe35 Mon Sep 17 00:00:00 2001 From: Kirill Chalov Date: Mon, 18 Nov 2019 21:13:37 +0800 Subject: [PATCH] Reveiw the file api-reference/peripherals/i2s.rst --- components/driver/include/driver/i2s.h | 2 + docs/en/api-reference/peripherals/i2s.rst | 172 ++++++++++++++++++---- 2 files changed, 145 insertions(+), 29 deletions(-) diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 40b786bc8..11ab03caa 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -226,6 +226,8 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate); /** * @brief 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. * * @param i2s_num I2S_NUM_0, I2S_NUM_1 diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index 335d6cb2d..90add3dee 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -4,26 +4,135 @@ I2S Overview -------- -ESP32 contains two I2S peripherals. These peripherals can be configured to input and output sample data via the I2S driver. +I2S (Inter-IC Sound) is a serial, synchronous communication protocol that is usually used for transmitting audio data between two digital audio devices. -The I2S peripheral supports DMA meaning it can stream sample data without requiring each sample to be read or written by the CPU. +ESP32 integrates two I2S controllers, referred to as I2S0 and I2S1, both of which can be used for streaming audio and video digital data. -I2S output can also be routed directly to the Digital/Analog Converter output channels (GPIO 25 & GPIO 26) to produce analog output directly, rather than via an external I2S codec. +An I2S bus consists of the following lines: -.. note:: For high accuracy clock applications, APLL clock source can be used with `.use_apll = true` and ESP32 will automatically calculate APLL parameter. +- 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 :cpp:member:`i2s_config_t::use_apll` to ``TRUE``. + + If :cpp:member:`i2s_config_t::use_apll` = ``TRUE`` and :cpp:member:`i2s_config_t::fixed_mclk` > ``0``, then the master clock output frequency for I2S will be equal to the value of :cpp:member:`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 :cpp:type:`i2s_config_t` with defined communication parameters +- Event queue size and handle + +Configuration example: + +.. code-block:: c + + 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 :cpp:type:`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 macro :c:macro:`I2S_PIN_NO_CHANGE`. See the example below. + +.. code-block:: c + + 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 :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. + +.. 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 I2S DMA Rx buffer, once the data is received by the I2S controller. + +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`. + + +Deleting the Driver +^^^^^^^^^^^^^^^^^^^ + +If the established communication is no longer required, the driver can be removed to free allocated resources by calling :cpp:func:`i2s_driver_uninstall`. -.. note:: If `use_apll = true` and `fixed_mclk > 0`, then the Master clock output for I2S is fixed and equal to the fixed_mclk value. The audio clock rate (LRCK) is always the MCLK divisor and 0 < MCLK/LRCK/channels/bits_per_sample < 64 Application Example ------------------- -A full I2S example is available in esp-idf: :example:`peripherals/i2s`. +A code example for the I2S driver can be found in the directory :example:`peripherals/i2s`. -Short example of I2S configuration: +In addition, there are two short configuration examples for the I2S driver. -.. highlight:: c -:: +I2S configuration +^^^^^^^^^^^^^^^^^ + +.. code-block:: c #include "driver/i2s.h" #include "freertos/queue.h" @@ -31,15 +140,15 @@ Short example of I2S configuration: 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 + .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 = { @@ -59,7 +168,11 @@ Short example of I2S configuration: i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver -Short example configuring I2S to use internal DAC for analog output:: + +Configuring I2S to use internal DAC for analog output +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c #include "driver/i2s.h" #include "freertos/queue.h" @@ -67,15 +180,15 @@ Short example configuring I2S to use internal DAC for analog output:: 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 + .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 }; ... @@ -83,7 +196,7 @@ Short example configuring I2S to use internal DAC for analog output:: 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); @@ -91,6 +204,7 @@ Short example configuring I2S to use internal DAC for analog output:: i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver + API Reference -------------