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 "freertos/semphr.h"
|
||||||
|
|
||||||
#include "soc/lldesc.h"
|
#include "soc/lldesc.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/i2s.h"
|
#include "driver/i2s.h"
|
||||||
#include "hal/gpio_hal.h"
|
#include "hal/gpio_hal.h"
|
||||||
|
#include "hal/i2s_hal.h"
|
||||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||||
#include "driver/dac.h"
|
#include "driver/dac.h"
|
||||||
#include "hal/i2s_hal.h"
|
|
||||||
#include "adc1_private.h"
|
#include "adc1_private.h"
|
||||||
#endif
|
#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)
|
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");
|
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
|
#endif // SOC_I2S_SUPPORTS_ADC_DAC
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_PDM
|
|
||||||
if ( p_i2s[i2s_num]->mode & I2S_MODE_PDM) {
|
if ( p_i2s[i2s_num]->mode & I2S_MODE_PDM) {
|
||||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||||
if ( p_i2s[i2s_num]->mode & I2S_MODE_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
|
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||||
_bck_div = 8;
|
_bck_div = 8;
|
||||||
}
|
}
|
||||||
#endif // SOC_I2S_SUPPORTS_PDM
|
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_APLL
|
#if SOC_I2S_SUPPORTS_APLL
|
||||||
int sdm0 = 0;
|
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: {
|
case I2S_CHANNEL_FMT_TDM: {
|
||||||
uint32_t num = 0;
|
uint32_t num = 0;
|
||||||
uint32_t max_chan = 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) {
|
for (int i = 0; chan_mask && i < 16; i++, chan_mask >>= 1) {
|
||||||
if ((chan_mask & 0x01) == 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;
|
max_chan = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max_chan > hal_cfg->chan_cfg.total_chan) {
|
if (max_chan > hal_cfg->total_chan) {
|
||||||
hal_cfg->chan_cfg.total_chan = max_chan;
|
hal_cfg->total_chan = max_chan;
|
||||||
}
|
}
|
||||||
hal_cfg->chan_cfg.active_chan = num;
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg;
|
||||||
int data_bits = 0;
|
int data_bits = 0;
|
||||||
int slot_bits = 0;
|
int chan_bits = 0;
|
||||||
int active_slot_num = 0;
|
int active_chan_num = 0;
|
||||||
int slot_num = 0;
|
int chan_num = 0;
|
||||||
|
|
||||||
cfg->ch = ch;
|
cfg->ch = ch;
|
||||||
cfg->sample_rate = rate;
|
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.chan_bits = cfg->bits_cfg.chan_bits < cfg->bits_cfg.sample_bits ?
|
||||||
cfg->bits_cfg.sample_bits : cfg->bits_cfg.chan_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;
|
data_bits = cfg->bits_cfg.sample_bits;
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_TDM
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
cfg->chan_cfg.chan_mask = ch & 0xFFFF;
|
cfg->chan_mask = ch & 0xFFFF;
|
||||||
active_slot_num = i2s_get_active_chan_num(cfg);
|
active_chan_num = i2s_get_active_chan_num(cfg);
|
||||||
slot_num = cfg->chan_cfg.total_chan;
|
chan_num = cfg->total_chan;
|
||||||
#else
|
#else
|
||||||
active_slot_num = i2s_get_active_chan_num(cfg);
|
active_chan_num = i2s_get_active_chan_num(cfg);
|
||||||
slot_num = ch == I2S_CHANNEL_MONO ? 2 : active_slot_num;
|
chan_num = ch == I2S_CHANNEL_MONO ? 2 : active_chan_num;
|
||||||
#endif
|
#endif
|
||||||
ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
|
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);
|
xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
|
||||||
}
|
}
|
||||||
//malloc DMA buffer
|
//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;
|
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 i2s_bck = 0; // I2S back clock
|
||||||
uint32_t bck_div = 0; // I2S bck div
|
uint32_t bck_div = 0; // I2S bck div
|
||||||
//calculate bck_div, f_bck and select source clock
|
//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;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
//configure i2s clock
|
//configure i2s clock
|
||||||
if (p_i2s[i2s_num]->mode & I2S_MODE_TX) {
|
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_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
|
// wait all writing on-going finish
|
||||||
if (p_i2s[i2s_num]->tx) {
|
if (p_i2s[i2s_num]->tx) {
|
||||||
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
|
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) {
|
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_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
|
// wait all writing on-going finish
|
||||||
if (p_i2s[i2s_num]->rx) {
|
if (p_i2s[i2s_num]->rx) {
|
||||||
xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
|
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");
|
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;
|
return ESP_OK;
|
||||||
#endif
|
#endif
|
||||||
#if SOC_I2S_SUPPORTS_PDM
|
|
||||||
//We only check if the I2S number is invalid when set to PDM mode.
|
//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");
|
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;
|
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 && (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");
|
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.comm_fmt = i2s_config->communication_format;
|
||||||
p_i2s[i2s_num]->hal_cfg.chan_fmt = i2s_config->channel_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.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
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
|
int active_chan = 0;
|
||||||
switch (i2s_config->channel_format) {
|
switch (i2s_config->channel_format) {
|
||||||
case I2S_CHANNEL_FMT_RIGHT_LEFT:
|
case I2S_CHANNEL_FMT_RIGHT_LEFT:
|
||||||
case I2S_CHANNEL_FMT_ALL_RIGHT:
|
case I2S_CHANNEL_FMT_ALL_RIGHT:
|
||||||
case I2S_CHANNEL_FMT_ALL_LEFT:
|
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_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.total_chan = 2;
|
||||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.total_chan = 2;
|
active_chan = 2;
|
||||||
break;
|
break;
|
||||||
case I2S_CHANNEL_FMT_ONLY_RIGHT:
|
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_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.total_chan = 1;
|
||||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.total_chan = 1;
|
active_chan = 1;
|
||||||
break;
|
break;
|
||||||
case I2S_CHANNEL_FMT_ONLY_LEFT:
|
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_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.total_chan = 1;
|
||||||
p_i2s[i2s_num]->hal_cfg.chan_cfg.total_chan = 1;
|
active_chan = 1;
|
||||||
break;
|
break;
|
||||||
case I2S_CHANNEL_FMT_TDM:
|
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");
|
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_cfg.chan_mask = i2s_config->tdm_chan_cfg.chan_mask;
|
p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->chan_mask;
|
||||||
i2s_get_active_chan_num(&p_i2s[i2s_num]->hal_cfg);
|
i2s_get_active_chan_num(&p_i2s[i2s_num]->hal_cfg);
|
||||||
break;
|
break;
|
||||||
default:
|
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_count = i2s_config->dma_buf_count;
|
||||||
p_i2s[i2s_num]->dma_buf_len = i2s_config->dma_buf_len;
|
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
|
#ifdef CONFIG_PM_ENABLE
|
||||||
if (i2s_config->use_apll) {
|
if (i2s_config->use_apll) {
|
||||||
ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock);
|
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
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
ret = i2s_set_clk(i2s_num, i2s_config->sample_rate,
|
ret = i2s_set_clk(i2s_num, i2s_config->sample_rate,
|
||||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.val,
|
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
|
#else
|
||||||
ret = i2s_set_clk(i2s_num, i2s_config->sample_rate,
|
ret = i2s_set_clk(i2s_num, i2s_config->sample_rate,
|
||||||
p_i2s[i2s_num]->hal_cfg.bits_cfg.val,
|
p_i2s[i2s_num]->hal_cfg.bits_cfg.val,
|
||||||
|
@@ -13,9 +13,7 @@
|
|||||||
#include "soc/i2s_periph.h"
|
#include "soc/i2s_periph.h"
|
||||||
#include "soc/rtc_periph.h"
|
#include "soc/rtc_periph.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "hal/i2s_hal.h"
|
|
||||||
#include "hal/i2s_types.h"
|
#include "hal/i2s_types.h"
|
||||||
#include "driver/periph_ctrl.h"
|
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||||
@@ -50,9 +48,15 @@ typedef struct {
|
|||||||
int data_in_num; /*!< DATA in pin*/
|
int data_in_num; /*!< DATA in pin*/
|
||||||
} i2s_pin_config_t;
|
} i2s_pin_config_t;
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_TDM
|
#if SOC_I2S_SUPPORTS_PCM
|
||||||
typedef i2s_hal_chan_cfg_t tdm_chan_cfg_t;
|
/**
|
||||||
typedef i2s_hal_tdm_flags_t tdm_flags_t;
|
* @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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,15 +76,30 @@ typedef struct {
|
|||||||
bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */
|
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) */
|
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.*/
|
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
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
tdm_chan_cfg_t tdm_chan_cfg; /*!< I2S TDM channel configurations*/
|
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). */
|
||||||
tdm_flags_t tdm_flags; /*!< I2S TDM flags*/
|
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. */
|
||||||
#endif
|
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;
|
} i2s_driver_config_t;
|
||||||
|
|
||||||
typedef i2s_driver_config_t i2s_config_t;
|
typedef i2s_driver_config_t i2s_config_t; // for backward compatible
|
||||||
typedef intr_handle_t i2s_isr_handle_t;
|
typedef intr_handle_t i2s_isr_handle_t; // for backward compatible
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S event queue types
|
* @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);
|
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.
|
* @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
|
* @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 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)
|
* @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);
|
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 */
|
/* 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]")
|
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());
|
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 */
|
/* Only ESP32 need I2S adc/dac test */
|
||||||
TEST_CASE("I2S adc test", "[i2s]")
|
TEST_CASE("I2S adc test", "[i2s]")
|
||||||
{
|
{
|
||||||
|
@@ -14,13 +14,13 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
"spi_hal_iram.c"
|
"spi_hal_iram.c"
|
||||||
"spi_slave_hal.c"
|
"spi_slave_hal.c"
|
||||||
"spi_slave_hal_iram.c"
|
"spi_slave_hal_iram.c"
|
||||||
"i2s_hal.c"
|
|
||||||
"sigmadelta_hal.c"
|
"sigmadelta_hal.c"
|
||||||
"timer_hal.c"
|
"timer_hal.c"
|
||||||
"ledc_hal.c"
|
"ledc_hal.c"
|
||||||
"ledc_hal_iram.c"
|
"ledc_hal_iram.c"
|
||||||
"i2c_hal.c"
|
"i2c_hal.c"
|
||||||
"i2c_hal_iram.c"
|
"i2c_hal_iram.c"
|
||||||
|
"i2s_hal.c"
|
||||||
"gpio_hal.c"
|
"gpio_hal.c"
|
||||||
"uart_hal.c"
|
"uart_hal.c"
|
||||||
"uart_hal_iram.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 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
|
* @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)
|
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 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
|
* @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)
|
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" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define I2S_LL_GET_HW(num) (&I2S0)
|
#define I2S_LL_GET_HW(num) (&I2S0)
|
||||||
|
|
||||||
#define I2S_LL_TDM_CH_MASK (0xffff)
|
#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 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
|
* @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)
|
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 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
|
* @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)
|
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 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;
|
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 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;
|
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 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;
|
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 &= ~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;
|
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 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;
|
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 &= ~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;
|
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 hw Peripheral I2S hardware instance address.
|
||||||
* @param pcm_cfg PCM configuration paramater
|
* @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) {
|
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||||
hw->tx_conf.tx_pcm_bypass = 1;
|
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 hw Peripheral I2S hardware instance address.
|
||||||
* @param pcm_cfg PCM configuration paramater
|
* @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) {
|
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||||
hw->rx_conf.rx_pcm_bypass = 1;
|
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 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
|
* @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)
|
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 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
|
* @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)
|
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 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
|
* @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)
|
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 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
|
* @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)
|
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 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;
|
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 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;
|
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 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;
|
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 &= ~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;
|
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 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;
|
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 &= ~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;
|
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 hw Peripheral I2S hardware instance address.
|
||||||
* @param pcm_cfg PCM configuration paramater
|
* @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) {
|
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||||
hw->tx_conf.tx_pcm_bypass = 1;
|
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 hw Peripheral I2S hardware instance address.
|
||||||
* @param pcm_cfg PCM configuration paramater
|
* @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) {
|
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||||
hw->rx_conf.rx_pcm_bypass = 1;
|
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
|
#else
|
||||||
int slot_bits = hal_cfg->bits_cfg.chan_bits;
|
int chan_bits = hal_cfg->bits_cfg.chan_bits;
|
||||||
int slot_num = hal_cfg->chan_cfg.total_chan;
|
int chan_num = hal_cfg->total_chan;
|
||||||
bool msb_shift_en = false;
|
bool msb_shift_en = false;
|
||||||
int tdm_ws_width = 0;
|
int tdm_ws_width = 0;
|
||||||
switch (hal_cfg->comm_fmt) {
|
switch (hal_cfg->comm_fmt) {
|
||||||
case I2S_COMM_FORMAT_STAND_MSB:
|
case I2S_COMM_FORMAT_STAND_MSB:
|
||||||
msb_shift_en = false;
|
msb_shift_en = false;
|
||||||
tdm_ws_width = slot_num * slot_bits / 2;
|
tdm_ws_width = chan_num * chan_bits / 2;
|
||||||
break;
|
break;
|
||||||
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
|
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
|
||||||
msb_shift_en = false;
|
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;
|
break;
|
||||||
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
||||||
msb_shift_en = false;
|
msb_shift_en = false;
|
||||||
tdm_ws_width = slot_bits;
|
tdm_ws_width = chan_bits;
|
||||||
break;
|
break;
|
||||||
default: //I2S_COMM_FORMAT_STAND_I2S
|
default: //I2S_COMM_FORMAT_STAND_I2S
|
||||||
msb_shift_en = true;
|
msb_shift_en = true;
|
||||||
tdm_ws_width = slot_num * slot_bits / 2;
|
tdm_ws_width = chan_num * chan_bits / 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||||
i2s_ll_tx_msb_shift_enable(hal->dev, msb_shift_en);
|
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_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) {
|
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||||
i2s_ll_rx_msb_shift_enable(hal->dev, msb_shift_en);
|
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_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
|
#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)
|
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 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
|
#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) {
|
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||||
i2s_ll_set_tx_slot_num(hal->dev, slot_num);
|
i2s_ll_set_tx_chan_num(hal->dev, chan_num);
|
||||||
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) {
|
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||||
i2s_ll_set_rx_slot_num(hal->dev, slot_num);
|
i2s_ll_set_rx_chan_num(hal->dev, chan_num);
|
||||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bits, data_bits);
|
i2s_ll_set_rx_sample_bit(hal->dev, chan_bits, data_bits);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
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) {
|
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
|
#endif
|
||||||
//I2S standards config: Philip, MSB or PCM, Only I2S mode should do this configuration.
|
//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_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_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_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_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);
|
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_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_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_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_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);
|
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
|
#endif
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_PDM
|
|
||||||
bool is_pdm = ((hal_cfg->mode & I2S_MODE_PDM) > 0);
|
|
||||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||||
if (hal_cfg->mode & I2S_MODE_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);
|
i2s_ll_tx_pdm_cfg(hal->dev, hal_cfg->sample_rate);
|
||||||
} else {
|
} else {
|
||||||
i2s_ll_set_tx_pdm_en(hal->dev, false);
|
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
|
#endif // SOC_I2S_SUPPORTS_PDM_TX
|
||||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||||
if (hal_cfg->mode & I2S_MODE_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);
|
i2s_ll_rx_pdm_cfg(hal->dev);
|
||||||
} else {
|
} else {
|
||||||
i2s_ll_set_rx_pdm_en(hal->dev, false);
|
i2s_ll_set_rx_pdm_en(hal->dev, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||||
#endif // SOC_I2S_SUPPORTS_PDM
|
//Configure I2S chan number,sample bit.
|
||||||
//Configure I2S slot number,sample bit.
|
|
||||||
i2s_hal_samples_config(hal, hal_cfg);
|
i2s_hal_samples_config(hal, hal_cfg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -44,35 +44,6 @@ typedef union {
|
|||||||
uint32_t val; /*!< I2S cannel bits configiration value */
|
uint32_t val; /*!< I2S cannel bits configiration value */
|
||||||
} i2s_hal_bits_cfg_t;
|
} 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
|
* @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_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*/
|
i2s_hal_bits_cfg_t bits_cfg; /*!< Channel bits configuration*/
|
||||||
#if SOC_I2S_SUPPORTS_TDM
|
#if SOC_I2S_SUPPORTS_TDM
|
||||||
i2s_hal_chan_cfg_t chan_cfg; /*!< active slot bit mask, using the ored mask of `i2s_channel_t`*/
|
uint32_t total_chan; /*!< Total number of I2S channels */
|
||||||
i2s_hal_tdm_flags_t flags; /*!< Set TDM flags*/
|
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
|
#endif
|
||||||
} i2s_hal_config_t;
|
} 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
|
* @brief Set I2S TX sample bit
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @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.
|
* @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
|
* @brief Set I2S RX sample bit
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @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.
|
* @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
|
* @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.
|
* @brief Configure I2S TX PCM encoder or decoder.
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @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)
|
#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.
|
* @brief Configure I2S RX PCM encoder or decoder.
|
||||||
*
|
*
|
||||||
* @param hal Context of the HAL layer
|
* @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)
|
#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_pcm_cfg((hal)->dev, cfg)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -36,16 +36,16 @@ typedef enum {
|
|||||||
} i2s_bits_per_sample_t;
|
} i2s_bits_per_sample_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S bit width per slot.
|
* @brief I2S bit width per chan.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2S_BITS_PER_SLOT_8BIT = (8), /*!< slot bit 8*/
|
I2S_BITS_PER_CHAN_DEFAULT = (0), /*!< chan bit equals to data bit*/
|
||||||
I2S_BITS_PER_SLOT_16BIT = (16), /*!< slot bit 16*/
|
I2S_BITS_PER_CHAN_8BIT = (8), /*!< chan bit 8*/
|
||||||
I2S_BITS_PER_SLOT_24BIT = (24), /*!< slot bit 24*/
|
I2S_BITS_PER_CHAN_16BIT = (16), /*!< chan bit 16*/
|
||||||
I2S_BITS_PER_SLOT_32BIT = (32), /*!< slot bit 32*/
|
I2S_BITS_PER_CHAN_24BIT = (24), /*!< chan bit 24*/
|
||||||
I2S_BITS_PER_SLOT_EQU_SAMPLE = (0), /*!< slot bit equals to data bit*/
|
I2S_BITS_PER_CHAN_32BIT = (32), /*!< chan bit 32*/
|
||||||
} i2s_bits_per_slot_t;
|
} i2s_bits_per_chan_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S channel.
|
* @brief I2S channel.
|
||||||
@@ -84,9 +84,6 @@ typedef enum {
|
|||||||
#endif
|
#endif
|
||||||
} i2s_channel_t;
|
} i2s_channel_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2S communication standard format
|
* @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_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*/
|
I2S_MODE_ADC_BUILT_IN = (0x1 << 5), /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||||
#endif
|
#endif
|
||||||
#if SOC_I2S_SUPPORTS_PDM
|
|
||||||
// PDM functions are only supported on I2S0 (all chips).
|
// PDM functions are only supported on I2S0 (all chips).
|
||||||
I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/
|
I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/
|
||||||
#endif
|
|
||||||
} i2s_mode_t;
|
} i2s_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,12 +164,12 @@ typedef enum {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
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_A_COMPRESS, /*!< A-law compress*/
|
||||||
I2S_PCM_U_DECOMPRESS, /*!< U-law decompress*/
|
I2S_PCM_U_DECOMPRESS, /*!< U-law decompress*/
|
||||||
I2S_PCM_U_COMPRESS, /*!< U-law compress*/
|
I2S_PCM_U_COMPRESS, /*!< U-law compress*/
|
||||||
I2S_PCM_DISABLE, /*!< Disable A/U law decopress or compress*/
|
} i2s_pcm_compress_t;
|
||||||
} i2s_pcm_mode_t;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||||
@@ -188,7 +183,6 @@ typedef enum {
|
|||||||
} i2s_pdm_dsr_t;
|
} i2s_pdm_dsr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_PDM
|
|
||||||
/**
|
/**
|
||||||
* @brief PDM PCM convter enable/disable.
|
* @brief PDM PCM convter enable/disable.
|
||||||
*
|
*
|
||||||
@@ -197,7 +191,6 @@ typedef enum {
|
|||||||
PDM_PCM_CONV_ENABLE, /*!< Enable PDM PCM convert*/
|
PDM_PCM_CONV_ENABLE, /*!< Enable PDM PCM convert*/
|
||||||
PDM_PCM_CONV_DISABLE, /*!< Disable PDM PCM convert*/
|
PDM_PCM_CONV_DISABLE, /*!< Disable PDM PCM convert*/
|
||||||
} pdm_pcm_conv_t;
|
} pdm_pcm_conv_t;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@@ -138,7 +138,6 @@
|
|||||||
#define SOC_I2S_NUM (2)
|
#define SOC_I2S_NUM (2)
|
||||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||||
#define SOC_I2S_SUPPORTS_PDM_RX (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_ADC_DAC (1) // ESP32 support ADC and DAC
|
||||||
|
|
||||||
#define SOC_I2S_SUPPORTS_APLL (1)// ESP32 support APLL
|
#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,
|
.rx_ws_sig = I2SI_WS_IN_IDX,
|
||||||
.data_out_sig = I2SO_SD_OUT_IDX,
|
.data_out_sig = I2SO_SD_OUT_IDX,
|
||||||
.data_in_sig = I2SI_SD_IN_IDX,
|
.data_in_sig = I2SI_SD_IN_IDX,
|
||||||
|
.irq = -1,
|
||||||
.module = PERIPH_I2S1_MODULE,
|
.module = PERIPH_I2S1_MODULE,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -112,7 +112,6 @@
|
|||||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||||
#define SOC_I2S_SUPPORTS_PDM_RX (0)
|
#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_SUPPORTS_TDM (1)
|
||||||
#define SOC_I2S_APLL_MIN_FREQ (250000000)
|
#define SOC_I2S_APLL_MIN_FREQ (250000000)
|
||||||
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
||||||
|
@@ -106,7 +106,10 @@
|
|||||||
|
|
||||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||||
#define SOC_I2S_NUM (1)
|
#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_MIN_FREQ (250000000)
|
||||||
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
||||||
#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware
|
#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 ( RTCCNTL = 0x60008000 );
|
||||||
PROVIDE ( RTCIO = 0x60008400 );
|
PROVIDE ( RTCIO = 0x60008400 );
|
||||||
PROVIDE ( HINF = 0x6000B000 );
|
PROVIDE ( HINF = 0x6000B000 );
|
||||||
PROVIDE ( I2S1 = 0x6002d000 );
|
PROVIDE ( I2S0 = 0x6002d000 );
|
||||||
PROVIDE ( I2C0 = 0x60013000 );
|
PROVIDE ( I2C0 = 0x60013000 );
|
||||||
PROVIDE ( UHCI0 = 0x60014000 );
|
PROVIDE ( UHCI0 = 0x60014000 );
|
||||||
PROVIDE ( UHCI1 = 0x6000c000 );
|
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,
|
.rx_ws_sig = I2S0I_WS_IN_IDX,
|
||||||
.data_out_sig = I2S0O_SD_OUT_IDX,
|
.data_out_sig = I2S0O_SD_OUT_IDX,
|
||||||
.data_in_sig = I2S0I_SD_IN_IDX,
|
.data_in_sig = I2S0I_SD_IN_IDX,
|
||||||
|
.irq = -1,
|
||||||
.module = PERIPH_I2S0_MODULE,
|
.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,
|
.rx_ws_sig = I2S1I_WS_IN_IDX,
|
||||||
.data_out_sig = I2S1O_SD_OUT_IDX,
|
.data_out_sig = I2S1O_SD_OUT_IDX,
|
||||||
.data_in_sig = I2S1I_SD_IN_IDX,
|
.data_in_sig = I2S1I_SD_IN_IDX,
|
||||||
|
.irq = -1,
|
||||||
.module = PERIPH_I2S1_MODULE,
|
.module = PERIPH_I2S1_MODULE,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -67,7 +67,6 @@
|
|||||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||||
#define SOC_I2S_SUPPORTS_PDM_RX (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)
|
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||||
|
|
||||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||||
|
@@ -1,24 +1,14 @@
|
|||||||
I2S
|
I2S
|
||||||
===
|
===
|
||||||
|
|
||||||
.. only:: esp32c3
|
{IDF_TARGET_I2S_NUM:default="two", esp32s2="one", esp32c3="one"}
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
This document is not updated for ESP32-C3 yet.
|
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
|
|
||||||
I2S (Inter-IC Sound) is a serial, synchronous communication protocol that is usually used for transmitting audio data between two digital audio devices.
|
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 {IDF_TARGET_I2S_NUM} I2S peripheral(s). These peripherals can be configured to input and output sample data via the I2S driver.
|
||||||
|
|
||||||
{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.
|
|
||||||
|
|
||||||
An I2S bus consists of the following lines:
|
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
|
- Operation as system master or slave
|
||||||
- Capable of acting as transmitter or receiver
|
- 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.
|
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
|
.. 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>`__].
|
For more information, see *{IDF_TARGET_NAME} Technical Reference Manual* > *I2S Controller (I2S)* > LCD Mode [`PDF <{IDF_TARGET_TRM_EN_URL}#camlcdctrl>`__].
|
||||||
|
|
||||||
.. note::
|
.. 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
|
- The structure :cpp:type:`i2s_config_t` with defined communication parameters
|
||||||
- Event queue size and handle
|
- Event queue size and handle
|
||||||
|
|
||||||
|
I2S will start automatically once :cpp:func`i2s_driver_install` returns ``ESP_OK``.
|
||||||
|
|
||||||
Configuration example:
|
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 = {
|
static const int i2s_num = 0; // i2s port number
|
||||||
.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
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
Setting Communication Pins
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@@ -100,15 +116,14 @@ Once the driver is installed, configure physical GPIO pins to which signals will
|
|||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
static const i2s_pin_config_t pin_config = {
|
static const i2s_pin_config_t pin_config = {
|
||||||
.bck_io_num = 26,
|
.bck_io_num = 4,
|
||||||
.ws_io_num = 25,
|
.ws_io_num = 5,
|
||||||
.data_out_num = 22,
|
.data_out_num = 18,
|
||||||
.data_in_num = I2S_PIN_NO_CHANGE
|
.data_in_num = I2S_PIN_NO_CHANGE
|
||||||
};
|
};
|
||||||
|
|
||||||
i2s_set_pin(i2s_num, &pin_config);
|
i2s_set_pin(i2s_num, &pin_config);
|
||||||
|
|
||||||
|
|
||||||
Running I2S Communication
|
Running I2S Communication
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -117,14 +132,17 @@ To perform a transmission:
|
|||||||
- Prepare the data for sending
|
- Prepare the data for sending
|
||||||
- Call the function :cpp:func:`i2s_write` and pass the data buffer address and data length to it
|
- 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
|
.. code-block:: c
|
||||||
|
|
||||||
i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100);
|
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`.
|
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`.
|
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
|
I2S configuration
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code-block:: c
|
Example for general usage.
|
||||||
|
|
||||||
#include "driver/i2s.h"
|
.. only:: not SOC_I2S_SUPPORTS_TDM
|
||||||
#include "freertos/queue.h"
|
|
||||||
|
|
||||||
static const int i2s_num = 0; // i2s port number
|
.. code-block:: c
|
||||||
|
|
||||||
static const i2s_config_t i2s_config = {
|
#include "driver/i2s.h"
|
||||||
.param_cfg = {
|
|
||||||
|
static const int i2s_num = 0; // i2s port number
|
||||||
|
|
||||||
|
i2s_config_t i2s_config = {
|
||||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||||
.sample_rate = 44100,
|
.sample_rate = 44100,
|
||||||
.slot_bits_cfg = 16,
|
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||||
},
|
.tx_desc_auto_clear = false,
|
||||||
.intr_alloc_flags = 0, // default interrupt priority
|
.dma_buf_count = 8,
|
||||||
.dma_buf_count = 8,
|
.dma_buf_len = 64,
|
||||||
.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 = {
|
static const i2s_pin_config_t pin_config = {
|
||||||
.bck_io_num = 26,
|
.bck_io_num = 4,
|
||||||
.ws_io_num = 25,
|
.ws_io_num = 5,
|
||||||
.data_out_num = 22,
|
.data_out_num = 18,
|
||||||
.data_in_num = I2S_PIN_NO_CHANGE
|
.data_in_num = I2S_PIN_NO_CHANGE
|
||||||
};
|
};
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
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, &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
|
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"
|
static const int i2s_num = 0; // i2s port number
|
||||||
#include "freertos/queue.h"
|
|
||||||
|
|
||||||
static const int i2s_num = 0; // i2s port number
|
i2s_config_t i2s_config = {
|
||||||
|
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||||
static const i2s_config_t i2s_config = {
|
|
||||||
.param_cfg = {
|
|
||||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
|
||||||
.sample_rate = 44100,
|
.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,
|
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||||
},
|
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||||
.intr_alloc_flags = 0, // default interrupt priority
|
.tx_desc_auto_clear = false,
|
||||||
.dma_buf_count = 8,
|
.dma_buf_count = 8,
|
||||||
.dma_buf_len = 64,
|
.dma_buf_len = 64
|
||||||
.use_apll = false
|
};
|
||||||
};
|
|
||||||
|
|
||||||
...
|
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_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 reset parameters by calling 'i2s_set_clk'
|
||||||
//You can call i2s_set_dac_mode to set built-in DAC output mode.
|
*
|
||||||
//i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
* 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
|
||||||
i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
* 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_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
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
|
Reference in New Issue
Block a user