Merge branch 'refactor/i2s_major_refactoring_for_ng' into 'master'

🔨i2s: Major refactoring for driver-NG

Closes IDF-4781 and IDF-4779

See merge request espressif/esp-idf!17484
This commit is contained in:
Kevin (Lao Kaiyao) 2022-03-23 15:32:46 +08:00
commit ba9d3fe819
25 changed files with 2793 additions and 2126 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@ -604,12 +604,7 @@ static esp_err_t i2s_lcd_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported clock source: %d", src);
break;
}
i2s_ll_mclk_div_t clk_cal_config = {
.mclk_div = LCD_PERIPH_CLOCK_PRE_SCALE,
.a = 1,
.b = 0,
};
i2s_ll_tx_set_clk(bus->hal.dev, &clk_cal_config);
i2s_ll_set_raw_mclk_div(bus->hal.dev, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0);
return ret;
}

View File

@ -256,12 +256,7 @@ static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, uint32_t fre
#else
i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); /*!< Clock from PLL_D2_CLK(160M)*/
uint32_t bck = I2S_BASE_CLK / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_B_DEFAULT / ADC_LL_CLKM_DIV_A_DEFAULT) / 2 / freq;
i2s_ll_mclk_div_t clk = {
.mclk_div = ADC_LL_CLKM_DIV_NUM_DEFAULT,
.a = ADC_LL_CLKM_DIV_A_DEFAULT,
.b = ADC_LL_CLKM_DIV_B_DEFAULT,
};
i2s_ll_rx_set_clk(hal->dev, &clk);
i2s_ll_set_raw_mclk_div(hal->dev, ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT);
i2s_ll_rx_set_bck_div_num(hal->dev, bck);
#endif
}

View File

@ -19,6 +19,7 @@
#include "soc/i2s_periph.h"
#include "soc/i2s_struct.h"
#include "hal/i2s_types.h"
#include "hal/i2s_types_priv.h"
#ifdef __cplusplus
extern "C" {
@ -34,14 +35,19 @@ extern "C" {
#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6)
#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1)
#define I2S_LL_EVENT_TX_EOF (1 << 12)
#define I2S_LL_BCK_MAX_PRESCALE (64)
#define I2S_LL_EVENT_RX_EOF BIT(9)
#define I2S_LL_EVENT_TX_EOF BIT(12)
#define I2S_LL_EVENT_RX_DSCR_ERR BIT(13)
#define I2S_LL_EVENT_TX_DSCR_ERR BIT(14)
#define I2S_INTR_MAX (UINT32_MAX)
/* I2S clock configuration structure */
typedef struct {
uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t mclk_div; // I2S module clock divider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t a;
uint16_t b; // The decimal part of module clock devider, the decimal is: b/a
uint16_t b; // The decimal part of module clock divider, the decimal is: b/a
} i2s_ll_mclk_div_t;
/**
@ -271,16 +277,68 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S TX clock devider
* @brief Configure I2S TX module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div);
hw->clkm_conf.clkm_div_b = set->b;
hw->clkm_conf.clkm_div_a = set->a;
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, mclk_div);
hw->clkm_conf.clkm_div_b = numerator;
hw->clkm_conf.clkm_div_a = denominator;
}
/**
* @brief Configure I2S module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
* mclk = sclk / (mclk_div + b/a)
*
* @param hw Peripheral I2S hardware instance address.
* @param mclk_div integer part of the division from sclk to mclk
* @param a Denominator of decimal part
* @param b Numerator of decimal part
*/
static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uint32_t a, uint32_t b)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, mclk_div);
hw->clkm_conf.clkm_div_b = b;
hw->clkm_conf.clkm_div_a = a;
}
/**
@ -295,16 +353,17 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S RX clock devider
* @brief Configure I2S RX module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div);
hw->clkm_conf.clkm_div_b = set->b;
hw->clkm_conf.clkm_div_a = set->a;
i2s_ll_tx_set_mclk(hw, sclk, mclk, mclk_div);
}
/**
@ -331,7 +390,6 @@ static inline void i2s_ll_enable_intr(i2s_dev_t *hw, uint32_t mask, bool en)
static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw)
{
hw->int_ena.out_eof = 1;
hw->int_ena.out_dscr_err = 1;
}
/**
@ -342,7 +400,6 @@ static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw)
static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw)
{
hw->int_ena.out_eof = 0;
hw->int_ena.out_dscr_err = 0;
}
/**
@ -353,7 +410,6 @@ static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw)
static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw)
{
hw->int_ena.in_suc_eof = 1;
hw->int_ena.in_dscr_err = 1;
}
/**
@ -364,7 +420,6 @@ static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw)
static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw)
{
hw->int_ena.in_suc_eof = 0;
hw->int_ena.in_dscr_err = 0;
}
/**
@ -582,7 +637,7 @@ static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val)
*/
static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
{
hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2);
hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
hw->sample_rate_conf.tx_bits_mod = data_bit;
}
@ -595,7 +650,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int
*/
static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
{
hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2);
hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
hw->sample_rate_conf.rx_bits_mod = data_bit;
}
@ -696,7 +751,7 @@ static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val)
static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
{
int data_bit = hw->sample_rate_conf.tx_bits_mod;
hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena;
hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
hw->conf_chan.tx_chan_mod = mono_ena;
}
@ -709,7 +764,7 @@ static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
{
int data_bit = hw->sample_rate_conf.rx_bits_mod;
hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena;
hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
hw->conf_chan.rx_chan_mod = mono_ena;
}
@ -749,28 +804,53 @@ static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr)
*dsr = (i2s_pdm_dsr_t)hw->pdm_conf.rx_sinc_dsr_16_en;
}
/**
* @brief Enable I2S TX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
{
hw->conf2.val = 0;
hw->pdm_conf.tx_pdm_en = false;
hw->pdm_conf.pcm2pdm_conv_en = false;
}
/**
* @brief Enable I2S RX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
{
hw->conf2.val = 0;
hw->pdm_conf.rx_pdm_en = false;
hw->pdm_conf.pdm2pcm_conv_en = false;
}
/**
* @brief Enable I2S TX PDM mode
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_ena Set true to enable TX PDM mode
*/
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_ena)
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
{
hw->pdm_conf.tx_pdm_en = pdm_ena;
hw->pdm_conf.pcm2pdm_conv_en = pdm_ena;
hw->conf2.val = 0;
hw->pdm_conf.tx_pdm_en = true;
hw->pdm_conf.pcm2pdm_conv_en = true;
}
/**
* @brief Enable I2S RX PDM mode
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_ena Set true to enable RX PDM mode
*/
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_ena)
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw)
{
hw->pdm_conf.rx_pdm_en = pdm_ena;
hw->pdm_conf.pdm2pcm_conv_en = pdm_ena;
hw->conf2.val = 0;
hw->pdm_conf.rx_pdm_en = true;
hw->pdm_conf.pdm2pcm_conv_en = true;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -33,9 +33,9 @@ extern "C" {
/* I2S clock configuration structure */
typedef struct {
uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t mclk_div; // I2S module clock divider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t a;
uint16_t b; // The decimal part of module clock devider, the decimal is: b/a
uint16_t b; // The decimal part of module clock divider, the decimal is: b/a
} i2s_ll_mclk_div_t;
/**
@ -103,7 +103,7 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw)
{
hw->rx_clkm_conf.mclk_sel = 0;
}
@ -113,7 +113,7 @@ static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw)
static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw)
{
hw->rx_clkm_conf.mclk_sel = 1;
}
@ -218,31 +218,65 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S TX clock devider
* @brief Configure I2S TX module clock divider
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
if (set->a == 0 || set->b == 0) {
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
if (denominator == 0 || numerator == 0) {
hw->tx_clkm_div_conf.tx_clkm_div_x = 0;
hw->tx_clkm_div_conf.tx_clkm_div_y = 0;
hw->tx_clkm_div_conf.tx_clkm_div_z = 0;
} else {
if (set->b > set->a / 2) {
hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / (set->a - set->b) - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % (set->a - set->b);
hw->tx_clkm_div_conf.tx_clkm_div_z = set->a - set->b;
if (numerator > denominator / 2) {
hw->tx_clkm_div_conf.tx_clkm_div_x = denominator / (denominator - numerator) - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = denominator % (denominator - numerator);
hw->tx_clkm_div_conf.tx_clkm_div_z = denominator - numerator;
hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 1;
} else {
hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / set->b - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % set->b + 1;
hw->tx_clkm_div_conf.tx_clkm_div_z = set->b;
hw->tx_clkm_div_conf.tx_clkm_div_x = denominator / numerator - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = denominator % numerator + 1;
hw->tx_clkm_div_conf.tx_clkm_div_z = numerator;
hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0;
}
}
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, mclk_div);
}
/**
@ -257,31 +291,66 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S RX clock devider
* @brief Configure I2S RX module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
if (set->a == 0 || set->b == 0) {
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
if (denominator == 0 || numerator == 0) {
hw->rx_clkm_div_conf.rx_clkm_div_x = 0;
hw->rx_clkm_div_conf.rx_clkm_div_y = 0;
hw->rx_clkm_div_conf.rx_clkm_div_z = 0;
} else {
if (set->b > set->a / 2) {
hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / (set->a - set->b) - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % (set->a - set->b);
hw->rx_clkm_div_conf.rx_clkm_div_z = set->a - set->b;
if (numerator > denominator / 2) {
hw->rx_clkm_div_conf.rx_clkm_div_x = denominator / (denominator - numerator) - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = denominator % (denominator - numerator);
hw->rx_clkm_div_conf.rx_clkm_div_z = denominator - numerator;
hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 1;
} else {
hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / set->b - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % set->b + 1;
hw->rx_clkm_div_conf.rx_clkm_div_z = set->b;
hw->rx_clkm_div_conf.rx_clkm_div_x = denominator / numerator - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = denominator % numerator + 1;
hw->rx_clkm_div_conf.rx_clkm_div_z = numerator;
hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0;
}
}
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, mclk_div);
}
/**
@ -503,17 +572,59 @@ static inline void i2s_ll_rx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level)
hw->rx_conf.rx_ws_idle_pol = ws_pol_level;
}
/**
* @brief Enable I2S TX TDM mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_tdm(i2s_dev_t *hw)
{
hw->tx_conf.tx_pdm_en = false;
hw->tx_conf.tx_tdm_en = true;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = false;
}
/**
* @brief Enable I2S RX TDM mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_tdm(i2s_dev_t *hw)
{
hw->rx_conf.rx_pdm_en = false;
hw->rx_conf.rx_tdm_en = true;
}
/**
* @brief Enable I2S TX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
{
i2s_ll_tx_enable_tdm(hw);
}
/**
* @brief Enable I2S RX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
{
i2s_ll_rx_enable_tdm(hw);
}
/**
* @brief Enable TX PDM mode.
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_enable Set true to TX enable PDM mode
*/
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
{
hw->tx_conf.tx_pdm_en = pdm_enable;
hw->tx_conf.tx_tdm_en = !pdm_enable;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable;
hw->tx_conf.tx_pdm_en = true;
hw->tx_conf.tx_tdm_en = false;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = true;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -34,9 +34,9 @@ extern "C" {
/* I2S clock configuration structure */
typedef struct {
uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t mclk_div; // I2S module clock divider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t a;
uint16_t b; // The decimal part of module clock devider, the decimal is: b/a
uint16_t b; // The decimal part of module clock divider, the decimal is: b/a
} i2s_ll_mclk_div_t;
/**
@ -104,7 +104,7 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw)
{
hw->rx_clkm_conf.mclk_sel = 0;
}
@ -114,7 +114,7 @@ static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw)
static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw)
{
hw->rx_clkm_conf.mclk_sel = 1;
}
@ -219,31 +219,65 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S TX clock devider
* @brief Configure I2S TX module clock divider
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
if (set->a == 0 || set->b == 0) {
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
if (denominator == 0 || numerator == 0) {
hw->tx_clkm_div_conf.tx_clkm_div_x = 0;
hw->tx_clkm_div_conf.tx_clkm_div_y = 0;
hw->tx_clkm_div_conf.tx_clkm_div_z = 0;
} else {
if (set->b > set->a / 2) {
hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / (set->a - set->b) - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % (set->a - set->b);
hw->tx_clkm_div_conf.tx_clkm_div_z = set->a - set->b;
if (numerator > denominator / 2) {
hw->tx_clkm_div_conf.tx_clkm_div_x = denominator / (denominator - numerator) - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = denominator % (denominator - numerator);
hw->tx_clkm_div_conf.tx_clkm_div_z = denominator - numerator;
hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 1;
} else {
hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / set->b - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % set->b + 1;
hw->tx_clkm_div_conf.tx_clkm_div_z = set->b;
hw->tx_clkm_div_conf.tx_clkm_div_x = denominator / numerator - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = denominator % numerator + 1;
hw->tx_clkm_div_conf.tx_clkm_div_z = numerator;
hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0;
}
}
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, mclk_div);
}
/**
@ -258,31 +292,66 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S RX clock devider
* @brief Configure I2S RX module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
if (set->a == 0 || set->b == 0) {
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
if (denominator == 0 || numerator == 0) {
hw->rx_clkm_div_conf.rx_clkm_div_x = 0;
hw->rx_clkm_div_conf.rx_clkm_div_y = 0;
hw->rx_clkm_div_conf.rx_clkm_div_z = 0;
} else {
if (set->b > set->a / 2) {
hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / (set->a - set->b) - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % (set->a - set->b);
hw->rx_clkm_div_conf.rx_clkm_div_z = set->a - set->b;
if (numerator > denominator / 2) {
hw->rx_clkm_div_conf.rx_clkm_div_x = denominator / (denominator - numerator) - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = denominator % (denominator - numerator);
hw->rx_clkm_div_conf.rx_clkm_div_z = denominator - numerator;
hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 1;
} else {
hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / set->b - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % set->b + 1;
hw->rx_clkm_div_conf.rx_clkm_div_z = set->b;
hw->rx_clkm_div_conf.rx_clkm_div_x = denominator / numerator - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = denominator % numerator + 1;
hw->rx_clkm_div_conf.rx_clkm_div_z = numerator;
hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0;
}
}
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, mclk_div);
}
/**
@ -504,17 +573,59 @@ static inline void i2s_ll_rx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level)
hw->rx_conf.rx_ws_idle_pol = ws_pol_level;
}
/**
* @brief Enable I2S TX TDM mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_tdm(i2s_dev_t *hw)
{
hw->tx_conf.tx_pdm_en = false;
hw->tx_conf.tx_tdm_en = true;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = false;
}
/**
* @brief Enable I2S RX TDM mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_tdm(i2s_dev_t *hw)
{
hw->rx_conf.rx_pdm_en = false;
hw->rx_conf.rx_tdm_en = true;
}
/**
* @brief Enable I2S TX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
{
i2s_ll_tx_enable_tdm(hw);
}
/**
* @brief Enable I2S RX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
{
i2s_ll_rx_enable_tdm(hw);
}
/**
* @brief Enable TX PDM mode.
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_enable Set true to TX enable PDM mode
*/
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
{
hw->tx_conf.tx_pdm_en = pdm_enable;
hw->tx_conf.tx_tdm_en = !pdm_enable;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable;
hw->tx_conf.tx_pdm_en = true;
hw->tx_conf.tx_tdm_en = false;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = true;
}
/**

View File

@ -29,19 +29,24 @@ extern "C" {
#define I2S_LL_BASE_CLK (2 * APB_CLK_FREQ)
#define I2S_LL_BCK_MAX_PRESCALE (64)
#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6)
#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1)
#define I2S_LL_EVENT_RX_EOF BIT(9)
#define I2S_LL_EVENT_TX_EOF BIT(12)
#define I2S_LL_EVENT_RX_DSCR_ERR BIT(13)
#define I2S_LL_EVENT_TX_DSCR_ERR BIT(14)
#define I2S_INTR_MAX (UINT32_MAX)
/* I2S clock configuration structure */
typedef struct {
uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t mclk_div; // I2S module clock divider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t a;
uint16_t b; // The decimal part of module clock devider, the decimal is: b/a
uint16_t b; // The decimal part of module clock divider, the decimal is: b/a
} i2s_ll_mclk_div_t;
#define I2S_LL_EVENT_TX_EOF (1 << 12)
#define I2S_LL_BCK_MAX_PRESCALE (64)
/**
* @brief Enable DMA descriptor owner check
*
@ -267,16 +272,68 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S TX clock devider
* @brief Configure I2S TX module clock divider
* @note mclk on ESP32S2 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div);
hw->clkm_conf.clkm_div_b = set->b;
hw->clkm_conf.clkm_div_a = set->a;
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, mclk_div);
hw->clkm_conf.clkm_div_b = numerator;
hw->clkm_conf.clkm_div_a = denominator;
}
/**
* @brief Configure I2S module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
* mclk = sclk / (mclk_div + b/a)
*
* @param hw Peripheral I2S hardware instance address.
* @param mclk_div integer part of the division from sclk to mclk
* @param a Denominator of decimal part
* @param b Numerator of decimal part
*/
static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uint32_t a, uint32_t b)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, mclk_div);
hw->clkm_conf.clkm_div_b = b;
hw->clkm_conf.clkm_div_a = a;
}
/**
@ -291,16 +348,17 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S RX clock devider
* @brief Configure I2S RX module clock divider
* @note mclk on ESP32S2 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div);
hw->clkm_conf.clkm_div_b = set->b;
hw->clkm_conf.clkm_div_a = set->a;
i2s_ll_tx_set_mclk(hw, sclk, mclk, mclk_div);
}
/**
@ -327,7 +385,6 @@ static inline void i2s_ll_enable_intr(i2s_dev_t *hw, uint32_t mask, bool en)
static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw)
{
hw->int_ena.out_eof = 1;
hw->int_ena.out_dscr_err = 1;
}
/**
@ -338,7 +395,6 @@ static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw)
static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw)
{
hw->int_ena.out_eof = 0;
hw->int_ena.out_dscr_err = 0;
}
/**
@ -349,7 +405,6 @@ static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw)
static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw)
{
hw->int_ena.in_suc_eof = 1;
hw->int_ena.in_dscr_err = 1;
}
/**
@ -360,7 +415,6 @@ static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw)
static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw)
{
hw->int_ena.in_suc_eof = 0;
hw->int_ena.in_dscr_err = 0;
}
/**
@ -419,15 +473,34 @@ static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw)
hw->lc_conf.in_rst = 0;
}
/**
* @brief Enable I2S TX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
{
hw->conf2.val = 0;
}
/**
* @brief Enable I2S RX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
{
hw->conf2.val = 0;
}
/**
* @brief Enable TX PDM mode.
* @note ESP32-S2 doesn't support pdm
* This function is used to be compatible with those support pdm
*
* @param hw Peripheral I2S hardware instance address (ignored)
* @param pdm_enable Set true to TX enable PDM mode (ignored)
*/
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
{
// Remain empty
}
@ -438,9 +511,8 @@ static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
* This function is used to be compatible with those support pdm
*
* @param hw Peripheral I2S hardware instance address (ignored)
* @param pdm_enable Set true to RX enable PDM mode (ignored)
*/
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw)
{
// Remain empty
}
@ -592,7 +664,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, uint32_t eof_num)
*/
static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
{
hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2);
hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
hw->sample_rate_conf.tx_bits_mod = data_bit;
}
@ -605,7 +677,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int
*/
static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
{
hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2);
hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
hw->sample_rate_conf.rx_bits_mod = data_bit;
}
@ -794,7 +866,7 @@ static inline void i2s_ll_tx_enable_dma_equal(i2s_dev_t *hw, bool en)
static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
{
int data_bit = hw->sample_rate_conf.tx_bits_mod;
hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena;
hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
hw->conf.tx_dma_equal = mono_ena;
hw->conf_chan.tx_chan_mod = mono_ena;
}
@ -808,7 +880,7 @@ static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
{
int data_bit = hw->sample_rate_conf.rx_bits_mod;
hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena;
hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
hw->conf.rx_dma_equal = mono_ena;
hw->conf_chan.rx_chan_mod = mono_ena;
}

