mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-09 04:25:32 +00:00
driver/i2s: support i2s on c3 and s3
1. Support i2s on esp32c3 and esp32s3 2. Refactor i2s_config_t to avoid breaking change 2. Fix a bug that receiving unavailable values from message queue when dma queue has been re-allocted 4. Support i2s unit test on esp32c3 and esp32s3
This commit is contained in:
@@ -33,12 +33,12 @@ extern "C" {
|
||||
// Get I2S hardware instance with giving i2s num
|
||||
#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : (((num) == 1) ? (&I2S1) : NULL))
|
||||
|
||||
#define I2S_INTR_IN_SUC_EOF BIT(9)
|
||||
#define I2S_INTR_OUT_EOF BIT(12)
|
||||
#define I2S_INTR_IN_DSCR_ERR BIT(13)
|
||||
#define I2S_INTR_OUT_DSCR_ERR BIT(14)
|
||||
#define I2S_INTR_MAX (0xFFFFFFFF)
|
||||
#define I2S_LL_AD_BCK_FACTOR (2)
|
||||
#define I2S_LL_PDM_BCK_FACTOR (64)
|
||||
#define I2S_LL_BASE_CLK (2*APB_CLK_FREQ)
|
||||
|
||||
#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6)
|
||||
#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1)
|
||||
|
||||
/* I2S clock configuration structure */
|
||||
typedef struct {
|
||||
@@ -46,56 +46,14 @@ typedef struct {
|
||||
uint16_t a;
|
||||
uint16_t b; // The decimal part of module clock devider, the decimal is: b/a
|
||||
uint16_t bck_div; // The BCK devider, Fbck = Fmclk / bck_div
|
||||
} i2s_clk_cal_t;
|
||||
|
||||
/**
|
||||
* @brief Calculate the closest sample rate clock configuration.
|
||||
* clock relationship:
|
||||
* Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a)
|
||||
*
|
||||
* @param fsclk I2S source clock freq.
|
||||
* @param fbck BCK freuency.
|
||||
* @param bck_div The BCK devider of bck. Generally, set bck_div to 8.
|
||||
* @param cal Point to `i2s_clk_cal_t` structure.
|
||||
*/
|
||||
static inline void i2s_ll_clk_cal(uint32_t fsclk, uint32_t fbck, int bck_div, i2s_clk_cal_t *cal)
|
||||
{
|
||||
int ma = 0;
|
||||
int mb = 0;
|
||||
uint32_t mclk = fbck*bck_div;
|
||||
cal->mclk_div = fsclk / mclk;
|
||||
cal->bck_div = bck_div;
|
||||
cal->a = 1;
|
||||
cal->b = 0;
|
||||
uint32_t freq_diff = fsclk - mclk * cal->mclk_div;
|
||||
uint32_t min = ~0;
|
||||
if (freq_diff == 0) {
|
||||
return;
|
||||
}
|
||||
for (int a = 2; a <= 63; a++) {
|
||||
for (int b = 1; b < a; b++) {
|
||||
ma = freq_diff*a;
|
||||
mb = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} i2s_ll_clk_cal_t;
|
||||
|
||||
/**
|
||||
* @brief I2S module general init, enable I2S clock.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_general_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
|
||||
{
|
||||
if (hw->clkm_conf.clk_en == 0) {
|
||||
hw->clkm_conf.clk_en = 1;
|
||||
@@ -104,37 +62,70 @@ static inline void i2s_ll_general_init(i2s_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S TX module general init.
|
||||
* @brief I2S tx msb right enable
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param enable Set true to enable tx msb right
|
||||
*/
|
||||
static inline void i2s_ll_tx_gen_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_tx_msb_right_en(i2s_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->conf.tx_start = 0;
|
||||
hw->conf.tx_reset = 1;
|
||||
hw->conf.tx_reset = 0;
|
||||
hw->conf.tx_msb_right = 0;
|
||||
hw->conf.tx_right_first = 0;
|
||||
hw->conf.tx_slave_mod = 0;
|
||||
hw->fifo_conf.tx_fifo_mod_force_en = 1;
|
||||
hw->conf.tx_msb_right = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S RX module general init.
|
||||
* @brief I2S rx msb right enable
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param enable Set true to enable rx msb right
|
||||
*/
|
||||
static inline void i2s_ll_rx_gen_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_rx_msb_right_en(i2s_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->conf.rx_start = 0;
|
||||
hw->conf.rx_reset = 1;
|
||||
hw->conf.rx_reset = 0;
|
||||
hw->conf.rx_msb_right = 0;
|
||||
hw->conf.rx_right_first = 0;
|
||||
hw->conf.rx_slave_mod = 0;
|
||||
hw->fifo_conf.rx_fifo_mod_force_en = 1;
|
||||
hw->conf.rx_msb_right = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S tx right channel first
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param enable Set true to enable send right channel first
|
||||
*/
|
||||
static inline void i2s_ll_tx_right_first_en(i2s_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->conf.tx_right_first = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S rx right channel first
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param enable Set true to enable receive right channel first
|
||||
*/
|
||||
static inline void i2s_ll_rx_right_first_en(i2s_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->conf.rx_right_first = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S tx fifo module force enable
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param enable Set true to enable tx fifo module
|
||||
*/
|
||||
static inline void i2s_ll_tx_fifo_mod_force_en(i2s_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->fifo_conf.tx_fifo_mod_force_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S rx fifo module force enable
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param enable Set true to enable rx fifo module
|
||||
*/
|
||||
static inline void i2s_ll_rx_fifo_mod_force_en(i2s_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->fifo_conf.rx_fifo_mod_force_en = enable;
|
||||
}
|
||||
/**
|
||||
* @brief Enable I2S TX slave mode
|
||||
*
|
||||
@@ -233,7 +224,7 @@ static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param set Pointer to I2S clock devider configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_clk_cal_t *set)
|
||||
static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set)
|
||||
{
|
||||
hw->clkm_conf.clkm_div_num = set->mclk_div;
|
||||
hw->clkm_conf.clkm_div_b = set->b;
|
||||
@@ -247,7 +238,7 @@ static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_clk_cal_t *set)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param set Pointer to I2S clock devider configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_clk_cal_t *set)
|
||||
static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set)
|
||||
{
|
||||
hw->clkm_conf.clkm_div_num = set->mclk_div;
|
||||
hw->clkm_conf.clkm_div_b = set->b;
|
||||
@@ -495,11 +486,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
*/
|
||||
static inline void i2s_ll_dma_enable(i2s_dev_t *hw, bool ena)
|
||||
{
|
||||
if (ena && !hw->fifo_conf.dscr_en) {
|
||||
hw->fifo_conf.dscr_en = 1;
|
||||
} else if (!ena && hw->fifo_conf.dscr_en) {
|
||||
hw->fifo_conf.dscr_en = 0;
|
||||
}
|
||||
hw->fifo_conf.dscr_en = ena;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -666,7 +653,7 @@ static inline void i2s_ll_set_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr)
|
||||
*/
|
||||
static inline void i2s_ll_get_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr)
|
||||
{
|
||||
*dsr = hw->pdm_conf.rx_sinc_dsr_16_en;
|
||||
*dsr = hw->pdm_conf.rx_sinc_dsr_16_en;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,7 +678,7 @@ static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate)
|
||||
uint32_t fp = 960;
|
||||
uint32_t fs = sample_rate / 100;
|
||||
typeof(hw->pdm_conf) pdm_conf_reg = hw->pdm_conf;
|
||||
pdm_conf_reg.tx_sinc_osr2 = fp/fs;
|
||||
pdm_conf_reg.tx_sinc_osr2 = fp / fs;
|
||||
pdm_conf_reg.tx_prescale = 0;
|
||||
pdm_conf_reg.tx_hp_in_shift = 1;
|
||||
pdm_conf_reg.tx_lp_in_shift = 1;
|
||||
|
Reference in New Issue
Block a user