mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
i2s: extract std/pdm/tdm modes
Type structures of these modes are defined. Driver and HAL layer are modified to fit these concepts.
This commit is contained in:
parent
c1bcb8756b
commit
f17edba20b
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
||||
void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src)
|
||||
{
|
||||
#if SOC_I2S_HW_VERSION_2
|
||||
i2s_ll_rx_enable_clock(hal->dev);
|
||||
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);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
| 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)
|
||||
{
|
||||
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, 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
|
||||
}
|
||||
|
||||
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, 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
|
||||
}
|
||||
|
||||
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_rx_set_pdm_mode_default(i2s_hal_context_t *hal)
|
||||
void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
||||
{
|
||||
/* 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
|
||||
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);
|
||||
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_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
|
||||
#else
|
||||
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
|
||||
i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_SLOT0 | I2S_TDM_SLOT1);
|
||||
#endif
|
||||
}
|
||||
#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)
|
||||
void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal)
|
||||
{
|
||||
/* Disable PDM tx mode and enable TDM mode (if support) */
|
||||
i2s_ll_tx_enable_pdm(hal->dev, false);
|
||||
i2s_ll_rx_enable_pdm(hal->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
| TDM Specific Slot Configurations |
|
||||
-------------------------------------------------------------------------*/
|
||||
#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)
|
||||
void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
||||
{
|
||||
/* 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_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
|
||||
#endif
|
||||
{
|
||||
/* Set tx common mode */
|
||||
i2s_hal_tx_set_common_mode(hal, hal_cfg);
|
||||
}
|
||||
i2s_hal_tx_set_channel_style(hal, hal_cfg);
|
||||
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_ll_tx_set_ws_width(hal->dev, slot_cfg->ws_width);
|
||||
}
|
||||
|
||||
/* Set configurations for RX mode */
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_stop(hal->dev);
|
||||
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_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_tdm_set_rx_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;
|
||||
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);
|
||||
}
|
||||
|
||||
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_tdm_enable_tx_channel(i2s_hal_context_t *hal)
|
||||
{
|
||||
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
|
||||
{
|
||||
/* 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);
|
||||
} else {
|
||||
i2s_hal_enable_slave_fd_mode(hal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i2s_hal_start_tx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_tx_start(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_start_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_rx_start(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_stop_tx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_tx_stop(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_stop_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_rx_stop(hal->dev);
|
||||
}
|
||||
|
@ -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,362 +15,251 @@
|
||||
|
||||
#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
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t sclk; /*!< I2S module clock */
|
||||
uint32_t mclk; /*!< I2S master clock */
|
||||
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;
|
||||
uint32_t sclk; /*!< I2S module clock */
|
||||
uint32_t mclk; /*!< I2S master clock */
|
||||
uint32_t bclk; /*!< I2S bit clock */
|
||||
uint16_t mclk_div; /*!< I2S master clock division */
|
||||
uint16_t bclk_div; /*!< I2S bit clock division*/
|
||||
} 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
|
||||
|
195
components/hal/include/hal/i2s_pdm.h
Normal file
195
components/hal/include/hal/i2s_pdm.h
Normal 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
|
175
components/hal/include/hal/i2s_std.h
Normal file
175
components/hal/include/hal/i2s_std.h
Normal 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
|
163
components/hal/include/hal/i2s_tdm.h
Normal file
163
components/hal/include/hal/i2s_tdm.h
Normal 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
|
107
components/hal/include/hal/i2s_types_priv.h
Normal file
107
components/hal/include/hal/i2s_types_priv.h
Normal 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
|
@ -231,10 +231,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
|
||||
@ -243,6 +251,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
|
||||
@ -251,6 +263,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
|
||||
|
@ -174,11 +174,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
|
||||
|
@ -304,13 +304,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
|
||||
|
@ -158,8 +158,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)
|
||||
|
@ -287,10 +287,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
|
||||
|
@ -170,7 +170,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)
|
||||
|
@ -311,6 +311,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
|
||||
@ -319,6 +323,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
|
||||
|
@ -165,10 +165,15 @@
|
||||
|
||||
/*-------------------------- 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_SUPPORTS_DMA_EQUAL (1)
|
||||
#define SOC_I2S_LCD_I80_VARIANT (1)
|
||||
#define SOC_I2S_NUM (1U)
|
||||
#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 ----------------------------------------*/
|
||||
/* Notes: On esp32-s2, LCD intel 8080 timing is generated by I2S peripheral */
|
||||
|
@ -367,10 +367,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
|
||||
|
@ -159,7 +159,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)
|
||||
|
Loading…
Reference in New Issue
Block a user