View File

@ -34,9 +34,9 @@ extern "C" {
/* I2S clock configuration structure */
typedef struct {
uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t mclk_div; // I2S module clock divider, Fmclk = Fsclk /(mclk_div+b/a)
uint16_t a;
uint16_t b; // The decimal part of module clock devider, the decimal is: b/a
uint16_t b; // The decimal part of module clock divider, the decimal is: b/a
} i2s_ll_mclk_div_t;
/**
@ -104,7 +104,7 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw)
{
hw->rx_clkm_conf.mclk_sel = 0;
}
@ -114,7 +114,7 @@ static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw)
static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw)
{
hw->rx_clkm_conf.mclk_sel = 1;
}
@ -221,31 +221,65 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S TX clock devider
* @brief Configure I2S TX module clock divider
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
if (set->a == 0 || set->b == 0) {
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
if (denominator == 0 || numerator == 0) {
hw->tx_clkm_div_conf.tx_clkm_div_x = 0;
hw->tx_clkm_div_conf.tx_clkm_div_y = 0;
hw->tx_clkm_div_conf.tx_clkm_div_z = 0;
} else {
if (set->b > set->a / 2) {
hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / (set->a - set->b) - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % (set->a - set->b);
hw->tx_clkm_div_conf.tx_clkm_div_z = set->a - set->b;
if (numerator > denominator / 2) {
hw->tx_clkm_div_conf.tx_clkm_div_x = denominator / (denominator - numerator) - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = denominator % (denominator - numerator);
hw->tx_clkm_div_conf.tx_clkm_div_z = denominator - numerator;
hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 1;
} else {
hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / set->b - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % set->b + 1;
hw->tx_clkm_div_conf.tx_clkm_div_z = set->b;
hw->tx_clkm_div_conf.tx_clkm_div_x = denominator / numerator - 1;
hw->tx_clkm_div_conf.tx_clkm_div_y = denominator % numerator + 1;
hw->tx_clkm_div_conf.tx_clkm_div_z = numerator;
hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0;
}
}
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, mclk_div);
}
/**
@ -260,31 +294,66 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
}
/**
* @brief Configure I2S RX clock devider
* @brief Configure I2S RX module clock divider
* @note mclk on ESP32 is shared by both TX and RX channel
*
* @param hw Peripheral I2S hardware instance address.
* @param set Pointer to I2S clock devider configuration paramater
* @param sclk system clock, 0 means use apll
* @param mclk module clock
* @param mclk_div integer part of the division from sclk to mclk
*/
static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set)
static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, uint32_t sclk, uint32_t mclk, uint32_t mclk_div)
{
if (set->a == 0 || set->b == 0) {
int ma = 0;
int mb = 0;
int denominator = 1;
int numerator = 0;
uint32_t freq_diff = abs(sclk - mclk * mclk_div);
if (!freq_diff) {
goto finish;
}
float decimal = freq_diff / (float)mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
mclk_div++;
goto finish;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
int b = (int)(a * (freq_diff / (double)mclk) + 0.5);
ma = freq_diff * a;
mb = mclk * b;
if (ma == mb) {
denominator = a;
numerator = b;
goto finish;
}
if (abs((mb - ma)) < min) {
denominator = a;
numerator = b;
min = abs(mb - ma);
}
}
finish:
if (denominator == 0 || numerator == 0) {
hw->rx_clkm_div_conf.rx_clkm_div_x = 0;
hw->rx_clkm_div_conf.rx_clkm_div_y = 0;
hw->rx_clkm_div_conf.rx_clkm_div_z = 0;
} else {
if (set->b > set->a / 2) {
hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / (set->a - set->b) - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % (set->a - set->b);
hw->rx_clkm_div_conf.rx_clkm_div_z = set->a - set->b;
if (numerator > denominator / 2) {
hw->rx_clkm_div_conf.rx_clkm_div_x = denominator / (denominator - numerator) - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = denominator % (denominator - numerator);
hw->rx_clkm_div_conf.rx_clkm_div_z = denominator - numerator;
hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 1;
} else {
hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / set->b - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % set->b + 1;
hw->rx_clkm_div_conf.rx_clkm_div_z = set->b;
hw->rx_clkm_div_conf.rx_clkm_div_x = denominator / numerator - 1;
hw->rx_clkm_div_conf.rx_clkm_div_y = denominator % numerator + 1;
hw->rx_clkm_div_conf.rx_clkm_div_z = numerator;
hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0;
}
}
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, mclk_div);
}
/**
@ -506,30 +575,72 @@ static inline void i2s_ll_rx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level)
hw->rx_conf.rx_ws_idle_pol = ws_pol_level;
}
/**
* @brief Enable I2S TX TDM mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_tdm(i2s_dev_t *hw)
{
hw->tx_conf.tx_pdm_en = false;
hw->tx_conf.tx_tdm_en = true;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = false;
}
/**
* @brief Enable I2S RX TDM mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_tdm(i2s_dev_t *hw)
{
hw->rx_conf.rx_pdm_en = false;
hw->rx_conf.rx_tdm_en = true;
hw->rx_conf.rx_pdm2pcm_en = false;
}
/**
* @brief Enable I2S TX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
{
i2s_ll_tx_enable_tdm(hw);
}
/**
* @brief Enable I2S RX STD mode
*
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
{
i2s_ll_rx_enable_tdm(hw);
}
/**
* @brief Enable TX PDM mode.
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_enable Set true to TX enable PDM mode
*/
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
{
hw->tx_conf.tx_pdm_en = pdm_enable;
hw->tx_conf.tx_tdm_en = !pdm_enable;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable;
hw->tx_conf.tx_pdm_en = true;
hw->tx_conf.tx_tdm_en = false;
hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = true;
}
/**
* @brief Enable RX PDM mode.
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_enable Set true to RX enable PDM mode
*/
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw)
{
hw->rx_conf.rx_pdm_en = pdm_enable;
hw->rx_conf.rx_tdm_en = !pdm_enable;
hw->rx_conf.rx_pdm2pcm_en = pdm_enable;
hw->rx_conf.rx_pdm_en = true;
hw->rx_conf.rx_tdm_en = false;
hw->rx_conf.rx_pdm2pcm_en = true;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -8,356 +8,282 @@
// The HAL layer for I2S (common part)
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "hal/i2s_hal.h"
/**
* @brief Calculate the closest sample rate clock configuration.
* clock relationship:
* Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a)
*
* @param clk_cfg I2S clock configuration(input)
* @param cal Point to `i2s_ll_mclk_div_t` structure(output).
*/
static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal)
{
int ma = 0;
int mb = 0;
cal->mclk_div = clk_cfg->mclk_div;
cal->a = 1;
cal->b = 0;
#include "hal/i2s_std.h"
#include "hal/i2s_pdm.h"
#include "hal/i2s_tdm.h"
uint32_t freq_diff = abs((int)clk_cfg->sclk - (int)(clk_cfg->mclk * cal->mclk_div));
if (!freq_diff) {
return;
}
float decimal = freq_diff / (float)clk_cfg->mclk;
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
if (decimal > 125.0 / 126.0) {
cal->mclk_div++;
return;
}
uint32_t min = ~0;
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
// Calculate the closest 'b' in this loop, no need to loop 'b' to seek the closest value
int b = (int)(a * (freq_diff / (double)clk_cfg->mclk) + 0.5);
ma = freq_diff * a;
mb = clk_cfg->mclk * b;
if (ma == mb) {
cal->a = a;
cal->b = b;
return;
}
if (abs((mb - ma)) < min) {
cal->a = a;
cal->b = b;
min = abs(mb - ma);
}
}
}
#if SOC_I2S_HW_VERSION_2 && SOC_I2S_SUPPORTS_PDM_TX
/* PDM tx high pass filter cut-off frequency and coeffecients list
* [0]: cut-off frequency; [1]: param0; [2]: param5 */
static const float cut_off_coef[21][3] = {
{185, 0, 0}, {172, 0, 1}, {160, 1, 1},
{150, 1, 2}, {137, 2, 2}, {126, 2, 3},
{120, 0, 3}, {115, 3, 3}, {106, 1, 7},
{104, 2, 4}, {92, 4, 4}, {91.5, 2, 7},
{81, 4, 5}, {77.2, 3, 7}, {69, 5, 5},
{63, 4, 7}, {58, 5, 6}, {49, 5, 7},
{46, 6, 6}, {35.5, 6, 7}, {23.3, 7, 7}};
#endif
void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel)
{
i2s_ll_tx_clk_set_src(hal->dev, sel);
i2s_ll_rx_clk_set_src(hal->dev, sel);
}
void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg)
{
i2s_ll_mclk_div_t mclk_set;
i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set);
i2s_ll_tx_set_clk(hal->dev, &mclk_set);
i2s_ll_tx_set_bck_div_num(hal->dev, clk_cfg->bclk_div);
}
void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg)
{
i2s_ll_mclk_div_t mclk_set;
i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set);
i2s_ll_rx_set_clk(hal->dev, &mclk_set);
i2s_ll_rx_set_bck_div_num(hal->dev, clk_cfg->bclk_div);
}
void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal)
{
i2s_ll_tx_set_slave_mod(hal->dev, false); //TX master
i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave
}
void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal)
{
i2s_ll_tx_set_slave_mod(hal->dev, true); //TX Slave
i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave
}
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num)
void i2s_hal_init(i2s_hal_context_t *hal, int port_id)
{
/* Get hardware instance */
hal->dev = I2S_LL_GET_HW(i2s_num);
hal->dev = I2S_LL_GET_HW(port_id);
}
#if SOC_I2S_SUPPORTS_PDM_TX
void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate)
void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src)
{
/* enable pdm tx mode */
i2s_ll_tx_enable_pdm(hal->dev, true);
#if SOC_I2S_SUPPORTS_TDM
#if SOC_I2S_HW_VERSION_2
i2s_ll_tx_enable_clock(hal->dev);
i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
i2s_ll_mclk_use_tx_clk(hal->dev);
/* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
i2s_ll_tx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
#else
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
i2s_ll_mclk_bind_to_tx_clk(hal->dev);
#endif
/* set pdm tx default presacle */
i2s_ll_tx_set_pdm_prescale(hal->dev, 0);
/* set pdm tx default sacle of high pass filter */
i2s_ll_tx_set_pdm_hp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
/* set pdm tx default sacle of low pass filter */
i2s_ll_tx_set_pdm_lp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
/* set pdm tx default sacle of sinc filter */
i2s_ll_tx_set_pdm_sinc_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
/* set pdm tx default sacle of sigma-delta filter */
i2s_ll_tx_set_pdm_sd_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1);
/* set pdm tx sample rate */
i2s_ll_tx_set_pdm_fpfs(hal->dev, 960, sample_rate / 100);
#if SOC_I2S_SUPPORTS_PDM_CODEC
/* enable pdm high pass filter */
i2s_ll_tx_enable_pdm_hp_filter(hal->dev, true);
/* set pdm tx high pass filter parameters */
i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, 6);
i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, 7);
/* enable pdm sigma-delta codec */
i2s_ll_tx_enable_pdm_sd_codec(hal->dev, true);
/* set pdm tx sigma-delta codec dither */
i2s_ll_tx_set_pdm_sd_dither(hal->dev, 0);
i2s_ll_tx_set_pdm_sd_dither2(hal->dev, 0);
#endif // SOC_I2S_SUPPORTS_PDM_CODEC
i2s_ll_tx_clk_set_src(hal->dev, clk_src);
i2s_ll_tx_set_mclk(hal->dev, clk_info->sclk, clk_info->mclk, clk_info->mclk_div);
i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div);
}
#endif // SOC_I2S_SUPPORTS_PDM_TX
#if SOC_I2S_SUPPORTS_PDM_RX
void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal)
void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src)
{
/* enable pdm rx mode */
i2s_ll_rx_enable_pdm(hal->dev, true);
/* set pdm rx downsample number */
i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S);
#if SOC_I2S_SUPPORTS_TDM
#if SOC_I2S_HW_VERSION_2
i2s_ll_rx_enable_clock(hal->dev);
i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
i2s_ll_mclk_use_rx_clk(hal->dev);
/* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
#else
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
i2s_ll_mclk_bind_to_rx_clk(hal->dev);
#endif
i2s_ll_rx_clk_set_src(hal->dev, clk_src);
i2s_ll_rx_set_mclk(hal->dev, clk_info->sclk, clk_info->mclk, clk_info->mclk_div);
i2s_ll_rx_set_bck_div_num(hal->dev, clk_info->bclk_div);
}
#endif // SOC_I2S_SUPPORTS_PDM_RX
void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
/*-------------------------------------------------------------------------
| STD Specific Slot Configurations |
-------------------------------------------------------------------------*/
void i2s_hal_std_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
{
/* Disable PDM tx mode and enable TDM mode (if support) */
i2s_ll_tx_enable_pdm(hal->dev, false);
#if SOC_I2S_SUPPORTS_TDM
i2s_ll_tx_enable_clock(hal->dev);
i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
i2s_ll_mclk_use_tx_clk(hal->dev);
// In TDM mode(more than 2 channels), the ws polarity should be high first.
if (hal_cfg->total_chan > 2) {
i2s_ll_tx_set_ws_idle_pol(hal->dev, true);
}
i2s_ll_tx_enable_left_align(hal->dev, hal_cfg->left_align);
i2s_ll_tx_enable_big_endian(hal->dev, hal_cfg->big_edin);
i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->bit_order_msb);
i2s_ll_tx_set_skip_mask(hal->dev, hal_cfg->skip_msk);
#else
i2s_ll_tx_enable_msb_right(hal->dev, false);
i2s_ll_tx_enable_right_first(hal->dev, false);
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
#endif
}
void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
{
/* Disable PDM rx mode and enable TDM rx mode (if support)*/
i2s_ll_rx_enable_pdm(hal->dev, false);
#if SOC_I2S_SUPPORTS_TDM
i2s_ll_rx_enable_clock(hal->dev);
i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
i2s_ll_mclk_use_rx_clk(hal->dev);
// In TDM mode(more than 2 channels), the ws polarity should be high first.
if (hal_cfg->total_chan > 2) {
i2s_ll_rx_set_ws_idle_pol(hal->dev, true);
}
i2s_ll_rx_enable_left_align(hal->dev, hal_cfg->left_align);
i2s_ll_rx_enable_big_endian(hal->dev, hal_cfg->big_edin);
i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->bit_order_msb);
#else
i2s_ll_rx_enable_msb_right(hal->dev, false);
i2s_ll_rx_enable_right_first(hal->dev, false);
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
#endif
}
static uint32_t i2s_hal_get_ws_bit(i2s_comm_format_t fmt, uint32_t chan_num, uint32_t chan_bits)
{
switch (fmt) {
case I2S_COMM_FORMAT_STAND_MSB:
return chan_num * chan_bits / 2;
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
return 1;
case I2S_COMM_FORMAT_STAND_PCM_LONG:
return chan_bits;
default: //I2S_COMM_FORMAT_STAND_I2S
return chan_num * chan_bits / 2;
}
}
void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
{
uint32_t chan_num = 2;
uint32_t chan_bits = hal_cfg->chan_bits;
uint32_t data_bits = hal_cfg->sample_bits;
bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) ||
(hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT);
/* Set channel number and valid data bits */
#if SOC_I2S_SUPPORTS_TDM
chan_num = hal_cfg->total_chan;
i2s_ll_tx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
i2s_ll_tx_set_chan_num(hal->dev, chan_num);
#endif
i2s_ll_tx_set_sample_bit(hal->dev, chan_bits, data_bits);
i2s_ll_tx_enable_mono_mode(hal->dev, is_mono);
/* Set communication format */
bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false;
uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits);
i2s_ll_tx_enable_msb_shift(hal->dev, shift_en);
i2s_ll_tx_set_ws_width(hal->dev, ws_width);
#if SOC_I2S_SUPPORTS_TDM
i2s_ll_tx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2);
#endif
}
void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
{
uint32_t chan_num = 2;
uint32_t chan_bits = hal_cfg->chan_bits;
uint32_t data_bits = hal_cfg->sample_bits;
bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) ||
(hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT);
#if SOC_I2S_SUPPORTS_TDM
chan_num = hal_cfg->total_chan;
i2s_ll_rx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
i2s_ll_rx_set_chan_num(hal->dev, chan_num);
#endif
i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits);
i2s_ll_rx_enable_mono_mode(hal->dev, is_mono);
/* Set communication format */
bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false;
uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits);
i2s_ll_rx_enable_msb_shift(hal->dev, shift_en);
i2s_ll_rx_set_ws_width(hal->dev, ws_width);
#if SOC_I2S_SUPPORTS_TDM
i2s_ll_rx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2);
#endif
}
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
{
#if SOC_I2S_SUPPORTS_ADC
if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) {
/* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel.
* In the current stage, we only support ADC1 and single channel mode.
* In default data mode, the ADC data is in 12-bit resolution mode.
*/
i2s_ll_enable_builtin_adc(hal->dev, true);
return;
}
i2s_ll_enable_builtin_adc(hal->dev, false);
#endif
#if SOC_I2S_SUPPORTS_DAC
if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) {
i2s_ll_enable_builtin_dac(hal->dev, true);
return;
}
i2s_ll_enable_builtin_dac(hal->dev, false);
#endif
/* Set configurations for TX mode */
if (hal_cfg->mode & I2S_MODE_TX) {
i2s_ll_tx_stop(hal->dev);
i2s_std_slot_config_t *slot_cfg = (i2s_std_slot_config_t*)slot_config;
uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
i2s_ll_tx_reset(hal->dev);
i2s_ll_tx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //TX Slave
#if SOC_I2S_SUPPORTS_PDM_TX
if (hal_cfg->mode & I2S_MODE_PDM) {
/* Set tx pdm mode */
i2s_hal_tx_set_pdm_mode_default(hal, hal_cfg->sample_rate);
} else
i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->ws_width);
#if SOC_I2S_HW_VERSION_1
i2s_ll_tx_enable_msb_right(hal->dev, slot_cfg->msb_right);
i2s_ll_tx_enable_right_first(hal->dev, slot_cfg->ws_pol);
/* Should always enable fifo */
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
#elif SOC_I2S_HW_VERSION_2
/* There are always 2 slots in std mode */
i2s_ll_tx_set_chan_num(hal->dev, 2);
/* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot
* Otherwise always enable the first two slots */
i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 0x01 : 0x03);
i2s_ll_tx_set_half_sample_bit(hal->dev, slot_bit_width);
i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->left_align);
i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->big_endian);
#endif
{
/* Set tx common mode */
i2s_hal_tx_set_common_mode(hal, hal_cfg);
}
i2s_hal_tx_set_channel_style(hal, hal_cfg);
}
/* Set configurations for RX mode */
if (hal_cfg->mode & I2S_MODE_RX) {
i2s_ll_rx_stop(hal->dev);
void i2s_hal_std_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
{
i2s_std_slot_config_t *slot_cfg = (i2s_std_slot_config_t*)slot_config;
uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
i2s_ll_rx_reset(hal->dev);
i2s_ll_rx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //RX Slave
#if SOC_I2S_SUPPORTS_PDM_RX
if (hal_cfg->mode & I2S_MODE_PDM) {
/* Set rx pdm mode */
i2s_hal_rx_set_pdm_mode_default(hal);
} else
i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->ws_width);
#if SOC_I2S_HW_VERSION_1
i2s_ll_rx_enable_msb_right(hal->dev, slot_cfg->msb_right);
i2s_ll_rx_enable_right_first(hal->dev, slot_cfg->ws_pol);
/* Should always enable fifo */
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
#elif SOC_I2S_HW_VERSION_2
/* There are always 2 slots in std mode */
i2s_ll_rx_set_chan_num(hal->dev, 2);
/* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot
* Otherwise always enable the first two slots */
i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 0x01 : 0x03);
i2s_ll_rx_set_half_sample_bit(hal->dev, slot_bit_width);
i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->left_align);
i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->big_endian);
#endif
{
/* Set rx common mode */
i2s_hal_rx_set_common_mode(hal, hal_cfg);
}
i2s_hal_rx_set_channel_style(hal, hal_cfg);
}
/* Set configurations for full-duplex mode */
if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) {
i2s_ll_share_bck_ws(hal->dev, true);
if (hal_cfg->mode & I2S_MODE_MASTER) {
i2s_hal_enable_master_fd_mode(hal);
void i2s_hal_std_enable_tx_channel(i2s_hal_context_t *hal)
{
i2s_ll_tx_enable_std(hal->dev);
}
void i2s_hal_std_enable_rx_channel(i2s_hal_context_t *hal)
{
i2s_ll_rx_enable_std(hal->dev);
}
/*-------------------------------------------------------------------------
| PDM Specific Slot Configurations |
-------------------------------------------------------------------------*/
#if SOC_I2S_SUPPORTS_PDM_TX
void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
{
i2s_pdm_tx_slot_config_t *slot_cfg = (i2s_pdm_tx_slot_config_t *)slot_config;
uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
i2s_ll_tx_reset(hal->dev);
i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
i2s_ll_tx_set_pdm_prescale(hal->dev, slot_cfg->sd_prescale);
i2s_ll_tx_set_pdm_hp_scale(hal->dev, slot_cfg->hp_scale);
i2s_ll_tx_set_pdm_lp_scale(hal->dev, slot_cfg->lp_scale);
i2s_ll_tx_set_pdm_sinc_scale(hal->dev, slot_cfg->sinc_scale);
i2s_ll_tx_set_pdm_sd_scale(hal->dev, slot_cfg->sd_scale);
#if SOC_I2S_HW_VERSION_1
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
#elif SOC_I2S_HW_VERSION_2
/* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
i2s_ll_tx_set_active_chan_mask(hal->dev, I2S_TDM_SLOT0 | I2S_TDM_SLOT1);
i2s_ll_tx_enable_pdm_hp_filter(hal->dev, slot_cfg->hp_en);
uint8_t cnt = 0;
float min = 1000;
float expt_cut_off = slot_cfg->hp_cut_off_freq_hz;
/* Find the closest cut-off frequency and its coefficients */
for (int i = 0; i < 21; i++) {
float tmp = cut_off_coef[i][0] < expt_cut_off ? expt_cut_off - cut_off_coef[i][0] : cut_off_coef[i][0] - expt_cut_off;
if (tmp < min) {
min = tmp;
cnt = i;
}
}
i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, cut_off_coef[cnt][1]);
i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, cut_off_coef[cnt][2]);
i2s_ll_tx_enable_pdm_sd_codec(hal->dev, slot_cfg->sd_en);
i2s_ll_tx_set_pdm_sd_dither(hal->dev, slot_cfg->sd_dither);
i2s_ll_tx_set_pdm_sd_dither2(hal->dev, slot_cfg->sd_dither2);
#endif
}
void i2s_hal_pdm_enable_tx_channel(i2s_hal_context_t *hal)
{
i2s_ll_tx_enable_pdm(hal->dev);
}
#endif
#if SOC_I2S_SUPPORTS_PDM_RX
void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
{
i2s_pdm_rx_slot_config_t *slot_cfg = (i2s_pdm_rx_slot_config_t *)slot_config;
uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
i2s_ll_rx_reset(hal->dev);
i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
#if SOC_I2S_HW_VERSION_1
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
#elif SOC_I2S_HW_VERSION_2
/* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_SLOT0 | I2S_TDM_SLOT1);
#endif
}
void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal)
{
i2s_ll_rx_enable_pdm(hal->dev);
}
#endif
/*-------------------------------------------------------------------------
| TDM Specific Slot Configurations |
-------------------------------------------------------------------------*/
#if SOC_I2S_SUPPORTS_TDM
void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
{
i2s_tdm_slot_config_t *slot_cfg = (i2s_tdm_slot_config_t*)slot_config;
uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
uint32_t cnt;
uint32_t msk = slot_cfg->slot_mask;
/* Get the maximum slot number */
cnt = 32 - __builtin_clz(msk);
/* There should be at least 2 slots in total even for mono mode */
cnt = cnt < 2 ? 2 : cnt;
uint32_t total_slot = slot_cfg->total_slot > cnt ? slot_cfg->total_slot : cnt;
i2s_ll_tx_reset(hal->dev);
i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
if (slot_cfg->ws_width == I2S_TDM_AUTO_WS_WIDTH) {
i2s_ll_tx_set_ws_width(hal->dev, (total_slot * slot_bit_width) / 2);
} else {
i2s_hal_enable_slave_fd_mode(hal);
}
}
i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->ws_width);
}
void i2s_hal_start_tx(i2s_hal_context_t *hal)
{
i2s_ll_tx_start(hal->dev);
i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
i2s_ll_tx_set_chan_num(hal->dev, total_slot);
/* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */
i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ?
I2S_TDM_SLOT0 : (uint32_t)slot_cfg->slot_mask);
i2s_ll_tx_set_skip_mask(hal->dev, slot_cfg->skip_mask);
i2s_ll_tx_set_half_sample_bit(hal->dev, total_slot * slot_bit_width / 2);
i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->left_align);
i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->big_endian);
}
void i2s_hal_start_rx(i2s_hal_context_t *hal)
void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
{
i2s_ll_rx_start(hal->dev);
i2s_tdm_slot_config_t *slot_cfg = (i2s_tdm_slot_config_t*)slot_config;
uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
uint32_t cnt;
uint32_t msk = slot_cfg->slot_mask;
for (cnt = 0; msk; cnt++, msk >>= 1);
/* Get the maximum slot number */
cnt = 32 - __builtin_clz(msk);
/* There should be at least 2 slots in total even for mono mode */
cnt = cnt < 2 ? 2 : cnt;
uint32_t total_slot = slot_cfg->total_slot > cnt ? slot_cfg->total_slot : cnt;
i2s_ll_rx_reset(hal->dev);
i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
if (slot_cfg->ws_width == I2S_TDM_AUTO_WS_WIDTH) {
i2s_ll_rx_set_ws_width(hal->dev, (total_slot * slot_bit_width) / 2);
} else {
i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->ws_width);
}
void i2s_hal_stop_tx(i2s_hal_context_t *hal)
{
i2s_ll_tx_stop(hal->dev);
i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
i2s_ll_rx_set_chan_num(hal->dev, total_slot);
/* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */
i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ?
I2S_TDM_SLOT0 : (uint32_t)slot_cfg->slot_mask);
i2s_ll_rx_set_half_sample_bit(hal->dev, total_slot * slot_bit_width / 2);
i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->left_align);
i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->big_endian);
}
void i2s_hal_stop_rx(i2s_hal_context_t *hal)
void i2s_hal_tdm_enable_tx_channel(i2s_hal_context_t *hal)
{
i2s_ll_rx_stop(hal->dev);
i2s_ll_tx_enable_tdm(hal->dev);
}
void i2s_hal_tdm_enable_rx_channel(i2s_hal_context_t *hal)
{
i2s_ll_rx_enable_tdm(hal->dev);
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,15 +15,36 @@
#pragma once
#include "soc/i2s_periph.h"
#include "soc/soc_caps.h"
#include "hal/i2s_types.h"
#include "hal/i2s_types_priv.h"
#include "hal/i2s_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief General clock configuration information
* @note It is a general purpose struct, not supposed to be used directly by user
*/
typedef struct {
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
} i2s_clk_config_t;
/**
* @brief General slot configuration information
* @note It is a general purpose struct, not supposed to be used directly by user
*/
typedef struct {
i2s_comm_mode_t mode; /*!< I2S communication mode, this field is for identification (MUST match the communication mode that applied) */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample) */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
} i2s_slot_config_t;
/**
* @brief I2S clock configuration
*/
@ -33,344 +54,212 @@ typedef struct {
uint32_t bclk; /*!< I2S bit clock */
uint16_t mclk_div; /*!< I2S master clock division */
uint16_t bclk_div; /*!< I2S bit clock division*/
} i2s_hal_clock_cfg_t;
/**
* @brief I2S HAL configurations
*/
typedef struct {
i2s_mode_t mode; /*!< I2S work mode, using ored mask of `i2s_mode_t`*/
uint32_t sample_rate; /*!< I2S sample rate*/
i2s_comm_format_t comm_fmt; /*!< I2S communication format */
i2s_channel_fmt_t chan_fmt; /*!< I2S channel format, there are total 16 channels in TDM mode.*/
uint32_t sample_bits; /*!< I2S sample bits in one channel */
uint32_t chan_bits; /*!< I2S total bits in one channel. Should not be smaller than 'sample_bits', default '0' means equal to 'sample_bits' */
uint32_t active_chan; /*!< I2S active channel number */
uint32_t total_chan; /*!< Total number of I2S channels */
#if SOC_I2S_SUPPORTS_TDM
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). */
bool left_align; /*!< Set to enable left aligment */
bool big_edin; /*!< Set to enable big edin */
bool bit_order_msb; /*!< Set to enable msb order */
bool skip_msk; /*!< 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 */
#endif
} i2s_hal_config_t;
} i2s_clock_info_t;
/**
* Context that should be maintained by both the driver and the HAL
*/
typedef struct {
i2s_dev_t *dev;
uint32_t version;
i2s_dev_t *dev; /*!< I2S instance address */
} i2s_hal_context_t;
/**
* @brief Enable I2S module clock
* @brief Init I2S hal context
*
* @param hal Context of the HAL layer
* @param port_id The I2S port number, the max port number is (I2S_NUM_MAX -1)
*/
#define i2s_hal_enable_module_clock(hal) i2s_ll_enable_clock((hal)->dev);
void i2s_hal_init(i2s_hal_context_t *hal, int port_id);
/**
* @brief Disable I2S module clock
* @brief Set tx channel clock
*
* @param hal Context of the HAL layer
* @param clk_info clock information
* @param clk_src clock source
*/
void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src);
/**
* @brief Set rx channel clock
*
* @param hal Context of the HAL layer
* @param clk_info clock information
* @param clk_src clock source
*/
void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src);
/*-------------------------------------------------------------------------
| STD configuration |
-------------------------------------------------------------------------*/
/**
* @brief Set tx slot to standard mode
*
* @param hal Context of the HAL layer
* @param is_slave If is slave role
* @param slot_config General slot configuration pointer, but will specified to i2s standard mode
*/
void i2s_hal_std_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config);
/**
* @brief Set rx slot to standard mode
*
* @param hal Context of the HAL layer
* @param is_slave If is slave role
* @param slot_config General slot configuration pointer, but will specified to i2s standard mode
*/
void i2s_hal_std_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config);
/**
* @brief Enable tx channel as standard mode
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_module_clock(hal) i2s_ll_disable_clock((hal)->dev);
void i2s_hal_std_enable_tx_channel(i2s_hal_context_t *hal);
/**
* @brief Enable rx channel as standard mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_std_enable_rx_channel(i2s_hal_context_t *hal);
/*-------------------------------------------------------------------------
| PDM configuration |
-------------------------------------------------------------------------*/
#if SOC_I2S_SUPPORTS_PDM
#if SOC_I2S_SUPPORTS_PDM_TX
/**
* @brief Set tx slot to pdm mode
*
* @param hal Context of the HAL layer
* @param is_slave If is slave role
* @param slot_config General slot configuration pointer, but will specified to i2s pdm tx mode
*/
void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config);
/**
* @brief Enable tx channel as pdm mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_pdm_enable_tx_channel(i2s_hal_context_t *hal);
#endif // SOC_I2S_SUPPORTS_PDM_TX
#if SOC_I2S_SUPPORTS_PDM_RX
/**
* @brief Set rx slot to pdm mode
*
* @param hal Context of the HAL layer
* @param is_slave If is slave role
* @param slot_config General slot configuration pointer, but will specified to i2s pdm rx mode
*/
void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config);
/**
* @brief Enable rx channel as pdm mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal);
#endif // SOC_I2S_SUPPORTS_PDM_RX
#endif // SOC_I2S_SUPPORTS_PDM
/*-------------------------------------------------------------------------
| TDM configuration |
-------------------------------------------------------------------------*/
#if SOC_I2S_SUPPORTS_TDM
/**
* @brief Set tx slot to tdm mode
*
* @param hal Context of the HAL layer
* @param is_slave If is slave role
* @param slot_config General slot configuration pointer, but will specified to i2s tdm mode
*/
void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config);
/**
* @brief Set rx slot to tdm mode
*
* @param hal Context of the HAL layer
* @param is_slave If is slave role
* @param slot_config General slot configuration pointer, but will specified to i2s tdm mode
*/
void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config);
/**
* @brief Enable tx channel as tdm mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_tdm_enable_tx_channel(i2s_hal_context_t *hal);
/**
* @brief Enable rx channel as tdm mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_tdm_enable_rx_channel(i2s_hal_context_t *hal);
#endif
/**
* @brief Start I2S TX channel
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_tx_start(hal) i2s_ll_tx_start((hal)->dev)
/**
* @brief Stop I2S TX channel
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_tx_stop(hal) i2s_ll_tx_stop((hal)->dev)
/**
* @brief Reset I2S TX channel
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_reset_tx(hal) i2s_ll_tx_reset((hal)->dev)
#define i2s_hal_tx_reset(hal) i2s_ll_tx_reset((hal)->dev)
/**
* @brief Reset I2S TX fifo
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_reset_tx_fifo(hal) i2s_ll_tx_reset_fifo((hal)->dev)
#define i2s_hal_tx_reset_fifo(hal) i2s_ll_tx_reset_fifo((hal)->dev)
/**
* @brief Start I2S RX channel
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_rx_start(hal) i2s_ll_rx_start((hal)->dev)
/**
* @brief Stop I2S RX channel
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_rx_stop(hal) i2s_ll_rx_stop((hal)->dev)
/**
* @brief Reset I2S RX channel
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_reset_rx(hal) i2s_ll_rx_reset((hal)->dev)
#define i2s_hal_rx_reset(hal) i2s_ll_rx_reset((hal)->dev)
/**
* @brief Reset I2S RX fifo
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_reset_rx_fifo(hal) i2s_ll_rx_reset_fifo((hal)->dev)
#define i2s_hal_rx_reset_fifo(hal) i2s_ll_rx_reset_fifo((hal)->dev)
/**
* @brief Get I2S hardware instance and enable I2S module clock
* @note This function should be called first before other hal layer function is called
*
* @param hal Context of the HAL layer
* @param i2s_num The uart port number, the max port number is (I2S_NUM_MAX -1)
*/
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num);
/**
* @brief Configure I2S source clock
*
* @param hal Context of the HAL layer
* @param sel The source clock index
*/
void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel);
/**
* @brief Set Tx channel style
*
* @param hal Context of the HAL layer
* @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t`
*/
void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
/**
* @brief Set Rx channel style
*
* @param hal Context of the HAL layer
* @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t`
*/
void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
/**
* @brief Initialize I2S hardware
*
* @param hal Context of the HAL layer
* @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t`
*/
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
/**
* @brief Enable I2S master full-duplex mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal);
/**
* @brief Enable I2S slave full-duplex mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal);
/**
* @brief Start I2S tx
*
* @param hal Context of the HAL layer
*/
void i2s_hal_start_tx(i2s_hal_context_t *hal);
/**
* @brief Start I2S rx
*
* @param hal Context of the HAL layer
*/
void i2s_hal_start_rx(i2s_hal_context_t *hal);
/**
* @brief Stop I2S tx
*
* @param hal Context of the HAL layer
*/
void i2s_hal_stop_tx(i2s_hal_context_t *hal);
/**
* @brief Stop I2S rx
*
* @param hal Context of the HAL layer
*/
void i2s_hal_stop_rx(i2s_hal_context_t *hal);
/**
* @brief Set the received data length to trigger `in_suc_eof` interrupt.
*
* @param hal Context of the HAL layer
* @param eof_byte The byte length that trigger in_suc_eof interrupt.
*/
#define i2s_hal_set_rx_eof_num(hal, eof_byte) i2s_ll_rx_set_eof_num((hal)->dev, eof_byte)
/**
* @brief Set I2S TX sample bit
*
* @param hal Context of the HAL layer
* @param chan_bit I2S TX chan bit
* @param data_bit The sample data bit length.
*/
#define i2s_hal_set_tx_sample_bit(hal, chan_bit, data_bit) i2s_ll_tx_set_sample_bit((hal)->dev, chan_bit, data_bit)
/**
* @brief Set I2S RX sample bit
*
* @param hal Context of the HAL layer
* @param chan_bit I2S RX chan bit
* @param data_bit The sample data bit length.
*/
#define i2s_hal_set_rx_sample_bit(hal, chan_bit, data_bit) i2s_ll_rx_set_sample_bit((hal)->dev, chan_bit, data_bit)
/**
* @brief Configure I2S TX module clock devider
*
* @param hal Context of the HAL layer
* @param clk_cfg I2S clock configuration
*/
void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg);
/**
* @brief Configure I2S RX module clock devider
*
* @param hal Context of the HAL layer
* @param clk_cfg I2S clock configuration
*/
void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg);
/**
* @brief Set I2S tx clock source
*
* @param hal Context of the HAL layer
* @param clk_src i2s tx clock source (see 'i2s_clock_src_t')
*/
#define i2s_hal_tx_set_clock_source(hal, clk_src) i2s_ll_tx_clk_set_src((hal)->dev, clk_src)
/**
* @brief Set I2S rx clock source
*
* @param hal Context of the HAL layer
* @param clk_src i2s rx clock source (see 'i2s_clock_src_t')
*/
#define i2s_hal_rx_set_clock_source(hal, clk_src) i2s_ll_rx_clk_set_src((hal)->dev, clk_src)
/**
* @brief Enable I2S tx slave mode
*
* @param hal Context of the HAL layer
* @param enable set 'true' to enable tx slave mode
*/
#define i2s_hal_tx_enable_slave_mode(hal, enable) i2s_ll_tx_set_slave_mod((hal)->dev, enable)
/**
* @brief Enable I2S rx slave mode
*
* @param hal Context of the HAL layer
* @param enable set 'true' to enable rx slave mode
*/
#define i2s_hal_rx_enable_slave_mode(hal, enable) i2s_ll_rx_set_slave_mod((hal)->dev, enable)
/**
* @brief Enable loopback mode
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_sig_loopback(hal) i2s_ll_share_bck_ws((hal)->dev, true)
/**
* @brief Set I2S configuration for common TX mode
* @note Common mode is for non-PDM mode like philip/MSB/PCM
*
* @param hal Context of the HAL layer
* @param hal_cfg hal configuration structure
*/
void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
/**
* @brief Set I2S configuration for common RX mode
* @note Common mode is for non-PDM mode like philip/MSB/PCM
*
* @param hal Context of the HAL layer
* @param hal_cfg hal configuration structure
*/
void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
#if SOC_I2S_SUPPORTS_PCM
/**
* @brief Configure I2S TX PCM encoder or decoder.
*
* @param hal Context of the HAL layer
* @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t`
*/
#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_set_pcm_type((hal)->dev, cfg)
/**
* @brief Configure I2S RX PCM encoder or decoder.
*
* @param hal Context of the HAL layer
* @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t`
*/
#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_set_pcm_type((hal)->dev, cfg)
#endif
#if SOC_I2S_SUPPORTS_PDM_TX
/**
* @brief Configure I2S TX PDM sample rate
* Fpdm = 64*Fpcm*fp/fs
*
* @param hal Context of the HAL layer
* @param fp TX PDM fp paramater configuration
* @param fs TX PDM fs paramater configuration
*/
#define i2s_hal_set_tx_pdm_fpfs(hal, fp, fs) i2s_ll_tx_set_pdm_fpfs((hal)->dev, fp, fs)
/**
* @brief Get I2S TX PDM fp
*
* @param hal Context of the HAL layer
* @return
* - fp configuration paramater
*/
#define i2s_hal_get_tx_pdm_fp(hal) i2s_ll_tx_get_pdm_fp((hal)->dev)
/**
* @brief Get I2S TX PDM fs
*
* @param hal Context of the HAL layer
* @return
* - fs configuration paramater
*/
#define i2s_hal_get_tx_pdm_fs(hal) i2s_ll_tx_get_pdm_fs((hal)->dev)
/**
* @brief Set I2S default configuration for PDM TX mode
*
* @param hal Context of the HAL layer
* @param sample_rate PDM sample rate
*/
void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate);
#endif
#if SOC_I2S_SUPPORTS_PDM_RX
/**
* @brief Configure RX PDM downsample
*
* @param hal Context of the HAL layer
* @param dsr PDM downsample configuration paramater
*/
#define i2s_hal_set_rx_pdm_dsr(hal, dsr) i2s_ll_rx_set_pdm_dsr((hal)->dev, dsr)
/**
* @brief Get RX PDM downsample configuration
*
* @param hal Context of the HAL layer
* @param dsr Pointer to accept PDM downsample configuration
*/
#define i2s_hal_get_rx_pdm_dsr(hal, dsr) i2s_ll_rx_get_pdm_dsr((hal)->dev, dsr)
/**
* @brief Set I2S default configuration for PDM R mode
*
* @param hal Context of the HAL layer
*/
void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal);
#endif
#if !SOC_GDMA_SUPPORTED
/**
@ -378,28 +267,28 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal);
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_tx_dma(hal) i2s_ll_enable_dma((hal)->dev,true)
#define i2s_hal_tx_enable_dma(hal) i2s_ll_enable_dma((hal)->dev,true)
/**
* @brief Enable I2S RX DMA
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_rx_dma(hal) i2s_ll_enable_dma((hal)->dev,true)
#define i2s_hal_rx_enable_dma(hal) i2s_ll_enable_dma((hal)->dev,true)
/**
* @brief Disable I2S TX DMA
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_tx_dma(hal) i2s_ll_enable_dma((hal)->dev,false)
#define i2s_hal_tx_disable_dma(hal) i2s_ll_enable_dma((hal)->dev,false)
/**
* @brief Disable I2S RX DMA
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_rx_dma(hal) i2s_ll_enable_dma((hal)->dev,false)
#define i2s_hal_rx_disable_dma(hal) i2s_ll_enable_dma((hal)->dev,false)
/**
* @brief Get I2S interrupt status
@ -423,28 +312,28 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal);
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_rx_intr(hal) i2s_ll_rx_enable_intr((hal)->dev)
#define i2s_hal_rx_enable_intr(hal) i2s_ll_rx_enable_intr((hal)->dev)
/**
* @brief Disable I2S RX interrupt
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_rx_intr(hal) i2s_ll_rx_disable_intr((hal)->dev)
#define i2s_hal_rx_disable_intr(hal) i2s_ll_rx_disable_intr((hal)->dev)
/**
* @brief Disable I2S TX interrupt
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_tx_intr(hal) i2s_ll_tx_disable_intr((hal)->dev)
#define i2s_hal_tx_disable_intr(hal) i2s_ll_tx_disable_intr((hal)->dev)
/**
* @brief Enable I2S TX interrupt
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_tx_intr(hal) i2s_ll_tx_enable_intr((hal)->dev)
#define i2s_hal_tx_enable_intr(hal) i2s_ll_tx_enable_intr((hal)->dev)
/**
* @brief Configure TX DMA descriptor address and start TX DMA
@ -452,7 +341,7 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal);
* @param hal Context of the HAL layer
* @param link_addr DMA descriptor link address.
*/
#define i2s_hal_start_tx_link(hal, link_addr) i2s_ll_tx_start_link((hal)->dev, link_addr)
#define i2s_hal_tx_start_link(hal, link_addr) i2s_ll_tx_start_link((hal)->dev, link_addr)
/**
* @brief Configure RX DMA descriptor address and start RX DMA
@ -460,35 +349,35 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal);
* @param hal Context of the HAL layer
* @param link_addr DMA descriptor link address.
*/
#define i2s_hal_start_rx_link(hal, link_addr) i2s_ll_rx_start_link((hal)->dev, link_addr)
#define i2s_hal_rx_start_link(hal, link_addr) i2s_ll_rx_start_link((hal)->dev, link_addr)
/**
* @brief Stop TX DMA link
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_stop_tx_link(hal) i2s_ll_tx_stop_link((hal)->dev)
#define i2s_hal_tx_stop_link(hal) i2s_ll_tx_stop_link((hal)->dev)
/**
* @brief Stop RX DMA link
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_stop_rx_link(hal) i2s_ll_rx_stop_link((hal)->dev)
#define i2s_hal_rx_stop_link(hal) i2s_ll_rx_stop_link((hal)->dev)
/**
* @brief Reset RX DMA
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_reset_rxdma(hal) i2s_ll_rx_reset_dma((hal)->dev)
#define i2s_hal_rx_reset_dma(hal) i2s_ll_rx_reset_dma((hal)->dev)
/**
* @brief Reset TX DMA
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_reset_txdma(hal) i2s_ll_tx_reset_dma((hal)->dev)
#define i2s_hal_tx_reset_dma(hal) i2s_ll_tx_reset_dma((hal)->dev)
/**
* @brief Get I2S out eof descriptor address
@ -507,38 +396,6 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal);
#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_rx_get_eof_des_addr((hal)->dev, addr)
#endif
#if SOC_I2S_SUPPORTS_ADC
/**
* @brief Enable Builtin DAC
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_builtin_dac(hal) i2s_ll_enable_builtin_dac((hal)->dev, true);
/**
* @brief Enable Builtin ADC
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_enable_builtin_adc(hal) i2s_ll_enable_builtin_adc((hal)->dev, true);
/**
* @brief Disable Builtin ADC
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_builtin_adc(hal) i2s_ll_enable_builtin_adc((hal)->dev, false);
#endif
#if SOC_I2S_SUPPORTS_DAC
/**
* @brief Disable Builtin DAC
*
* @param hal Context of the HAL layer
*/
#define i2s_hal_disable_builtin_dac(hal) i2s_ll_enable_builtin_dac((hal)->dev, false);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,195 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file is specified for I2S PDM communication mode
* Features:
* - Only support PDM tx/rx mode
* - Fixed to 2 slots
* - Data bit width only support 16 bits
*/
#pragma once
#include "hal/i2s_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_I2S_SUPPORTS_PDM_RX
/**
* @brief PDM format in 2 slots(RX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_RX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_PDM, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
}
/**
* @brief i2s default pdm rx clock configuration
* @param rate sample rate
*/
#define I2S_PDM_RX_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_D2CLK, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
.dn_sample_mode = I2S_PDM_DSR_8S \
}
/**
* @breif I2S slot configuration for pdm rx mode
*/
typedef struct {
/* General fields */
i2s_comm_mode_t mode; /*!< I2S communication mode, this field is for identification (MUST match the communication mode in 'i2s_chan_config_t') */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample), only support 16 bits for PDM mode */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) , only support 16 bits for PDM mode */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
} i2s_pdm_rx_slot_config_t;
/**
* @breif I2S clock configuration for pdm rx mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
/* Particular fields */
i2s_pdm_dsr_t dn_sample_mode; /*!< Down-sampling rate mode */
} i2s_pdm_rx_clk_config_t;
#endif // SOC_I2S_SUPPORTS_PDM_RX
#if SOC_I2S_SUPPORTS_PDM_TX
#if SOC_I2S_HW_VERSION_2
/**
* @brief PDM style in 2 slots(TX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_TX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_PDM, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.sd_prescale = 0, \
.sd_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.hp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.lp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.sinc_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.sd_en = true, \
.hp_en = true, \
.hp_cut_off_freq_hz = 49, \
.sd_dither = 0, \
.sd_dither2 = 0, \
}
#else
/**
* @brief PDM style in 2 slots(TX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_TX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_PDM, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.dma_desc_num = 8, \
.dma_frame_num = 200, \
.auto_clear = false, \
.slot_mode = mono_or_stereo, \
.sd_prescale = 0, \
.sd_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.hp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.lp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.sinc_scale = I2S_PDM_SIG_SCALING_MUL_1, \
}
#endif // SOC_I2S_HW_VERSION_2
/**
* @brief i2s default pdm tx clock configuration
* @note TX PDM can only be set to the following two up-sampling rate configurations:
* 1: fp = 960, fs = sample_rate_hz / 100, in this case, Fpdm = 128*48000
* 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate_hz
* If the pdm receiver do not care the pdm serial clock, it's recommended set Fpdm = 128*48000.
* Otherwise, the second configuration should be applied.
* @param rate sample rate
*/
#define I2S_PDM_TX_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_D2CLK, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
.up_sample_fp = 960, \
.up_sample_fs = ((rate) / 100), \
}
/*
High Pass Filter Cut-off Frequency Sheet
+----------------+------------------+----------------+------------------+----------------+------------------+
| param0, param5 | cut-off freq(Hz) | param0, param5 | cut-off freq(Hz) | param0, param5 | cut-off freq(Hz) |
+----------------+------------------+----------------+------------------+----------------+------------------+
| (0, 0) | 185 | (3, 3) | 115 | (5, 5) | 69 |
| (0, 1) | 172 | (1, 7) | 106 | (4, 7) | 63 |
| (1, 1) | 160 | (2, 4) | 104 | (5, 6) | 58 |
| (1, 2) | 150 | (4, 4) | 92 | (5, 7) | 49 |
| (2, 2) | 137 | (2, 7) | 91.5 | (6, 6) | 46 |
| (2, 3) | 126 | (4, 5) | 81 | (6, 7) | 35.5 |
| (0, 3) | 120 | (3, 7) | 77.2 | (7, 7) | 23.3 |
+----------------+------------------+----------------+------------------+----------------+------------------+
*/
/**
* @brief I2S slot configuration for pdm tx mode
*/
typedef struct {
/* General fields */
i2s_comm_mode_t mode; /*!< I2S communication mode, this field is for identification (MUST match the communication mode in 'i2s_chan_config_t') */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample), only support 16 bits for PDM mode */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot), only support 16 bits for PDM mode */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
/* Particular fields */
uint32_t sd_prescale; /*!< Sigma-delta filter prescale */
i2s_pdm_sig_scale_t sd_scale; /*!< Sigma-delta filter scaling value */
i2s_pdm_sig_scale_t hp_scale; /*!< High pass filter scaling value */
i2s_pdm_sig_scale_t lp_scale; /*!< Low pass filter scaling value */
i2s_pdm_sig_scale_t sinc_scale; /*!< Sinc filter scaling value */
#if SOC_I2S_HW_VERSION_2
bool sd_en; /*!< Sigma-delta filter enable */
bool hp_en; /*!< High pass filter enable */
float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */
uint32_t sd_dither; /*!< Sigma-delta filter dither */
uint32_t sd_dither2; /*!< Sigma-delta filter dither2 */
#endif // SOC_I2S_HW_VERSION_2
} i2s_pdm_tx_slot_config_t;
/**
* @breif I2S clock configuration for pdm tx mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
/* Particular fields */
uint32_t up_sample_fp; /*!< Up-sampling param fp */
uint32_t up_sample_fs; /*!< Up-sampling param fs */
} i2s_pdm_tx_clk_config_t;
#endif // SOC_I2S_SUPPORTS_PDM_TX
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,175 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file is specified for I2S standard communication mode
* Features:
* - Philip/MSB/PCM are supported in standard mode
* - Fixed to 2 slots
*/
#pragma once
#include "hal/i2s_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_I2S_HW_VERSION_1 // For esp32/esp32-s2
/**
* @brief Philip format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_STD, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = true, \
.msb_right = false, \
}
/**
* @brief PCM(short) format in 2 slots
* @note PCM(long) is sample as philip in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PCM_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_STD, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.msb_right = false, \
}
/**
* @brief MSB format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_STD, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = false, \
.msb_right = false, \
}
#else
/**
* @brief Philip format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_STD, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false \
}
/**
* @brief PCM(short) format in 2 slots
* @note PCM(long) is sample as philip in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PCM_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_STD, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false \
}
/**
* @brief MSB format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.mode = I2S_COMM_MODE_STD, \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = false, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false \
}
#endif
/**
* @brief i2s default standard clock configuration
* @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while using 24 bits data width
* Otherwise the sample rate might be imprecise since the bclk division is not a integer
* @param rate sample rate
*/
#define I2S_STD_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_D2CLK, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
}
/**
* @breif I2S slot configuration for standard mode
*/
typedef struct {
/* General fields */
i2s_comm_mode_t mode; /*!< I2S communication mode, this field is for identification (MUST match the communication mode in 'i2s_chan_config_t') */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample) */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
/* Particular fields */
uint32_t ws_width; /*!< WS signal width (i.e. the number of bclk ticks that ws signal is high) */
bool ws_pol; /*!< WS signal polarity, set true to enable high lever first */
bool bit_shift; /*!< Set to enbale bit shift in Philip mode */
#if SOC_I2S_HW_VERSION_1 // For esp32/esp32-s2
bool msb_right; /*!< Set to place right channel data at the MSB in the FIFO */
#else
bool left_align; /*!< Set to enable left alignment */
bool big_endian; /*!< Set to enable big endian */
bool bit_order_lsb; /*!< Set to enable lsb first */
#endif
} i2s_std_slot_config_t;
/**
* @breif I2S clock configuration for standard mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
} i2s_std_clk_config_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,163 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file is specified for I2S TDM communication mode
* Features:
* - More than 2 slots
*/
#pragma once
#include "hal/i2s_types.h"
#if SOC_I2S_SUPPORTS_TDM
#ifdef __cplusplus
extern "C" {
#endif
#define I2S_TDM_AUTO_SLOT_NUM (0) // Auto means total slot number will be equal to the maximum active slot number
#define I2S_TDM_AUTO_WS_WIDTH (0) // Auto means ws signal width will be equal to the half width of a frame
/**
* @brief Philip format in active slot that enabled by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_PHILIP_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.mode = I2S_COMM_MODE_TDM, \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = I2S_TDM_AUTO_WS_WIDTH, \
.ws_pol = false, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false, \
.slot_mask = (mask), \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief MSB format in active slot enabled that by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.mode = I2S_COMM_MODE_TDM, \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = I2S_TDM_AUTO_WS_WIDTH, \
.ws_pol = false, \
.bit_shift = false, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false ,\
.slot_mask = (mask), \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief PCM(short) format in active slot that enabled by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.mode = I2S_COMM_MODE_TDM, \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false, \
.slot_mask = (mask), \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief PCM(long) format in active slot that enabled by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_PCM_LONG_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.mode = I2S_COMM_MODE_TDM, \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_DEFAULT, \
.slot_mode = mono_or_stereo, \
.ws_width = (bits_per_sample), \
.ws_pol = true, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false, \
.slot_mask = (mask), \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief i2s default tdm clock configuration
* @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while the data width in slot configuration is set to 24 bits
* Otherwise the sample rate might be imprecise since the bclk division is not a integer
* @param rate sample rate
*/
#define I2S_TDM_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_D2CLK, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
}
/**
* @breif I2S slot configuration for tdm mode
*/
typedef struct {
/* General fields */
i2s_comm_mode_t mode; /*!< I2S communication mode, this field is for identification (MUST match the communication mode in 'i2s_chan_config_t') */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample) */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
/* Particular fields */
uint32_t ws_width; /*!< WS signal width ((i.e. the number of bclk ticks that ws signal is high)) */
bool ws_pol; /*!< WS signal polarity, set true to enable high lever first */
bool bit_shift; /*!< Set true to enable bit shift in Philip mode */
bool left_align; /*!< Set true to enable left alignment */
bool big_endian; /*!< Set true to enable big endian */
bool bit_order_lsb; /*!< Set true to enable lsb first */
bool skip_mask; /*!< Set true 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 */
i2s_tdm_slot_mask_t slot_mask; /*!< Slot mask. Activating slots by setting 1 to corresponding bits. When the activated slots is not consecutive, those data in unactivated slots will be ignored */
uint32_t total_slot; /*!< I2S total number of slots. If it is smaller than the biggest activated channel number, it will be set to this number automatically. */
} i2s_tdm_slot_config_t;
/**
* @breif I2S clock configuration for tdm mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
} i2s_tdm_clk_config_t;
#ifdef __cplusplus
}
#endif
#endif // SOC_I2S_SUPPORTS_TDM

View File

@ -0,0 +1,107 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#include "i2s_types_priv.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief I2S controller communication mode
*/
typedef enum {
I2S_COMM_MODE_STD, /*!< I2S controller using standard communication mode, support philip/MSB/PCM format */
#if SOC_I2S_SUPPORTS_PDM
I2S_COMM_MODE_PDM, /*!< I2S controller using PDM communication mode, support PDM output or input */
#endif
#if SOC_I2S_SUPPORTS_TDM
I2S_COMM_MODE_TDM, /*!< I2S controller using TDM communication mode, support up to 16 slots per frame */
#endif
I2S_COMM_MODE_MAX
} i2s_comm_mode_t;
/**
* @brief I2S channel slot mode
*/
typedef enum {
I2S_SLOT_MODE_MONO = 1, /*!< I2S channel slot format mono, transmit same data in all slots for tx mode, only receive the data in the first slots for rx mode. */
I2S_SLOT_MODE_STEREO = 2, /*!< I2S channel slot format stereo, transmit different data in different slots for tx mode, receive the data in all slots for rx mode. */
} i2s_slot_mode_t;
/**
* @brief I2S channel direction
*/
typedef enum {
I2S_DIR_RX = BIT(0), /*!< I2S channel direction RX */
I2S_DIR_TX = BIT(1), /*!< I2S channel direction TX */
} i2s_dir_t;
/**
* @brief I2S controller role
*/
typedef enum {
I2S_ROLE_MASTER, /*!< I2S controller master role, bclk and ws signal will be set to output */
I2S_ROLE_SLAVE /*!< I2S controller slave role, bclk and ws signal will be set to input */
} i2s_role_t;
/**
* @brief Available data bit width in one slot
*/
typedef enum {
I2S_DATA_BIT_WIDTH_8BIT = 8, /*!< I2S channel data bit-width: 8 */
I2S_DATA_BIT_WIDTH_16BIT = 16, /*!< I2S channel data bit-width: 16 */
I2S_DATA_BIT_WIDTH_24BIT = 24, /*!< I2S channel data bit-width: 24 */
I2S_DATA_BIT_WIDTH_32BIT = 32, /*!< I2S channel data bit-width: 32 */
} i2s_data_bit_width_t;
/**
* @brief Total slot bit width in one slot
*
*/
typedef enum {
I2S_SLOT_BIT_WIDTH_DEFAULT = (0), /*!< I2S channel slot bit-width equals to data bit-width */
I2S_SLOT_BIT_WIDTH_8BIT = (8), /*!< I2S channel slot bit-width: 8 */
I2S_SLOT_BIT_WIDTH_16BIT = (16), /*!< I2S channel slot bit-width: 16 */
I2S_SLOT_BIT_WIDTH_24BIT = (24), /*!< I2S channel slot bit-width: 24 */
I2S_SLOT_BIT_WIDTH_32BIT = (32), /*!< I2S channel slot bit-width: 32 */
} i2s_slot_bit_width_t;
#if SOC_I2S_SUPPORTS_TDM
/**
* @brief tdm slot number
* @note There are 16 slots in TDM mode.
* For TX module, only the active slot send the audio data, the inactive slot send a constant or will be skipped if 'skip_msk' is set.
* For RX module, only receive the audio data in active slots, the data in inactive slots will be ignored.
* the bit map of active slot can not exceed (0x1<<total_slot_num).
* e.g: slot_mask = (I2S_TDM_SLOT0 | I2S_TDM_SLOT3), here the active slot number is 2 and total_slot is not supposed to be smaller than 4.
*/
typedef enum {
I2S_TDM_SLOT0 = BIT(0), /*!< I2S slot 0 enabled */
I2S_TDM_SLOT1 = BIT(1), /*!< I2S slot 1 enabled */
I2S_TDM_SLOT2 = BIT(2), /*!< I2S slot 2 enabled */
I2S_TDM_SLOT3 = BIT(3), /*!< I2S slot 3 enabled */
I2S_TDM_SLOT4 = BIT(4), /*!< I2S slot 4 enabled */
I2S_TDM_SLOT5 = BIT(5), /*!< I2S slot 5 enabled */
I2S_TDM_SLOT6 = BIT(6), /*!< I2S slot 6 enabled */
I2S_TDM_SLOT7 = BIT(7), /*!< I2S slot 7 enabled */
I2S_TDM_SLOT8 = BIT(8), /*!< I2S slot 8 enabled */
I2S_TDM_SLOT9 = BIT(9), /*!< I2S slot 9 enabled */
I2S_TDM_SLOT10 = BIT(10), /*!< I2S slot 10 enabled */
I2S_TDM_SLOT11 = BIT(11), /*!< I2S slot 11 enabled */
I2S_TDM_SLOT12 = BIT(12), /*!< I2S slot 12 enabled */
I2S_TDM_SLOT13 = BIT(13), /*!< I2S slot 13 enabled */
I2S_TDM_SLOT14 = BIT(14), /*!< I2S slot 14 enabled */
I2S_TDM_SLOT15 = BIT(15), /*!< I2S slot 15 enabled */
} i2s_tdm_slot_mask_t;
#endif // SOC_I2S_SUPPORTS_TDM
#ifdef __cplusplus
}
#endif

