mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 06:04:33 +02:00
doc/i2s: update i2s programming guide on s3 & c3
This commit is contained in:
@@ -14,12 +14,13 @@
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "soc/lldesc.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
#include "driver/dac.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
#include "adc1_private.h"
|
||||
#endif
|
||||
|
||||
@@ -138,22 +139,6 @@ static void gpio_matrix_in_check_and_set(int gpio, uint32_t signal_idx, bool inv
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
esp_err_t i2s_pcm_config(i2s_port_t i2s_num, i2s_mode_t mode, i2s_pcm_mode_t pcm_cfg)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
|
||||
|
||||
if (mode & I2S_MODE_TX) {
|
||||
i2s_hal_tx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg);
|
||||
} else if (mode & I2S_MODE_RX) {
|
||||
i2s_hal_rx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
float i2s_get_clk(i2s_port_t i2s_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
|
||||
@@ -428,7 +413,6 @@ static esp_err_t i2s_fbclk_cal(int i2s_num, uint32_t rate, int channel, int chan
|
||||
}
|
||||
#endif // SOC_I2S_SUPPORTS_ADC_DAC
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
if ( p_i2s[i2s_num]->mode & I2S_MODE_PDM) {
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
if ( p_i2s[i2s_num]->mode & I2S_MODE_TX) {
|
||||
@@ -447,7 +431,6 @@ static esp_err_t i2s_fbclk_cal(int i2s_num, uint32_t rate, int channel, int chan
|
||||
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||
_bck_div = 8;
|
||||
}
|
||||
#endif // SOC_I2S_SUPPORTS_PDM
|
||||
|
||||
#if SOC_I2S_SUPPORTS_APLL
|
||||
int sdm0 = 0;
|
||||
@@ -487,7 +470,7 @@ static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg)
|
||||
case I2S_CHANNEL_FMT_TDM: {
|
||||
uint32_t num = 0;
|
||||
uint32_t max_chan = 0;
|
||||
uint32_t chan_mask = hal_cfg->chan_cfg.chan_mask;
|
||||
uint32_t chan_mask = hal_cfg->chan_mask;
|
||||
|
||||
for (int i = 0; chan_mask && i < 16; i++, chan_mask >>= 1) {
|
||||
if ((chan_mask & 0x01) == 1) {
|
||||
@@ -495,10 +478,9 @@ static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg)
|
||||
max_chan = i + 1;
|
||||
}
|
||||
}
|
||||
if (max_chan > hal_cfg->chan_cfg.total_chan) {
|
||||
hal_cfg->chan_cfg.total_chan = max_chan;
|
||||
if (max_chan > hal_cfg->total_chan) {
|
||||
hal_cfg->total_chan = max_chan;
|
||||
}
|
||||
hal_cfg->chan_cfg.active_chan = num;
|
||||
return num;
|
||||
}
|
||||
#endif
|
||||
@@ -514,9 +496,9 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
|
||||
|
||||
i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg;
|
||||
int data_bits = 0;
|
||||
int slot_bits = 0;
|
||||
int active_slot_num = 0;
|
||||
int slot_num = 0;
|
||||
int chan_bits = 0;
|
||||
int active_chan_num = 0;
|
||||
int chan_num = 0;
|
||||
|
||||
cfg->ch = ch;
|
||||
cfg->sample_rate = rate;
|
||||
@@ -524,16 +506,16 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
|
||||
|
||||
cfg->bits_cfg.chan_bits = cfg->bits_cfg.chan_bits < cfg->bits_cfg.sample_bits ?
|
||||
cfg->bits_cfg.sample_bits : cfg->bits_cfg.chan_bits;
|
||||
slot_bits = cfg->bits_cfg.chan_bits;
|
||||
chan_bits = cfg->bits_cfg.chan_bits;
|
||||
data_bits = cfg->bits_cfg.sample_bits;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
cfg->chan_cfg.chan_mask = ch & 0xFFFF;
|
||||
active_slot_num = i2s_get_active_chan_num(cfg);
|
||||
slot_num = cfg->chan_cfg.total_chan;
|
||||
cfg->chan_mask = ch & 0xFFFF;
|
||||
active_chan_num = i2s_get_active_chan_num(cfg);
|
||||
chan_num = cfg->total_chan;
|
||||
#else
|
||||
active_slot_num = i2s_get_active_chan_num(cfg);
|
||||
slot_num = ch == I2S_CHANNEL_MONO ? 2 : active_slot_num;
|
||||
active_chan_num = i2s_get_active_chan_num(cfg);
|
||||
chan_num = ch == I2S_CHANNEL_MONO ? 2 : active_chan_num;
|
||||
#endif
|
||||
ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
|
||||
|
||||
@@ -551,7 +533,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
|
||||
xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
|
||||
}
|
||||
//malloc DMA buffer
|
||||
if (i2s_alloc_dma_buffer(i2s_num, data_bits, active_slot_num) != ESP_OK ) {
|
||||
if (i2s_alloc_dma_buffer(i2s_num, data_bits, active_chan_num) != ESP_OK ) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -559,13 +541,13 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
|
||||
uint32_t i2s_bck = 0; // I2S back clock
|
||||
uint32_t bck_div = 0; // I2S bck div
|
||||
//calculate bck_div, f_bck and select source clock
|
||||
if (i2s_fbclk_cal(i2s_num, rate, slot_num, slot_bits, &i2s_clk, &i2s_bck, &bck_div) != ESP_OK) {
|
||||
if (i2s_fbclk_cal(i2s_num, rate, chan_num, chan_bits, &i2s_clk, &i2s_bck, &bck_div) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
//configure i2s clock
|
||||
if (p_i2s[i2s_num]->mode & I2S_MODE_TX) {
|
||||
i2s_hal_tx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div);
|
||||
i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), slot_bits, data_bits);
|
||||
i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits);
|
||||
// wait all writing on-going finish
|
||||
if (p_i2s[i2s_num]->tx) {
|
||||
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
|
||||
@@ -573,7 +555,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
|
||||
}
|
||||
if (p_i2s[i2s_num]->mode & I2S_MODE_RX) {
|
||||
i2s_hal_rx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div);
|
||||
i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), slot_bits, data_bits);
|
||||
i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits);
|
||||
// wait all writing on-going finish
|
||||
if (p_i2s[i2s_num]->rx) {
|
||||
xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
|
||||
@@ -1002,11 +984,9 @@ static esp_err_t i2s_check_cfg_static(i2s_port_t i2s_num)
|
||||
ESP_RETURN_ON_FALSE(!((cfg->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), ESP_ERR_INVALID_ARG, TAG, "I2S DAC built-in only support on I2S0");
|
||||
return ESP_OK;
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
//We only check if the I2S number is invalid when set to PDM mode.
|
||||
ESP_RETURN_ON_FALSE(!((cfg->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), ESP_ERR_INVALID_ARG, TAG, "I2S DAC PDM only support on I2S0");
|
||||
return ESP_OK;
|
||||
#endif
|
||||
|
||||
ESP_RETURN_ON_FALSE(cfg->comm_fmt && (cfg->comm_fmt < I2S_COMM_FORMAT_STAND_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid communication formats");
|
||||
ESP_RETURN_ON_FALSE(!((cfg->comm_fmt & I2S_COMM_FORMAT_STAND_MSB) && (cfg->comm_fmt & I2S_COMM_FORMAT_STAND_PCM_LONG)), ESP_ERR_INVALID_ARG, TAG, "multiple communication formats specified");
|
||||
@@ -1096,29 +1076,30 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
p_i2s[i2s_num]->hal_cfg.comm_fmt = i2s_config->communication_format;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_fmt = i2s_config->channel_format;
|
||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.sample_bits = i2s_config->bits_per_sample;
|
||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.chan_bits = i2s_config->bits_per_slot;
|
||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.chan_bits = i2s_config->bits_per_chan;
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
int active_chan = 0;
|
||||
switch (i2s_config->channel_format) {
|
||||
case I2S_CHANNEL_FMT_RIGHT_LEFT:
|
||||
case I2S_CHANNEL_FMT_ALL_RIGHT:
|
||||
case I2S_CHANNEL_FMT_ALL_LEFT:
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.active_chan = 2;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.total_chan = 2;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1;
|
||||
p_i2s[i2s_num]->hal_cfg.total_chan = 2;
|
||||
active_chan = 2;
|
||||
break;
|
||||
case I2S_CHANNEL_FMT_ONLY_RIGHT:
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.chan_mask = i2s_config->tdm_flags.left_align_en ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.active_chan = 1;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.total_chan = 1;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->tdm_flags.left_align_en ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0;
|
||||
p_i2s[i2s_num]->hal_cfg.total_chan = 1;
|
||||
active_chan = 1;
|
||||
break;
|
||||
case I2S_CHANNEL_FMT_ONLY_LEFT:
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.chan_mask = i2s_config->tdm_flags.left_align_en ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.active_chan = 1;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.total_chan = 1;
|
||||
p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->tdm_flags.left_align_en ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1;
|
||||
p_i2s[i2s_num]->hal_cfg.total_chan = 1;
|
||||
active_chan = 1;
|
||||
break;
|
||||
case I2S_CHANNEL_FMT_TDM:
|
||||
ESP_RETURN_ON_FALSE((i2s_config->tdm_chan_cfg.chan_mask != 0), ESP_ERR_INVALID_ARG, TAG, "i2s all channel are disabled");
|
||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.chan_mask = i2s_config->tdm_chan_cfg.chan_mask;
|
||||
ESP_RETURN_ON_FALSE((i2s_config->chan_mask != 0), ESP_ERR_INVALID_ARG, TAG, "i2s all channel are disabled");
|
||||
p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->chan_mask;
|
||||
i2s_get_active_chan_num(&p_i2s[i2s_num]->hal_cfg);
|
||||
break;
|
||||
default:
|
||||
@@ -1138,6 +1119,18 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
p_i2s[i2s_num]->dma_buf_count = i2s_config->dma_buf_count;
|
||||
p_i2s[i2s_num]->dma_buf_len = i2s_config->dma_buf_len;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
// Set PCM compress type for PCM communication mode
|
||||
if (p_i2s[i2s_num]->communication_format & I2S_COMM_FORMAT_STAND_PCM_SHORT) {
|
||||
if (p_i2s[i2s_num]->mode & I2S_MODE_TX) {
|
||||
i2s_hal_tx_pcm_cfg(&(p_i2s[i2s_num]->hal), i2s_config->pcm_compress_type);
|
||||
}
|
||||
if (p_i2s[i2s_num]->mode & I2S_MODE_RX) {
|
||||
i2s_hal_rx_pcm_cfg(&(p_i2s[i2s_num]->hal), i2s_config->pcm_compress_type);
|
||||
}
|
||||
}
|
||||
#endif // SOC_I2S_SUPPORTS_PCM
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (i2s_config->use_apll) {
|
||||
ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock);
|
||||
@@ -1198,7 +1191,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
ret = i2s_set_clk(i2s_num, i2s_config->sample_rate,
|
||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.val,
|
||||
(i2s_channel_t)p_i2s[i2s_num]->hal_cfg.chan_cfg.active_chan);
|
||||
(i2s_channel_t)active_chan);
|
||||
#else
|
||||
ret = i2s_set_clk(i2s_num, i2s_config->sample_rate,
|
||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.val,
|
||||
|
@@ -13,9 +13,7 @@
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
#include "hal/i2s_types.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
@@ -50,9 +48,15 @@ typedef struct {
|
||||
int data_in_num; /*!< DATA in pin*/
|
||||
} i2s_pin_config_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
typedef i2s_hal_chan_cfg_t tdm_chan_cfg_t;
|
||||
typedef i2s_hal_tdm_flags_t tdm_flags_t;
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief I2S PCM configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_pcm_compress_t pcm_mode; /*!< I2S PCM a/u-law decompress or compress mode */
|
||||
} i2s_pcm_cfg_t;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -72,15 +76,30 @@ typedef struct {
|
||||
bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */
|
||||
bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */
|
||||
int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value.*/
|
||||
i2s_bits_per_slot_t bits_per_slot; /*!< I2S total bits in one channel, Should not be smaller than 'bits_per_sample', default '0' means equal to 'bits_per_sample' */
|
||||
i2s_bits_per_chan_t bits_per_chan; /*!< I2S total bits in one channel, Should not be smaller than 'bits_per_sample', default '0' means equal to 'bits_per_sample' */
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
i2s_pcm_compress_t pcm_compress_type; /*!< I2S PCM a/u-law decompress or compress mode. Set this field if `communication_format` is set to `I2S_COMM_FORMAT_STAND_PCM_SHORT` or `I2S_COMM_FORMAT_STAND_PCM_LONG` */
|
||||
#endif // SOC_I2S_SUPPORTS_PCM
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
tdm_chan_cfg_t tdm_chan_cfg; /*!< I2S TDM channel configurations*/
|
||||
tdm_flags_t tdm_flags; /*!< I2S TDM flags*/
|
||||
#endif
|
||||
i2s_channel_t chan_mask; /*!< I2S active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<<total_chan). */
|
||||
uint32_t total_chan; /*!< I2S Total number of channels. If it is smaller than the biggest active channel number, it will be set to this number automatically. */
|
||||
union {
|
||||
struct {
|
||||
uint32_t left_align_en : 1; /*!< Set to enable left aligment */
|
||||
uint32_t big_edin_en : 1; /*!< Set to enable big edin */
|
||||
uint32_t bit_order_msb_en : 1; /*!< Set to enable msb order */
|
||||
uint32_t skip_msk_en : 1; /*!< Set to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
|
||||
};
|
||||
uint32_t val; /*!< TDM flag value*/
|
||||
} tdm_flags; /*!< I2S TDM flags*/
|
||||
#endif // SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
} i2s_driver_config_t;
|
||||
|
||||
typedef i2s_driver_config_t i2s_config_t;
|
||||
typedef intr_handle_t i2s_isr_handle_t;
|
||||
typedef i2s_driver_config_t i2s_config_t; // for backward compatible
|
||||
typedef intr_handle_t i2s_isr_handle_t; // for backward compatible
|
||||
|
||||
/**
|
||||
* @brief I2S event queue types
|
||||
@@ -340,23 +359,6 @@ esp_err_t i2s_start(i2s_port_t i2s_num);
|
||||
*/
|
||||
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief Configure I2S a/u-law decompress or compress
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0
|
||||
*
|
||||
* @param mode I2S mode. I2S_MODE_TX, I2S_MODE_RX
|
||||
*
|
||||
* @param pcm_cfg a/u-law decompress or compress configuration paramater
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_pcm_config(i2s_port_t i2s_num, i2s_mode_t mode, i2s_pcm_mode_t pcm_cfg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set clock & bit width used for I2S RX and TX.
|
||||
*
|
||||
@@ -373,7 +375,7 @@ esp_err_t i2s_pcm_config(i2s_port_t i2s_num, i2s_mode_t mode, i2s_pcm_mode_t pcm
|
||||
*
|
||||
* @param bits_cfg I2S bits configuation
|
||||
* the low 16 bits is for data bits per sample in one channel (see 'i2s_bits_per_sample_t')
|
||||
* the high 16 bits is for total bits in one channel (see 'i2s_bits_per_slot_t')
|
||||
* the high 16 bits is for total bits in one channel (see 'i2s_bits_per_chan_t')
|
||||
*
|
||||
* @param ch I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO)
|
||||
*
|
||||
|
@@ -232,7 +232,7 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
}
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
|
||||
#if SOC_I2S_NUM > 1
|
||||
/* ESP32S2 and ESP32C3 has only single I2S port and hence following test cases are not applicable */
|
||||
TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
{
|
||||
@@ -492,7 +492,7 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
TEST_ASSERT(initial_size == esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
#if DISABLED_FOR_TARGETS(ESP32)
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
/* Only ESP32 need I2S adc/dac test */
|
||||
TEST_CASE("I2S adc test", "[i2s]")
|
||||
{
|
||||
|
@@ -14,13 +14,13 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"spi_hal_iram.c"
|
||||
"spi_slave_hal.c"
|
||||
"spi_slave_hal_iram.c"
|
||||
"i2s_hal.c"
|
||||
"sigmadelta_hal.c"
|
||||
"timer_hal.c"
|
||||
"ledc_hal.c"
|
||||
"ledc_hal_iram.c"
|
||||
"i2c_hal.c"
|
||||
"i2c_hal_iram.c"
|
||||
"i2s_hal.c"
|
||||
"gpio_hal.c"
|
||||
"uart_hal.c"
|
||||
"uart_hal_iram.c"
|
||||
|
@@ -453,10 +453,10 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure TX slot bit and audio data bit, on ESP32, sample_bit should equals to data_bit
|
||||
* @brief Congfigure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
@@ -466,10 +466,10 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure RX slot bit and audio data bit, on ESP32, sample_bit should equals to data_bit
|
||||
* @brief Congfigure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
|
@@ -28,7 +28,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define I2S_LL_GET_HW(num) (&I2S0)
|
||||
|
||||
#define I2S_LL_TDM_CH_MASK (0xffff)
|
||||
@@ -320,10 +319,10 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure TX slot bit and audio data bit
|
||||
* @brief Congfigure TX chan bit and audio data bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
@@ -333,10 +332,10 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure RX slot bit and audio data bit
|
||||
* @brief Congfigure RX chan bit and audio data bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
@@ -390,52 +389,52 @@ static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure TX total slot number
|
||||
* @brief Configure TX total chan number
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
* @param total_num Total chan number
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure RX total slot number
|
||||
* @brief Configure RX total chan number
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
* @param total_num Total chan number
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the bimap of the active TX slot, only the active slot can launch audio data.
|
||||
* @brief Set the bimap of the active TX chan, only the active chan can launch audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param slot_mask mask of tx active slot
|
||||
* @param chan_mask mask of tx active chan
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask)
|
||||
{
|
||||
typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the bimap of the active RX slot, only the active slot can receive audio data.
|
||||
* @brief Set the bimap of the active RX chan, only the active chan can receive audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param slot_mask mask of rx active slot
|
||||
* @param chan_mask mask of rx active chan
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask)
|
||||
{
|
||||
typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
@@ -556,7 +555,7 @@ static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->tx_conf.tx_pcm_bypass = 1;
|
||||
@@ -572,7 +571,7 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->rx_conf.rx_pcm_bypass = 1;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -448,10 +448,10 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t eof_num)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure TX slot bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit
|
||||
* @brief Congfigure TX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
@@ -461,10 +461,10 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure RX slot bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit
|
||||
* @brief Congfigure RX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
|
@@ -322,10 +322,10 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure TX slot bit and audio data bit
|
||||
* @brief Congfigure TX chan bit and audio data bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
@@ -335,10 +335,10 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Congfigure RX slot bit and audio data bit
|
||||
* @brief Congfigure RX chan bit and audio data bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_bit The slot bit width
|
||||
* @param sample_bit The chan bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
@@ -392,52 +392,52 @@ static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure TX total slot number
|
||||
* @brief Configure TX total chan number
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
* @param total_num Total chan number
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure RX total slot number
|
||||
* @brief Configure RX total chan number
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
* @param total_num Total chan number
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the bimap of the active TX slot, only the active slot can launch audio data.
|
||||
* @brief Set the bimap of the active TX chan, only the active chan can launch audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param slot_mask mask of tx active slot
|
||||
* @param chan_mask mask of tx active chan
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask)
|
||||
{
|
||||
typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the bimap of the active RX slot, only the active slot can receive audio data.
|
||||
* @brief Set the bimap of the active RX chan, only the active chan can receive audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param slot_mask mask of rx active slot
|
||||
* @param chan_mask mask of rx active chan
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask)
|
||||
{
|
||||
typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ static inline void i2s_ll_get_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->tx_conf.tx_pcm_bypass = 1;
|
||||
@@ -604,7 +604,7 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->rx_conf.rx_pcm_bypass = 1;
|
||||
|
@@ -148,14 +148,14 @@ static void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_hal_config_t
|
||||
}
|
||||
}
|
||||
#else
|
||||
int slot_bits = hal_cfg->bits_cfg.chan_bits;
|
||||
int slot_num = hal_cfg->chan_cfg.total_chan;
|
||||
int chan_bits = hal_cfg->bits_cfg.chan_bits;
|
||||
int chan_num = hal_cfg->total_chan;
|
||||
bool msb_shift_en = false;
|
||||
int tdm_ws_width = 0;
|
||||
switch (hal_cfg->comm_fmt) {
|
||||
case I2S_COMM_FORMAT_STAND_MSB:
|
||||
msb_shift_en = false;
|
||||
tdm_ws_width = slot_num * slot_bits / 2;
|
||||
tdm_ws_width = chan_num * chan_bits / 2;
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
|
||||
msb_shift_en = false;
|
||||
@@ -163,22 +163,22 @@ static void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_hal_config_t
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
||||
msb_shift_en = false;
|
||||
tdm_ws_width = slot_bits;
|
||||
tdm_ws_width = chan_bits;
|
||||
break;
|
||||
default: //I2S_COMM_FORMAT_STAND_I2S
|
||||
msb_shift_en = true;
|
||||
tdm_ws_width = slot_num * slot_bits / 2;
|
||||
tdm_ws_width = chan_num * chan_bits / 2;
|
||||
break;
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_tx_msb_shift_enable(hal->dev, msb_shift_en);
|
||||
i2s_ll_set_tx_tdm_ws_width(hal->dev, tdm_ws_width);
|
||||
i2s_ll_set_tx_half_sample_bit(hal->dev, slot_num * slot_bits / 2);
|
||||
i2s_ll_set_tx_half_sample_bit(hal->dev, chan_num * chan_bits / 2);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_msb_shift_enable(hal->dev, msb_shift_en);
|
||||
i2s_ll_set_rx_tdm_ws_width(hal->dev, tdm_ws_width);
|
||||
i2s_ll_set_rx_half_sample_bit(hal->dev, slot_num * slot_bits / 2);
|
||||
i2s_ll_set_rx_half_sample_bit(hal->dev, chan_num * chan_bits / 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -186,23 +186,23 @@ static void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_hal_config_t
|
||||
void i2s_hal_samples_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
||||
{
|
||||
int data_bits = hal_cfg->bits_cfg.sample_bits;
|
||||
int slot_bits = hal_cfg->bits_cfg.chan_bits;
|
||||
int chan_bits = hal_cfg->bits_cfg.chan_bits;
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
int slot_num = hal_cfg->chan_cfg.total_chan;
|
||||
int chan_num = hal_cfg->total_chan;
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_slot_num(hal->dev, slot_num);
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
i2s_ll_set_tx_chan_num(hal->dev, chan_num);
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, chan_bits, data_bits);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_slot_num(hal->dev, slot_num);
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
i2s_ll_set_rx_chan_num(hal->dev, chan_num);
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, chan_bits, data_bits);
|
||||
}
|
||||
#else
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, chan_bits, data_bits);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, chan_bits, data_bits);
|
||||
}
|
||||
#endif
|
||||
//I2S standards config: Philip, MSB or PCM, Only I2S mode should do this configuration.
|
||||
@@ -224,7 +224,7 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
||||
i2s_ll_set_tx_clk_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
|
||||
i2s_ll_mclk_use_tx_clk(hal->dev);
|
||||
|
||||
i2s_ll_set_tx_active_slot_mask(hal->dev, hal_cfg->chan_cfg.chan_mask);
|
||||
i2s_ll_set_tx_active_chan_mask(hal->dev, hal_cfg->chan_mask);
|
||||
i2s_ll_tx_left_align_enable(hal->dev, hal_cfg->flags.left_align_en);
|
||||
i2s_ll_tx_big_endian_enable(hal->dev, hal_cfg->flags.big_edin_en);
|
||||
i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->flags.bit_order_msb_en);
|
||||
@@ -247,7 +247,7 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
||||
i2s_ll_set_rx_clk_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
|
||||
i2s_ll_mclk_use_rx_clk(hal->dev);
|
||||
|
||||
i2s_ll_set_rx_active_slot_mask(hal->dev, hal_cfg->chan_cfg.chan_mask);
|
||||
i2s_ll_set_rx_active_chan_mask(hal->dev, hal_cfg->chan_mask);
|
||||
i2s_ll_rx_left_align_enable(hal->dev, hal_cfg->flags.left_align_en);
|
||||
i2s_ll_rx_big_endian_enable(hal->dev, hal_cfg->flags.big_edin_en);
|
||||
i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->flags.bit_order_msb_en);
|
||||
@@ -271,11 +271,9 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
bool is_pdm = ((hal_cfg->mode & I2S_MODE_PDM) > 0);
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
if (is_pdm) {
|
||||
if (hal_cfg->mode & I2S_MODE_PDM) {
|
||||
i2s_ll_tx_pdm_cfg(hal->dev, hal_cfg->sample_rate);
|
||||
} else {
|
||||
i2s_ll_set_tx_pdm_en(hal->dev, false);
|
||||
@@ -284,15 +282,13 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cf
|
||||
#endif // SOC_I2S_SUPPORTS_PDM_TX
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
if (is_pdm) {
|
||||
if (hal_cfg->mode & I2S_MODE_PDM) {
|
||||
i2s_ll_rx_pdm_cfg(hal->dev);
|
||||
} else {
|
||||
i2s_ll_set_rx_pdm_en(hal->dev, false);
|
||||
}
|
||||
}
|
||||
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||
#endif // SOC_I2S_SUPPORTS_PDM
|
||||
//Configure I2S slot number,sample bit.
|
||||
//Configure I2S chan number,sample bit.
|
||||
i2s_hal_samples_config(hal, hal_cfg);
|
||||
|
||||
}
|
||||
|
@@ -44,35 +44,6 @@ typedef union {
|
||||
uint32_t val; /*!< I2S cannel bits configiration value */
|
||||
} i2s_hal_bits_cfg_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
/**
|
||||
* @brief I2S channel configurations
|
||||
*
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t total_chan : 8; /*!< Total number of I2S channels */
|
||||
uint32_t active_chan : 8; /*!< Active channel number, it will be set automatically if chan_mask is set */
|
||||
uint32_t chan_mask : 16; /*!< Active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<<total_slot_num). */
|
||||
};
|
||||
uint32_t val; /*!< Slot data bits value*/
|
||||
} i2s_hal_chan_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief I2S TDM flags
|
||||
*
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t left_align_en : 1; /*!< Set to enable left aligment */
|
||||
uint32_t big_edin_en : 1; /*!< Set to enable big edin */
|
||||
uint32_t bit_order_msb_en : 1; /*!< Set to enable msb order */
|
||||
uint32_t skip_msk_en : 1; /*!< Set to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
|
||||
};
|
||||
uint32_t val;
|
||||
} i2s_hal_tdm_flags_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S HAL configurations
|
||||
*/
|
||||
@@ -84,8 +55,17 @@ typedef struct {
|
||||
i2s_channel_fmt_t chan_fmt; /*!< I2S channel format, there are total 16 channels in TDM mode.*/
|
||||
i2s_hal_bits_cfg_t bits_cfg; /*!< Channel bits configuration*/
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
i2s_hal_chan_cfg_t chan_cfg; /*!< active slot bit mask, using the ored mask of `i2s_channel_t`*/
|
||||
i2s_hal_tdm_flags_t flags; /*!< Set TDM flags*/
|
||||
uint32_t total_chan; /*!< Total number of I2S channels */
|
||||
uint32_t chan_mask; /*!< Active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<<total_chan_num). */
|
||||
union {
|
||||
struct {
|
||||
uint32_t left_align_en : 1; /*!< Set to enable left aligment */
|
||||
uint32_t big_edin_en : 1; /*!< Set to enable big edin */
|
||||
uint32_t bit_order_msb_en : 1; /*!< Set to enable msb order */
|
||||
uint32_t skip_msk_en : 1; /*!< Set to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
|
||||
};
|
||||
uint32_t val; /*!< TDM flags value */
|
||||
} flags; /*!< Set TDM flags */
|
||||
#endif
|
||||
} i2s_hal_config_t;
|
||||
|
||||
@@ -211,19 +191,19 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal);
|
||||
* @brief Set I2S TX sample bit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param slot_bit I2S TX slot bit
|
||||
* @param chan_bit I2S TX chan bit
|
||||
* @param data_bit The sample data bit length.
|
||||
*/
|
||||
#define i2s_hal_set_tx_sample_bit(hal, slot_bit, data_bit) i2s_ll_set_tx_sample_bit((hal)->dev, slot_bit, data_bit)
|
||||
#define i2s_hal_set_tx_sample_bit(hal, chan_bit, data_bit) i2s_ll_set_tx_sample_bit((hal)->dev, chan_bit, data_bit)
|
||||
|
||||
/**
|
||||
* @brief Set I2S RX sample bit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param slot_bit I2S RX slot bit
|
||||
* @param chan_bit I2S RX chan bit
|
||||
* @param data_bit The sample data bit length.
|
||||
*/
|
||||
#define i2s_hal_set_rx_sample_bit(hal, slot_bit, data_bit) i2s_ll_set_rx_sample_bit((hal)->dev, slot_bit, data_bit)
|
||||
#define i2s_hal_set_rx_sample_bit(hal, chan_bit, data_bit) i2s_ll_set_rx_sample_bit((hal)->dev, chan_bit, data_bit)
|
||||
|
||||
/**
|
||||
* @brief Configure I2S TX module clock devider
|
||||
@@ -250,7 +230,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc
|
||||
* @brief Configure I2S TX PCM encoder or decoder.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_mode_t`
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t`
|
||||
*/
|
||||
#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_pcm_cfg((hal)->dev, cfg)
|
||||
|
||||
@@ -258,7 +238,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc
|
||||
* @brief Configure I2S RX PCM encoder or decoder.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_mode_t`
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t`
|
||||
*/
|
||||
#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_pcm_cfg((hal)->dev, cfg)
|
||||
#endif
|
||||
|
@@ -36,16 +36,16 @@ typedef enum {
|
||||
} i2s_bits_per_sample_t;
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per slot.
|
||||
* @brief I2S bit width per chan.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_SLOT_8BIT = (8), /*!< slot bit 8*/
|
||||
I2S_BITS_PER_SLOT_16BIT = (16), /*!< slot bit 16*/
|
||||
I2S_BITS_PER_SLOT_24BIT = (24), /*!< slot bit 24*/
|
||||
I2S_BITS_PER_SLOT_32BIT = (32), /*!< slot bit 32*/
|
||||
I2S_BITS_PER_SLOT_EQU_SAMPLE = (0), /*!< slot bit equals to data bit*/
|
||||
} i2s_bits_per_slot_t;
|
||||
I2S_BITS_PER_CHAN_DEFAULT = (0), /*!< chan bit equals to data bit*/
|
||||
I2S_BITS_PER_CHAN_8BIT = (8), /*!< chan bit 8*/
|
||||
I2S_BITS_PER_CHAN_16BIT = (16), /*!< chan bit 16*/
|
||||
I2S_BITS_PER_CHAN_24BIT = (24), /*!< chan bit 24*/
|
||||
I2S_BITS_PER_CHAN_32BIT = (32), /*!< chan bit 32*/
|
||||
} i2s_bits_per_chan_t;
|
||||
|
||||
/**
|
||||
* @brief I2S channel.
|
||||
@@ -84,9 +84,6 @@ typedef enum {
|
||||
#endif
|
||||
} i2s_channel_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S communication standard format
|
||||
*
|
||||
@@ -134,10 +131,8 @@ typedef enum {
|
||||
I2S_MODE_DAC_BUILT_IN = (0x1 << 4), /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
|
||||
I2S_MODE_ADC_BUILT_IN = (0x1 << 5), /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
// PDM functions are only supported on I2S0 (all chips).
|
||||
I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/
|
||||
#endif
|
||||
} i2s_mode_t;
|
||||
|
||||
/**
|
||||
@@ -169,12 +164,12 @@ typedef enum {
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_PCM_A_DECOMPRESS=0, /*!< A-law decompress*/
|
||||
I2S_PCM_DISABLE = 0, /*!< Disable A/U law decopress or compress*/
|
||||
I2S_PCM_A_DECOMPRESS, /*!< A-law decompress*/
|
||||
I2S_PCM_A_COMPRESS, /*!< A-law compress*/
|
||||
I2S_PCM_U_DECOMPRESS, /*!< U-law decompress*/
|
||||
I2S_PCM_U_COMPRESS, /*!< U-law compress*/
|
||||
I2S_PCM_DISABLE, /*!< Disable A/U law decopress or compress*/
|
||||
} i2s_pcm_mode_t;
|
||||
} i2s_pcm_compress_t;
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
@@ -188,7 +183,6 @@ typedef enum {
|
||||
} i2s_pdm_dsr_t;
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
/**
|
||||
* @brief PDM PCM convter enable/disable.
|
||||
*
|
||||
@@ -197,7 +191,6 @@ typedef enum {
|
||||
PDM_PCM_CONV_ENABLE, /*!< Enable PDM PCM convert*/
|
||||
PDM_PCM_CONV_DISABLE, /*!< Disable PDM PCM convert*/
|
||||
} pdm_pcm_conv_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -138,7 +138,6 @@
|
||||
#define SOC_I2S_NUM (2)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM (1) // (SOC_I2S_SUPPORTS_PDM_RX | SOC_I2S_SUPPORTS_PDM_TX)
|
||||
#define SOC_I2S_SUPPORTS_ADC_DAC (1) // ESP32 support ADC and DAC
|
||||
|
||||
#define SOC_I2S_SUPPORTS_APLL (1)// ESP32 support APLL
|
||||
|
@@ -26,6 +26,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.rx_ws_sig = I2SI_WS_IN_IDX,
|
||||
.data_out_sig = I2SO_SD_OUT_IDX,
|
||||
.data_in_sig = I2SI_SD_IN_IDX,
|
||||
.irq = -1,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@@ -112,7 +112,6 @@
|
||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (0)
|
||||
#define SOC_I2S_SUPPORTS_PDM (1) //(SOC_I2S_SUPPORTS_PDM_RX | SOC_I2S_SUPPORTS_PDM_TX)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
#define SOC_I2S_APLL_MIN_FREQ (250000000)
|
||||
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
||||
|
@@ -106,7 +106,10 @@
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
#define SOC_I2S_NUM (1)
|
||||
|
||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (0)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
#define SOC_I2S_APLL_MIN_FREQ (250000000)
|
||||
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
||||
#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware
|
||||
|
@@ -7,7 +7,7 @@ PROVIDE ( SIGMADELTA = 0x60004f00 );
|
||||
PROVIDE ( RTCCNTL = 0x60008000 );
|
||||
PROVIDE ( RTCIO = 0x60008400 );
|
||||
PROVIDE ( HINF = 0x6000B000 );
|
||||
PROVIDE ( I2S1 = 0x6002d000 );
|
||||
PROVIDE ( I2S0 = 0x6002d000 );
|
||||
PROVIDE ( I2C0 = 0x60013000 );
|
||||
PROVIDE ( UHCI0 = 0x60014000 );
|
||||
PROVIDE ( UHCI1 = 0x6000c000 );
|
||||
|
@@ -26,6 +26,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.rx_ws_sig = I2S0I_WS_IN_IDX,
|
||||
.data_out_sig = I2S0O_SD_OUT_IDX,
|
||||
.data_in_sig = I2S0I_SD_IN_IDX,
|
||||
.irq = -1,
|
||||
.module = PERIPH_I2S0_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -35,6 +36,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.rx_ws_sig = I2S1I_WS_IN_IDX,
|
||||
.data_out_sig = I2S1O_SD_OUT_IDX,
|
||||
.data_in_sig = I2S1I_SD_IN_IDX,
|
||||
.irq = -1,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@@ -67,7 +67,6 @@
|
||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM (1) //(SOC_I2S_SUPPORTS_PDM_RX | SOC_I2S_SUPPORTS_PDM_TX)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
|
@@ -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.
|
||||
|
||||
.. 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
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
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:
|
||||
|
||||
.. only:: not SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
static const i2s_config_t i2s_config = {
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = 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
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false
|
||||
.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,50 +158,149 @@ Application Example
|
||||
|
||||
A code example for the I2S driver can be found in the directory :example:`peripherals/i2s`.
|
||||
|
||||
.. 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
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Example for general usage.
|
||||
|
||||
.. only:: not SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
.. 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 = {
|
||||
.param_cfg = {
|
||||
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
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false
|
||||
.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,
|
||||
.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
|
||||
|
||||
.. 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_RIGHT_LEFT,
|
||||
.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);
|
||||
|
||||
...
|
||||
/* 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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -196,12 +313,10 @@ 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 = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
.sample_rate = 44100,
|
||||
.slot_bits_cfg = 16, /* the DAC module will only take the 8bits from MSB */
|
||||
.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,
|
||||
|
Reference in New Issue
Block a user