View File

@ -243,10 +243,18 @@ config SOC_I2S_NUM
int
default 2
config SOC_I2S_HW_VERSION_1
bool
default y
config SOC_I2S_SUPPORTS_APLL
bool
default y
config SOC_I2S_SUPPORTS_PDM
bool
default y
config SOC_I2S_SUPPORTS_PDM_TX
bool
default y
@ -255,6 +263,10 @@ config SOC_I2S_SUPPORTS_PDM_RX
bool
default y
config SOC_I2S_SUPPORTS_ADC_DAC
bool
default y
config SOC_I2S_SUPPORTS_ADC
bool
default y
@ -263,6 +275,10 @@ config SOC_I2S_SUPPORTS_DAC
bool
default y
config SOC_I2S_SUPPORTS_LCD_CAMERA
bool
default y
config SOC_I2S_TRANS_SIZE_ALIGN_WORD
bool
default y

View File

@ -177,11 +177,15 @@
/*-------------------------- I2S CAPS ----------------------------------------*/
// ESP32 has 2 I2S
#define SOC_I2S_NUM (2U)
#define SOC_I2S_SUPPORTS_APLL (1) // ESP32 support APLL
#define SOC_I2S_HW_VERSION_1 (1)
#define SOC_I2S_SUPPORTS_APLL (1)
#define SOC_I2S_SUPPORTS_PDM (1)
#define SOC_I2S_SUPPORTS_PDM_TX (1)
#define SOC_I2S_SUPPORTS_PDM_RX (1)
#define SOC_I2S_SUPPORTS_ADC (1) // ESP32 support ADC and DAC
#define SOC_I2S_SUPPORTS_ADC_DAC (1)
#define SOC_I2S_SUPPORTS_ADC (1)
#define SOC_I2S_SUPPORTS_DAC (1)
#define SOC_I2S_SUPPORTS_LCD_CAMERA (1)
#define SOC_I2S_TRANS_SIZE_ALIGN_WORD (1) // I2S DMA transfer size must be aligned to word
#define SOC_I2S_LCD_I80_VARIANT (1) // I2S has a special LCD mode that can generate Intel 8080 TX timing

View File

@ -316,13 +316,21 @@ config SOC_I2C_SUPPORT_RTC
default y
config SOC_I2S_NUM
int
default 1
bool
default y
config SOC_I2S_HW_VERSION_2
bool
default y
config SOC_I2S_SUPPORTS_PCM
bool
default y
config SOC_I2S_SUPPORTS_PDM
bool
default y
config SOC_I2S_SUPPORTS_PDM_TX
bool
default y

View File

@ -161,8 +161,10 @@
#define SOC_I2C_SUPPORT_RTC (1)
/*-------------------------- I2S CAPS ----------------------------------------*/
#define SOC_I2S_NUM (1U)
#define SOC_I2S_NUM (1)
#define SOC_I2S_HW_VERSION_2 (1)
#define SOC_I2S_SUPPORTS_PCM (1)
#define SOC_I2S_SUPPORTS_PDM (1)
#define SOC_I2S_SUPPORTS_PDM_TX (1)
#define SOC_I2S_SUPPORTS_PDM_CODEC (1)
#define SOC_I2S_SUPPORTS_TDM (1)

View File

@ -303,10 +303,18 @@ config SOC_I2S_NUM
bool
default y
config SOC_I2S_HW_VERSION_2
bool
default y
config SOC_I2S_SUPPORTS_PCM
bool
default y
config SOC_I2S_SUPPORTS_PDM
bool
default y
config SOC_I2S_SUPPORTS_PDM_TX
bool
default y

View File

@ -173,7 +173,9 @@
/*-------------------------- I2S CAPS ----------------------------------------*/
#define SOC_I2S_NUM (1)
#define SOC_I2S_HW_VERSION_2 (1)
#define SOC_I2S_SUPPORTS_PCM (1)
#define SOC_I2S_SUPPORTS_PDM (1)
#define SOC_I2S_SUPPORTS_PDM_TX (1)
#define SOC_I2S_SUPPORTS_PDM_CODEC (1)
#define SOC_I2S_SUPPORTS_TDM (1)

View File

@ -323,6 +323,10 @@ config SOC_I2S_NUM
int
default 1
config SOC_I2S_HW_VERSION_1
bool
default y
config SOC_I2S_SUPPORTS_APLL
bool
default y
@ -331,6 +335,22 @@ config SOC_I2S_SUPPORTS_DMA_EQUAL
bool
default y
config SOC_I2S_SUPPORTS_LCD_CAMERA
bool
default y
config SOC_I2S_APLL_MIN_FREQ
int
default 250000000
config SOC_I2S_APLL_MAX_FREQ
int
default 500000000
config SOC_I2S_APLL_MIN_RATE
int
default 10675
config SOC_I2S_LCD_I80_VARIANT
bool
default y

View File

@ -169,8 +169,13 @@
/*-------------------------- I2S CAPS ----------------------------------------*/
// ESP32-S2 has 1 I2S
#define SOC_I2S_NUM (1U)
#define SOC_I2S_SUPPORTS_APLL (1) // ESP32-S2 support APLL
#define SOC_I2S_HW_VERSION_1 (1)
#define SOC_I2S_SUPPORTS_APLL (1)
#define SOC_I2S_SUPPORTS_DMA_EQUAL (1)
#define SOC_I2S_SUPPORTS_LCD_CAMERA (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
#define SOC_I2S_LCD_I80_VARIANT (1)
/*-------------------------- LCD CAPS ----------------------------------------*/

View File

@ -379,10 +379,18 @@ config SOC_I2S_NUM
int
default 2
config SOC_I2S_HW_VERSION_2
bool
default y
config SOC_I2S_SUPPORTS_PCM
bool
default y
config SOC_I2S_SUPPORTS_PDM
bool
default y
config SOC_I2S_SUPPORTS_PDM_TX
bool
default y

View File

@ -163,7 +163,9 @@
/*-------------------------- I2S CAPS ----------------------------------------*/
#define SOC_I2S_NUM (2)
#define SOC_I2S_HW_VERSION_2 (1)
#define SOC_I2S_SUPPORTS_PCM (1)
#define SOC_I2S_SUPPORTS_PDM (1)
#define SOC_I2S_SUPPORTS_PDM_TX (1)
#define SOC_I2S_SUPPORTS_PDM_RX (1)
#define SOC_I2S_SUPPORTS_PDM_CODEC (1)