mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-30 14:20:05 +01:00
driver: support I2S on ESP32-S3 & ESP32-C3
1. refactor I2S driver. 2. support TDM mode for esp2s3 & esp32c3.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -39,19 +39,148 @@ extern "C" {
|
||||
#define I2S_INTR_OUT_DSCR_ERR BIT(14)
|
||||
#define I2S_INTR_MAX (0xFFFFFFFF)
|
||||
|
||||
/* I2S clock configuration structure */
|
||||
typedef struct {
|
||||
uint16_t mclk_div; // I2S module clock devider, 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 bck_div; // The BCK devider, Fbck = Fmclk / bck_div
|
||||
} i2s_clk_cal_t;
|
||||
|
||||
/**
|
||||
* @brief Reset rx fifo
|
||||
* @brief Calculate the closest sample rate clock configuration.
|
||||
* clock relationship:
|
||||
* Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a)
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @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_reset_rx_fifo(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_clk_cal(uint32_t fsclk, uint32_t fbck, int bck_div, i2s_clk_cal_t *cal)
|
||||
{
|
||||
hw->conf.rx_fifo_reset = 1;
|
||||
hw->conf.rx_fifo_reset = 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset tx fifo
|
||||
* @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)
|
||||
{
|
||||
if (hw->clkm_conf.clk_en == 0) {
|
||||
hw->clkm_conf.clk_sel = 2;
|
||||
hw->clkm_conf.clk_en = 1;
|
||||
hw->conf2.val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S TX module general init.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_tx_gen_init(i2s_dev_t *hw)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S RX module general init.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_rx_gen_init(i2s_dev_t *hw)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2S TX slave mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param slave_en Set true to enable slave mode
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en)
|
||||
{
|
||||
hw->conf.tx_slave_mod = slave_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2S RX slave mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param slave_en Set true to enable slave mode
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en)
|
||||
{
|
||||
hw->conf.rx_slave_mod = slave_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset TX module
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_reset_tx(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.tx_reset = 1;
|
||||
hw->conf.tx_reset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset RX module
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_reset_rx(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.rx_reset = 1;
|
||||
hw->conf.rx_reset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset TX FIFO
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
@@ -62,40 +191,68 @@ static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable rx interrupt
|
||||
* @brief Reset RX FIFO
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.in_suc_eof = 1;
|
||||
hw->int_ena.in_dscr_err = 1;
|
||||
hw->conf.rx_fifo_reset = 1;
|
||||
hw->conf.rx_fifo_reset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable rx interrupt
|
||||
* @brief Set TX source clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param src I2S source clock
|
||||
*/
|
||||
static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
{
|
||||
hw->int_ena.in_suc_eof = 0;
|
||||
hw->int_ena.in_dscr_err = 0;
|
||||
hw->clkm_conf.clk_sel = (src == 1) ? 1 : 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable tx interrupt
|
||||
* @brief Set RX source clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param src I2S source clock
|
||||
*/
|
||||
static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
{
|
||||
hw->int_ena.out_eof = 0;
|
||||
hw->int_ena.out_dscr_err = 0;
|
||||
hw->clkm_conf.clk_sel = (src == 1) ? 1 : 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable tx interrupt
|
||||
* @brief Configure I2S TX clock devider
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
hw->sample_rate_conf.tx_bck_div_num = set->bck_div;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2S RX clock devider
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
hw->sample_rate_conf.rx_bck_div_num = set->bck_div;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable TX interrupt
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
@@ -106,14 +263,58 @@ static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset dma in
|
||||
* @brief Disable TX interrupt
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw)
|
||||
{
|
||||
hw->lc_conf.in_rst = 1;
|
||||
hw->lc_conf.in_rst = 0;
|
||||
hw->int_ena.out_eof = 0;
|
||||
hw->int_ena.out_dscr_err = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable RX interrupt
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.in_suc_eof = 1;
|
||||
hw->int_ena.in_dscr_err = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable RX interrupt
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.in_suc_eof = 0;
|
||||
hw->int_ena.in_dscr_err = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S interrupt status
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param intr_mask Pointer to accept interrupt status
|
||||
*/
|
||||
static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *intr_mask)
|
||||
{
|
||||
*intr_mask = hw->int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2S interrupt status
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param clr_mask Interrupt mask to be cleared.
|
||||
*/
|
||||
static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask)
|
||||
{
|
||||
hw->int_clr.val = clr_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,39 +329,18 @@ static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset tx
|
||||
* @brief Reset dma in
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_reset_tx(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.tx_reset = 1;
|
||||
hw->conf.tx_reset = 0;
|
||||
hw->lc_conf.in_rst = 1;
|
||||
hw->lc_conf.in_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset rx
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_reset_rx(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.rx_reset = 1;
|
||||
hw->conf.rx_reset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start out link
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_start_out_link(i2s_dev_t *hw)
|
||||
{
|
||||
hw->out_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start tx
|
||||
* @brief Start TX module
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
@@ -170,17 +350,7 @@ static inline void i2s_ll_start_tx(i2s_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start in link
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_start_in_link(i2s_dev_t *hw)
|
||||
{
|
||||
hw->in_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start rx
|
||||
* @brief Start RX module
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
@@ -189,6 +359,50 @@ static inline void i2s_ll_start_rx(i2s_dev_t *hw)
|
||||
hw->conf.rx_start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure TX DMA descriptor address and start TX DMA
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param link_addr DMA descriptor link address.
|
||||
*/
|
||||
static inline void i2s_ll_start_tx_link(i2s_dev_t *hw, uint32_t link_addr)
|
||||
{
|
||||
hw->out_link.addr = link_addr;
|
||||
hw->out_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure RX DMA descriptor address and start TX DMA
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param link_addr DMA descriptor link address.
|
||||
*/
|
||||
static inline void i2s_ll_start_rx_link(i2s_dev_t *hw, uint32_t link_addr)
|
||||
{
|
||||
hw->in_link.addr = link_addr;
|
||||
hw->in_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop TX module
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_stop_tx(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.tx_start = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop RX module
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_stop_rx(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.rx_start = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop out link
|
||||
*
|
||||
@@ -199,16 +413,6 @@ static inline void i2s_ll_stop_out_link(i2s_dev_t *hw)
|
||||
hw->out_link.stop = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop tx
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_stop_tx(i2s_dev_t *hw)
|
||||
{
|
||||
hw->conf.tx_start = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop in link
|
||||
*
|
||||
@@ -220,456 +424,77 @@ static inline void i2s_ll_stop_in_link(i2s_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop rx
|
||||
* @brief Get I2S out eof descriptor address
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param eof_addr Pointer to accept out eof des address
|
||||
*/
|
||||
static inline void i2s_ll_stop_rx(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr)
|
||||
{
|
||||
hw->conf.rx_start = 0;
|
||||
*eof_addr = hw->out_eof_des_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable dma
|
||||
* @brief Get I2S in eof descriptor address
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param eof_addr Pointer to accept in eof des address
|
||||
*/
|
||||
static inline void i2s_ll_enable_dma(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr)
|
||||
{
|
||||
//Enable and configure DMA
|
||||
typeof(hw->lc_conf) lc_conf;
|
||||
lc_conf.val = 0;
|
||||
lc_conf.out_eof_mode = 1;
|
||||
hw->lc_conf.val = lc_conf.val;
|
||||
*eof_addr = hw->in_eof_des_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S interrupt status
|
||||
* @brief Configure the received length to trigger in_suc_eof interrupt
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get interrupt status
|
||||
* @param eof_num the byte length to trigger in_suc_eof interrupt
|
||||
*/
|
||||
static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val)
|
||||
static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t eof_num)
|
||||
{
|
||||
*val = hw->int_st.val;
|
||||
hw->rx_eof_num = eof_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2S interrupt status
|
||||
* @brief Congfigure TX slot bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to clear interrupt status
|
||||
* @param sample_bit The slot bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val)
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
{
|
||||
hw->int_clr.val = val;
|
||||
hw->fifo_conf.tx_fifo_mod = (sample_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2);
|
||||
hw->sample_rate_conf.tx_bits_mod = data_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S out eof des address
|
||||
* @brief Congfigure RX slot bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get out eof des address
|
||||
* @param sample_bit The slot bit width
|
||||
* @param data_bit The audio data bit width
|
||||
*/
|
||||
static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val)
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
{
|
||||
*val = hw->out_eof_des_addr;
|
||||
hw->fifo_conf.rx_fifo_mod = (sample_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2);
|
||||
hw->sample_rate_conf.rx_bits_mod = data_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S in eof des address
|
||||
* @brief Enable I2S DMA
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get in eof des address
|
||||
* @param ena Set true to enable DMA
|
||||
*/
|
||||
static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val)
|
||||
static inline void i2s_ll_dma_enable(i2s_dev_t *hw, bool ena)
|
||||
{
|
||||
*val = hw->in_eof_des_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S tx fifo mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get tx fifo mode
|
||||
*/
|
||||
static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val)
|
||||
{
|
||||
*val = hw->fifo_conf.tx_fifo_mod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx fifo mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx fifo mode
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->fifo_conf.tx_fifo_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S rx fifo mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get rx fifo mode
|
||||
*/
|
||||
static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val)
|
||||
{
|
||||
*val = hw->fifo_conf.rx_fifo_mod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx fifo mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx fifo mode
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->fifo_conf.rx_fifo_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx chan mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx chan mode
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf_chan.tx_chan_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx chan mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx chan mode
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf_chan.rx_chan_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx dma equal
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx dma equal
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_dma_equal(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.tx_dma_equal = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx dma equal
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx dma equal
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_dma_equal(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.rx_dma_equal = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S out link address
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set out link address
|
||||
*/
|
||||
static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->out_link.addr = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S in link address
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set in link address
|
||||
*/
|
||||
static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->in_link.addr = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx eof num
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx eof num
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->rx_eof_num = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S clkm div num
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set clkm div num
|
||||
*/
|
||||
static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->clkm_conf.clkm_div_num = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S clkm div b
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set clkm div b
|
||||
*/
|
||||
static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->clkm_conf.clkm_div_b = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S clkm div a
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set clkm div a
|
||||
*/
|
||||
static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->clkm_conf.clkm_div_a = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx bck div num
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx bck div num
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->sample_rate_conf.tx_bck_div_num = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx bck div num
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx bck div num
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->sample_rate_conf.rx_bck_div_num = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S clk sel
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set clk sel
|
||||
*/
|
||||
static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->clkm_conf.clk_sel = (val == 1) ? 1 : 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx bits mod
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx bits mod
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->sample_rate_conf.tx_bits_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx bits mod
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx bits mod
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->sample_rate_conf.rx_bits_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S dscr en
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set dscr en
|
||||
*/
|
||||
static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val)
|
||||
{
|
||||
hw->fifo_conf.dscr_en = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S lcd en
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set lcd en
|
||||
*/
|
||||
static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val)
|
||||
{
|
||||
hw->conf2.lcd_en = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S camera en
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set camera en
|
||||
*/
|
||||
static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val)
|
||||
{
|
||||
hw->conf2.camera_en = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx fifo mod force en
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx fifo mod force en
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val)
|
||||
{
|
||||
hw->fifo_conf.tx_fifo_mod_force_en = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx fifo mod force en
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx fifo mod force en
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val)
|
||||
{
|
||||
hw->fifo_conf.rx_fifo_mod_force_en = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx right first
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx right first
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.tx_right_first = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx right first
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx right first
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.rx_right_first = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx slave mod
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx slave mod
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.tx_slave_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx slave mod
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx slave mod
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.rx_slave_mod = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S tx msb right
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get tx msb right
|
||||
*/
|
||||
static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val)
|
||||
{
|
||||
*val = hw->conf.tx_msb_right;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S rx msb right
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to get rx msb right
|
||||
*/
|
||||
static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val)
|
||||
{
|
||||
*val = hw->conf.rx_msb_right;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx msb right
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx msb right
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.tx_msb_right = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx msb right
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx msb right
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.rx_msb_right = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx mono
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set tx mono
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.tx_mono = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx mono
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set rx mono
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.rx_mono = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2S sig loopback
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param val value to set sig loopback
|
||||
*/
|
||||
static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val)
|
||||
{
|
||||
hw->conf.sig_loopback = val;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -760,6 +585,53 @@ static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw)
|
||||
hw->conf.rx_msb_shift = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable TX mono mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param mono_ena Set true to enable mono mde.
|
||||
*/
|
||||
static inline void i2s_ll_tx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena)
|
||||
{
|
||||
int data_bit = hw->sample_rate_conf.tx_bits_mod;
|
||||
if (data_bit <= I2S_BITS_PER_SAMPLE_16BIT) {
|
||||
hw->fifo_conf.tx_fifo_mod = 0 + mono_ena;
|
||||
} else {
|
||||
hw->fifo_conf.tx_fifo_mod = 2 + mono_ena;
|
||||
}
|
||||
hw->conf.tx_dma_equal = mono_ena;
|
||||
hw->conf_chan.tx_chan_mod = mono_ena;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable RX mono mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param mono_ena Set true to enable mono mde.
|
||||
*/
|
||||
static inline void i2s_ll_rx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena)
|
||||
{
|
||||
int data_bit = hw->sample_rate_conf.rx_bits_mod;
|
||||
if (data_bit <= I2S_BITS_PER_SAMPLE_16BIT) {
|
||||
hw->fifo_conf.rx_fifo_mod = 0 + mono_ena;
|
||||
} else {
|
||||
hw->fifo_conf.rx_fifo_mod = 2 + mono_ena;
|
||||
}
|
||||
hw->conf.rx_dma_equal = mono_ena;
|
||||
hw->conf_chan.rx_chan_mod = mono_ena;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2S loopback mode
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param loopback_en Set true to enable loopback mode.
|
||||
*/
|
||||
static inline void i2s_ll_loop_back_ena(i2s_dev_t *hw, bool loopback_en)
|
||||
{
|
||||
hw->conf.sig_loopback = loopback_en;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -12,230 +12,291 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
// The HAL layer for I2S (common part)
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/gdma_channel.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
|
||||
#define I2S_TX_PDM_FP_DEF 960 // Set to the recommended value(960) in TRM
|
||||
#define I2S_RX_PDM_DSR_DEF 0
|
||||
#define I2S_MODE_I2S (I2S_MODE_MASTER|I2S_MODE_SLAVE|I2S_MODE_TX|I2S_MODE_RX) /*!< I2S normal mode*/
|
||||
|
||||
void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits)
|
||||
void i2s_hal_reset_tx(i2s_hal_context_t *hal)
|
||||
{
|
||||
if (bits <= I2S_BITS_PER_SAMPLE_16BIT) {
|
||||
i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
|
||||
} else {
|
||||
i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3);
|
||||
}
|
||||
i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
|
||||
#if SOC_I2S_SUPPORTS_DMA_EQUAL
|
||||
i2s_ll_set_tx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits)
|
||||
{
|
||||
if (bits <= I2S_BITS_PER_SAMPLE_16BIT) {
|
||||
i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
|
||||
} else {
|
||||
i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3);
|
||||
}
|
||||
i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
|
||||
#if SOC_I2S_SUPPORTS_DMA_EQUAL
|
||||
i2s_ll_set_rx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t addr)
|
||||
{
|
||||
i2s_ll_set_in_link_addr(hal->dev, addr);
|
||||
i2s_ll_set_rx_eof_num(hal->dev, bytes_num);
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
void i2s_hal_tx_pdm_cfg(i2s_hal_context_t *hal, uint32_t fp, uint32_t fs)
|
||||
{
|
||||
i2s_ll_tx_pdm_cfg(hal->dev, fp, fs);
|
||||
}
|
||||
|
||||
void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, uint32_t *fp, uint32_t *fs)
|
||||
{
|
||||
i2s_ll_get_tx_pdm(hal->dev, fp, fs);
|
||||
}
|
||||
|
||||
void i2s_hal_rx_pdm_cfg(i2s_hal_context_t *hal, uint32_t dsr)
|
||||
{
|
||||
i2s_ll_rx_pdm_cfg(hal->dev, dsr);
|
||||
}
|
||||
|
||||
void i2s_hal_get_rx_pdm(i2s_hal_context_t *hal, uint32_t *dsr)
|
||||
{
|
||||
i2s_ll_get_rx_pdm(hal->dev, dsr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div)
|
||||
{
|
||||
i2s_ll_set_clkm_div_num(hal->dev, div_num);
|
||||
i2s_ll_set_clkm_div_a(hal->dev, div_a);
|
||||
i2s_ll_set_clkm_div_b(hal->dev, div_b);
|
||||
i2s_ll_set_tx_bck_div_num(hal->dev, tx_bck_div);
|
||||
i2s_ll_set_rx_bck_div_num(hal->dev, rx_bck_div);
|
||||
}
|
||||
|
||||
void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits)
|
||||
{
|
||||
i2s_ll_set_tx_bits_mod(hal->dev, bits);
|
||||
}
|
||||
|
||||
void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits)
|
||||
{
|
||||
i2s_ll_set_rx_bits_mod(hal->dev, bits);
|
||||
}
|
||||
|
||||
void i2s_hal_reset(i2s_hal_context_t *hal)
|
||||
{
|
||||
// Reset I2S TX/RX module first, and then, reset DMA and FIFO.
|
||||
i2s_ll_reset_tx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_reset_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_reset_rx(hal->dev);
|
||||
i2s_ll_reset_dma_in(hal->dev);
|
||||
i2s_ll_reset_dma_out(hal->dev);
|
||||
i2s_ll_reset_rx_fifo(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_reset_tx_fifo(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_reset_tx_fifo(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_reset_rx_fifo(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_reset_rx_fifo(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_start_tx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_start_out_link(hal->dev);
|
||||
i2s_ll_start_tx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_start_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_start_in_link(hal->dev);
|
||||
i2s_ll_start_rx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_stop_tx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_stop_out_link(hal->dev);
|
||||
i2s_ll_stop_tx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_stop_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_stop_in_link(hal->dev);
|
||||
i2s_ll_stop_rx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_config_t *i2s_config)
|
||||
void i2s_hal_set_tx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit)
|
||||
{
|
||||
switch (i2s_config->communication_format) {
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, slot_bit, data_bit);
|
||||
}
|
||||
|
||||
void i2s_hal_set_rx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit)
|
||||
{
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bit, data_bit);
|
||||
}
|
||||
|
||||
void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel)
|
||||
{
|
||||
i2s_ll_set_tx_clk_src(hal->dev, sel);
|
||||
i2s_ll_set_rx_clk_src(hal->dev, sel);
|
||||
}
|
||||
|
||||
void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor)
|
||||
{
|
||||
i2s_clk_cal_t clk_set = {0};
|
||||
i2s_ll_clk_cal(sclk, fbck, factor, &clk_set);
|
||||
i2s_ll_set_tx_clk(hal->dev, &clk_set);
|
||||
}
|
||||
|
||||
void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor)
|
||||
{
|
||||
i2s_clk_cal_t clk_set = {0};
|
||||
i2s_ll_clk_cal(sclk, fbck, factor, &clk_set);
|
||||
i2s_ll_set_rx_clk(hal->dev, &clk_set);
|
||||
}
|
||||
|
||||
void i2s_hal_set_rx_eof_num(i2s_hal_context_t *hal, uint32_t eof_byte)
|
||||
{
|
||||
i2s_ll_set_rx_eof_num(hal->dev, eof_byte);
|
||||
}
|
||||
|
||||
void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, 0); //TX master
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
|
||||
}
|
||||
|
||||
void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
void i2s_hal_tx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg)
|
||||
{
|
||||
i2s_ll_tx_pcm_cfg(hal->dev, cfg);
|
||||
}
|
||||
|
||||
void i2s_hal_rx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg)
|
||||
{
|
||||
i2s_ll_rx_pcm_cfg(hal->dev, cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2s_hal_enable_sig_loopback(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_loop_back_ena(hal->dev, 1);
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
void i2s_hal_set_tx_pdm_fpfs(i2s_hal_context_t *hal, int fp, int fs)
|
||||
{
|
||||
i2s_ll_set_tx_pdm_fpfs(hal->dev, fp, fs);
|
||||
}
|
||||
|
||||
void i2s_hal_get_tx_pdm_fpfs(i2s_hal_context_t *hal, int *fp, int *fs)
|
||||
{
|
||||
i2s_ll_get_tx_pdm_fpfs(hal->dev, (uint32_t *)fp, (uint32_t *)fs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
void i2s_hal_set_rx_pdm_dsr(i2s_hal_context_t *hal, i2s_pdm_dsr_t dsr)
|
||||
{
|
||||
i2s_ll_set_pdm_rx_dsr(hal->dev, dsr);
|
||||
}
|
||||
|
||||
void i2s_hal_get_rx_pdm_dsr(i2s_hal_context_t *hal, i2s_pdm_dsr_t *dsr)
|
||||
{
|
||||
i2s_ll_get_pdm_rx_dsr(hal->dev, dsr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num)
|
||||
{
|
||||
//Get hardware instance.
|
||||
hal->dev = I2S_LL_GET_HW(i2s_num);
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
hal->dma = &GDMA;
|
||||
if (i2s_num == 0) {
|
||||
hal->dma_ch = SOC_GDMA_I2S0_DMA_CHANNEL;
|
||||
hal->dma_peri_sel = SOC_GDMA_TRIG_PERIPH_I2S0;
|
||||
}
|
||||
#if SOC_I2S_NUM > 1
|
||||
if (i2s_num == 1) {
|
||||
hal->dma_ch = SOC_GDMA_I2S1_DMA_CHANNEL;
|
||||
hal->dma_peri_sel = SOC_GDMA_TRIG_PERIPH_I2S1;
|
||||
}
|
||||
#endif
|
||||
gdma_ll_enable_m2m_mode(hal->dma, hal->dma_ch, false);
|
||||
#endif
|
||||
i2s_ll_general_init(hal->dev);
|
||||
}
|
||||
|
||||
static void i2s_hal_format_config(i2s_hal_context_t *hal, i2s_mode_t i2s_mode, i2s_comm_format_t format, i2s_slot_channel_cfg_t slot_bit_cfg, i2s_slot_bits_cfg_t slot_ch_cfg)
|
||||
{
|
||||
int active_slot_num = slot_ch_cfg & 0xffff;
|
||||
#if !SOC_I2S_SUPPORTS_TDM
|
||||
switch (format) {
|
||||
case I2S_COMM_FORMAT_STAND_MSB:
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_format_msb_align(hal->dev);
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_format_msb_align(hal->dev);
|
||||
}
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pcm_long(hal->dev);
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_pcm_long(hal->dev);
|
||||
}
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pcm_short(hal->dev);
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_pcm_short(hal->dev);
|
||||
}
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pcm_long(hal->dev);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_pcm_long(hal->dev);
|
||||
}
|
||||
break;
|
||||
default: //I2S_COMM_FORMAT_STAND_I2S
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_format_philip(hal->dev);
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_format_philip(hal->dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (active_slot_num == I2S_CHANNEL_MONO) {
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_tx_mono_mode_ena(hal->dev, active_slot_num == I2S_CHANNEL_MONO);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_mono_mode_ena(hal->dev, active_slot_num == I2S_CHANNEL_MONO);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int data_bits = slot_bit_cfg & 0xffff;
|
||||
int slot_bits = ((slot_bit_cfg >> SLOT_BIT_SHIFT) == I2S_BITS_PER_SLOT_SAMPLE_BIT_EQU) ? data_bits : slot_bit_cfg >> SLOT_BIT_SHIFT;
|
||||
int slot_num = ((slot_ch_cfg >> SLOT_CH_SHIFT) == 0 || (active_slot_num == I2S_CHANNEL_MONO)) ? 2 : (slot_ch_cfg >> SLOT_CH_SHIFT);
|
||||
bool msb_shift_en = false;
|
||||
int tdm_ws_width = 0;
|
||||
switch (format) {
|
||||
case I2S_COMM_FORMAT_STAND_MSB:
|
||||
msb_shift_en = false;
|
||||
tdm_ws_width = slot_num*slot_bits/2;
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
|
||||
msb_shift_en = false;
|
||||
tdm_ws_width = 1;
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
||||
msb_shift_en = false;
|
||||
tdm_ws_width = slot_bits;
|
||||
break;
|
||||
default: //I2S_COMM_FORMAT_STAND_I2S
|
||||
msb_shift_en = true;
|
||||
tdm_ws_width = slot_num*slot_bits/2;
|
||||
break;
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_tx_msb_shift_enable(hal->dev, msb_shift_en);
|
||||
i2s_ll_set_tx_tdm_ws_width(hal->dev, tdm_ws_width);
|
||||
i2s_ll_set_tx_half_sample_bit(hal->dev, slot_num*slot_bits/2);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_msb_shift_enable(hal->dev, msb_shift_en);
|
||||
i2s_ll_set_rx_tdm_ws_width(hal->dev, tdm_ws_width);
|
||||
i2s_ll_set_rx_half_sample_bit(hal->dev, slot_num*slot_bits/2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config)
|
||||
void i2s_hal_samples_config(i2s_hal_context_t *hal, i2s_mode_t i2s_mode, i2s_comm_format_t communication_format, i2s_slot_channel_cfg_t slot_bit_cfg, i2s_slot_bits_cfg_t slot_ch_cfg)
|
||||
{
|
||||
//reset i2s
|
||||
i2s_ll_reset_tx(hal->dev);
|
||||
i2s_ll_reset_rx(hal->dev);
|
||||
|
||||
//reset dma
|
||||
i2s_ll_reset_dma_in(hal->dev);
|
||||
i2s_ll_reset_dma_out(hal->dev);
|
||||
|
||||
i2s_ll_enable_dma(hal->dev);
|
||||
|
||||
i2s_ll_set_lcd_en(hal->dev, 0);
|
||||
i2s_ll_set_camera_en(hal->dev, 0);
|
||||
|
||||
i2s_ll_set_dscr_en(hal->dev, 0);
|
||||
|
||||
i2s_ll_set_tx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left
|
||||
i2s_ll_set_tx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel
|
||||
i2s_ll_set_tx_mono(hal->dev, 0);
|
||||
|
||||
i2s_ll_set_rx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left
|
||||
i2s_ll_set_rx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel
|
||||
i2s_ll_set_rx_mono(hal->dev, 0);
|
||||
|
||||
i2s_ll_set_dscr_en(hal->dev, 1); //connect dma to fifo
|
||||
|
||||
i2s_ll_stop_tx(hal->dev);
|
||||
i2s_ll_stop_rx(hal->dev);
|
||||
int active_slot_num = slot_ch_cfg & 0xffff;
|
||||
int data_bits = slot_bit_cfg & 0xffff;
|
||||
int slot_bits = ((slot_bit_cfg >> SLOT_BIT_SHIFT) == I2S_BITS_PER_SLOT_SAMPLE_BIT_EQU) ? data_bits : slot_bit_cfg >> SLOT_BIT_SHIFT;
|
||||
int slot_num = ((slot_ch_cfg >> SLOT_CH_SHIFT) == 0 || (active_slot_num == I2S_CHANNEL_MONO)) ? 2 : (slot_ch_cfg >> SLOT_CH_SHIFT);
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_slot_mun(hal->dev, slot_num);
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_slot_mun(hal->dev, slot_num);
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
}
|
||||
#else
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
}
|
||||
#endif
|
||||
//I2S standards config: Philip, MSB or PCM, Only I2S mode should do this configuration.
|
||||
if ((i2s_mode & (~(I2S_MODE_I2S))) == 0) {
|
||||
i2s_hal_format_config(hal, i2s_mode, communication_format, slot_bit_cfg, slot_ch_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_param_t *i2s_config)
|
||||
{
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_msb_right(hal->dev, 0);
|
||||
i2s_ll_set_tx_right_first(hal->dev, 0);
|
||||
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, 0); // Master
|
||||
i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1);
|
||||
|
||||
i2s_ll_tx_gen_init(hal->dev);
|
||||
if (i2s_config->mode & I2S_MODE_SLAVE) {
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_msb_right(hal->dev, 0);
|
||||
i2s_ll_set_rx_right_first(hal->dev, 0);
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, 0); // Master
|
||||
i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1);
|
||||
|
||||
i2s_ll_rx_gen_init(hal->dev);
|
||||
if (i2s_config->mode & I2S_MODE_SLAVE) {
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
if (!(i2s_config->mode & I2S_MODE_PDM)) {
|
||||
i2s_ll_set_rx_pdm_en(hal->dev, 0);
|
||||
i2s_ll_set_tx_pdm_en(hal->dev, 0);
|
||||
} else {
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
i2s_ll_tx_pdm_cfg(hal->dev, I2S_TX_PDM_FP_DEF, i2s_config->sample_rate/100);
|
||||
}
|
||||
if(i2s_config->mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_pdm_cfg(hal->dev, I2S_RX_PDM_DSR_DEF);
|
||||
}
|
||||
// PDM mode have nothing to do with communication format configuration.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
|
||||
if (i2s_config->mode & I2S_MODE_DAC_BUILT_IN) {
|
||||
@@ -243,32 +304,54 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_ADC_BUILT_IN) {
|
||||
i2s_ll_build_in_adc_ena(hal->dev);
|
||||
i2s_ll_set_rx_chan_mod(hal->dev, 1);
|
||||
i2s_ll_set_rx_fifo_mod(hal->dev, 1);
|
||||
i2s_ll_set_rx_mono(hal->dev, 0);
|
||||
}
|
||||
// Buildin ADC and DAC have nothing to do with communication format configuration.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
i2s_hal_format_config(hal, i2s_config);
|
||||
}
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
if (!(i2s_config->mode & I2S_MODE_PDM)) {
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_pdm_en(hal->dev, false);
|
||||
}
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pdm_en(hal->dev, false);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
i2s_ll_tx_pdm_cfg(hal->dev, i2s_config->sample_rate);
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2s_hal_enable_master_mode(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, 0); //MASTER Slave
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
|
||||
}
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
if(i2s_config->mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_pdm_cfg(hal->dev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
|
||||
}
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_active_slot_mask(hal->dev, i2s_config->active_slot_mask);
|
||||
i2s_ll_tx_left_align_enable(hal->dev, i2s_config->left_align_en);
|
||||
i2s_ll_tx_big_endian_enable(hal->dev, i2s_config->big_edin_en);
|
||||
i2s_ll_tx_set_bit_order(hal->dev, i2s_config->bit_order_msb_en);
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_active_slot_mask(hal->dev, i2s_config->active_slot_mask);
|
||||
i2s_ll_rx_left_align_enable(hal->dev, i2s_config->left_align_en);
|
||||
i2s_ll_rx_big_endian_enable(hal->dev, i2s_config->big_edin_en);
|
||||
i2s_ll_rx_set_bit_order(hal->dev, i2s_config->bit_order_msb_en);
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num)
|
||||
{
|
||||
//Get hardware instance.
|
||||
hal->dev = I2S_LL_GET_HW(i2s_num);
|
||||
//Configure I2S slot number,sample bit.
|
||||
i2s_hal_samples_config(hal, i2s_config->mode, i2s_config->communication_format, i2s_config->slot_bits_cfg, i2s_config->slot_channel_cfg);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -25,8 +25,11 @@
|
||||
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/i2s_ll.h"
|
||||
#include "hal/i2s_types.h"
|
||||
#include "hal/i2s_ll.h"
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "hal/gdma_ll.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -37,162 +40,91 @@ extern "C" {
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_dev_t *dev;
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_dev_t *dma;
|
||||
int dma_ch;
|
||||
int dma_peri_sel;
|
||||
#endif
|
||||
uint32_t version;
|
||||
} i2s_hal_context_t;
|
||||
|
||||
/**
|
||||
* @brief Get I2S interrupt status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param status interrupt status
|
||||
*/
|
||||
#define i2s_hal_get_intr_status(hal, status) i2s_ll_get_intr_status((hal)->dev, status)
|
||||
|
||||
/**
|
||||
* @brief Clear I2S interrupt status
|
||||
* @brief Reset I2S TX channel
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param mask interrupt status mask
|
||||
*/
|
||||
#define i2s_hal_clear_intr_status(hal, mask) i2s_ll_clear_intr_status((hal)->dev, mask)
|
||||
void i2s_hal_reset_tx(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Get I2S out eof des address
|
||||
* @brief Reset I2S TX fifo
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr out eof des address
|
||||
*/
|
||||
#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_get_out_eof_des_addr((hal)->dev, addr)
|
||||
void i2s_hal_reset_tx_fifo(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Get I2S in eof des address
|
||||
* @brief Reset I2S RX channel
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr in eof des address
|
||||
*/
|
||||
#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_get_in_eof_des_addr((hal)->dev, addr)
|
||||
void i2s_hal_reset_rx(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Enable I2S rx interrupt
|
||||
* @brief Reset I2S RX fifo
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_enable_rx_intr(hal) i2s_ll_enable_rx_intr((hal)->dev)
|
||||
void i2s_hal_reset_rx_fifo(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Disable I2S rx interrupt
|
||||
* @brief Init the I2S hal. 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)
|
||||
*/
|
||||
#define i2s_hal_disable_rx_intr(hal) i2s_ll_disable_rx_intr((hal)->dev)
|
||||
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Disable I2S tx interrupt
|
||||
* @brief Configure I2S source clock
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param sel The source clock index
|
||||
*/
|
||||
#define i2s_hal_disable_tx_intr(hal) i2s_ll_disable_tx_intr((hal)->dev)
|
||||
void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel);
|
||||
|
||||
/**
|
||||
* @brief Enable I2S tx interrupt
|
||||
* @brief Configure communication format
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2s_mode I2S mode. Using the ored mask of I2S_MODE_MASTER, I2S_MODE_SLAVE, I2S_MODE_TX, I2S_MODE_RX
|
||||
* @param communication_format I2S communication format. Can be a value of `i2s_comm_format_t`.
|
||||
* @param slot_bit_cfg I2S slot bit configuration
|
||||
* @param slot_ch_cfg I2S slot channel configuration
|
||||
*/
|
||||
#define i2s_hal_enable_tx_intr(hal) i2s_ll_enable_tx_intr((hal)->dev)
|
||||
void i2s_hal_samples_config(i2s_hal_context_t *hal, i2s_mode_t i2s_mode, i2s_comm_format_t communication_format, i2s_slot_channel_cfg_t slot_bit_cfg, i2s_slot_bits_cfg_t slot_ch_cfg);
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx mode
|
||||
* @brief Config I2S param
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param ch i2s channel
|
||||
* @param bits bits per sample
|
||||
* @param i2s_config I2S paramater configuration structer, refer to `i2s_config_param_t`
|
||||
*/
|
||||
void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits);
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_param_t *i2s_config);
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx mode
|
||||
* @brief Enable I2S master full-duplex mode
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param ch i2s channel
|
||||
* @param bits bits per sample
|
||||
*/
|
||||
void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits);
|
||||
void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Set I2S out link address
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr out link address
|
||||
*/
|
||||
#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr)
|
||||
|
||||
/**
|
||||
* @brief Set I2S out link address
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr out link address
|
||||
*/
|
||||
#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr)
|
||||
|
||||
/**
|
||||
* @brief Set I2S out link address
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr out link address
|
||||
*/
|
||||
#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr)
|
||||
|
||||
/**
|
||||
* @brief Set I2S in link
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param rx_eof_num in link eof num
|
||||
* @param addr in link address
|
||||
*/
|
||||
void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t rx_eof_num, uint32_t addr);
|
||||
|
||||
/**
|
||||
* @brief Set I2S clk div
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param div_num i2s clkm div num
|
||||
* @param div_a i2s clkm div a
|
||||
* @param div_b i2s clkm div b
|
||||
* @param tx_bck_div tx bck div num
|
||||
* @param rx_bck_div rx bck div num
|
||||
*/
|
||||
void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div);
|
||||
|
||||
/**
|
||||
* @brief Set I2S clock sel
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param sel clock sel
|
||||
*/
|
||||
#define i2s_hal_set_clock_sel(hal, sel) i2s_ll_set_clk_sel((hal)->dev, sel)
|
||||
|
||||
/**
|
||||
* @brief Set I2S tx bits mod
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param bits bit width per sample.
|
||||
*/
|
||||
void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits);
|
||||
|
||||
/**
|
||||
* @brief Set I2S rx bits mod
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param bits bit width per sample.
|
||||
*/
|
||||
void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits);
|
||||
|
||||
/**
|
||||
* @brief Reset I2S TX & RX module, including DMA and FIFO
|
||||
* @brief Enable I2S slave full-duplex mode
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_reset(i2s_hal_context_t *hal);
|
||||
void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Start I2S tx
|
||||
@@ -223,76 +155,256 @@ void i2s_hal_stop_tx(i2s_hal_context_t *hal);
|
||||
void i2s_hal_stop_rx(i2s_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Config I2S param
|
||||
* @brief Set the received data length to trigger `in_suc_eof` interrupt.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2s_config I2S configurations - see i2s_config_t struct
|
||||
* @param eof_byte The byte length that trigger in_suc_eof interrupt.
|
||||
*/
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config);
|
||||
void i2s_hal_set_rx_eof_num(i2s_hal_context_t *hal, uint32_t eof_byte);
|
||||
|
||||
/**
|
||||
* @brief Enable I2S sig loopback
|
||||
* @brief Set I2S TX sample bit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param slot_bit I2S TX slot bit
|
||||
* @param data_bit The sample data bit lengh.
|
||||
*/
|
||||
#define i2s_hal_enable_sig_loopback(hal) i2s_ll_set_sig_loopback((hal)->dev, 1)
|
||||
void i2s_hal_set_tx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit);
|
||||
|
||||
/**
|
||||
* @brief Enable I2S master mode
|
||||
* @brief Set I2S RX sample bit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param slot_bit I2S RX slot bit
|
||||
* @param data_bit The sample data bit lengh.
|
||||
*/
|
||||
void i2s_hal_enable_master_mode(i2s_hal_context_t *hal);
|
||||
void i2s_hal_set_rx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit);
|
||||
|
||||
/**
|
||||
* @brief Enable I2S slave mode
|
||||
* @brief Configure I2S TX module clock devider
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param sclk I2S source clock freq
|
||||
* @param fbck I2S bck freq
|
||||
* @param factor bck factor, factor=sclk/fbck
|
||||
*/
|
||||
void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal);
|
||||
void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor);
|
||||
|
||||
/**
|
||||
* @brief Init the I2S hal and set the I2S to the default configuration. This function should be called first before other hal layer function is called
|
||||
* @brief Configure I2S RX module clock devider
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2s_num The uart port number, the max port number is (I2S_NUM_MAX -1)
|
||||
* @param sclk I2S source clock freq
|
||||
* @param fbck I2S bck freq
|
||||
* @param factor bck factor, factor=sclk/fbck
|
||||
*/
|
||||
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num);
|
||||
void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor);
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief Set I2S tx pdm
|
||||
* @brief Configure I2S TX PCM encoder or decoder.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param fp tx pdm fp
|
||||
* @param fs tx pdm fs
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_cfg_t`
|
||||
*/
|
||||
void i2s_hal_tx_pdm_cfg(i2s_hal_context_t *hal, uint32_t fp, uint32_t fs);
|
||||
void i2s_hal_tx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg);
|
||||
|
||||
/**
|
||||
* @brief Get I2S tx pdm
|
||||
* @brief Configure I2S RX PCM encoder or decoder.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param dsr rx pdm dsr
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_cfg_t`
|
||||
*/
|
||||
void i2s_hal_rx_pdm_cfg(i2s_hal_context_t *hal, uint32_t dsr);
|
||||
void i2s_hal_rx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get I2S tx pdm configuration
|
||||
* @brief Enable loopback mode
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param fp Pointer to receive tx PDM fp configuration
|
||||
* @param fs Pointer to receive tx PDM fs configuration
|
||||
*/
|
||||
void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, uint32_t *fp, uint32_t *fs);
|
||||
void i2s_hal_enable_sig_loopback(i2s_hal_context_t *hal);
|
||||
|
||||
#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
|
||||
*/
|
||||
void i2s_hal_set_tx_pdm_fpfs(i2s_hal_context_t *hal, int fp, int fs);
|
||||
|
||||
/**
|
||||
* @brief Get I2S rx pdm configuration
|
||||
* @brief Get I2S TX PDM configuration
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param dsr rx pdm dsr
|
||||
* @param fp Pointer to accept TX PDM fp paramater configuration
|
||||
* @param fs Pointer to accept TX PDM fs paramater configuration
|
||||
*/
|
||||
void i2s_hal_get_rx_pdm(i2s_hal_context_t *hal, uint32_t *dsr);
|
||||
void i2s_hal_get_tx_pdm_fpfs(i2s_hal_context_t *hal, int *fp, int *fs);
|
||||
#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
|
||||
*/
|
||||
void i2s_hal_set_rx_pdm_dsr(i2s_hal_context_t *hal, i2s_pdm_dsr_t dsr);
|
||||
|
||||
/**
|
||||
* @brief Get RX PDM downsample configuration
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param dsr Pointer to accept PDM downsample configuration
|
||||
*/
|
||||
void i2s_hal_get_rx_pdm_dsr(i2s_hal_context_t *hal, i2s_pdm_dsr_t *dsr);
|
||||
#endif
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
/**
|
||||
* @brief Enable I2S TX DMA
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_attach_tx_dma(hal) i2s_ll_dma_enable((hal)->dev,true)
|
||||
|
||||
/**
|
||||
* @brief Enable I2S RX DMA
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_attach_rx_dma(hal) i2s_ll_dma_enable((hal)->dev,true)
|
||||
|
||||
/**
|
||||
* @brief Get I2S interrupt status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param status Pointer to accept I2S interrupt status
|
||||
*/
|
||||
#define i2s_hal_get_intr_status(hal, status) i2s_ll_get_intr_status((hal)->dev, status)
|
||||
|
||||
/**
|
||||
* @brief Get I2S interrupt status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param mask Interrupt mask to be cleared.
|
||||
*/
|
||||
#define i2s_hal_clear_intr_status(hal, mask) i2s_ll_clear_intr_status((hal)->dev, mask)
|
||||
|
||||
/**
|
||||
* @brief Enable I2S RX interrupt
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_enable_rx_intr(hal) i2s_ll_enable_rx_intr((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Disable I2S RX interrupt
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_disable_rx_intr(hal) i2s_ll_disable_rx_intr((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Disable I2S TX interrupt
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_disable_tx_intr(hal) i2s_ll_disable_tx_intr((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Enable I2S TX interrupt
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_enable_tx_intr(hal) i2s_ll_enable_tx_intr((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Configure TX DMA descriptor address and start TX DMA
|
||||
*
|
||||
* @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_start_tx_link((hal)->dev, link_addr)
|
||||
|
||||
/**
|
||||
* @brief Configure RX DMA descriptor address and start RX DMA
|
||||
*
|
||||
* @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_start_rx_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_stop_out_link((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Stop RX DMA link
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_stop_rx_link(hal) i2s_ll_stop_in_link((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Reset RX DMA
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_reset_rxdma(hal) i2s_ll_reset_dma_in((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Reset TX DMA
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
#define i2s_hal_reset_txdma(hal) i2s_ll_reset_dma_out((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Get I2S out eof descriptor address
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr Pointer to accept out eof des address
|
||||
*/
|
||||
#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_get_out_eof_des_addr((hal)->dev, addr)
|
||||
|
||||
/**
|
||||
* @brief Get I2S in suc eof descriptor address
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param addr Pointer to accept in suc eof des address
|
||||
*/
|
||||
#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_get_in_eof_des_addr((hal)->dev, addr)
|
||||
#else
|
||||
#define i2s_hal_attach_tx_dma(hal) gdma_ll_tx_connect_to_periph((hal)->dma, (hal)->dma_ch, (hal)->dma_peri_sel)
|
||||
#define i2s_hal_attach_rx_dma(hal) gdma_ll_rx_connect_to_periph((hal)->dma, (hal)->dma_ch, (hal)->dma_peri_sel)
|
||||
#define i2s_hal_get_intr_status(hal, status) (*status = (gdma_ll_get_interrupt_status((hal)->dma, (hal)->dma_ch)))
|
||||
#define i2s_hal_clear_intr_status(hal, mask) gdma_ll_clear_interrupt_status((hal)->dma, (hal)->dma_ch, mask)
|
||||
#define i2s_hal_enable_rx_intr(hal) gdma_ll_enable_interrupt((hal)->dma, (hal)->dma_ch, I2S_INTR_IN_DSCR_ERR|I2S_INTR_IN_SUC_EOF, 1)
|
||||
#define i2s_hal_disable_rx_intr(hal) gdma_ll_enable_interrupt((hal)->dma, (hal)->dma_ch, I2S_INTR_IN_DSCR_ERR|I2S_INTR_IN_SUC_EOF, 0)
|
||||
#define i2s_hal_enable_tx_intr(hal) gdma_ll_enable_interrupt((hal)->dma, (hal)->dma_ch, I2S_INTR_OUT_DSCR_ERR|I2S_INTR_OUT_EOF, 1)
|
||||
#define i2s_hal_disable_tx_intr(hal) gdma_ll_enable_interrupt((hal)->dma, (hal)->dma_ch, I2S_INTR_OUT_DSCR_ERR|I2S_INTR_OUT_EOF, 0)
|
||||
#define i2s_hal_start_tx_link(hal, link_addr) do{\
|
||||
gdma_ll_tx_set_desc_addr((hal)->dma,(hal)->dma_ch,link_addr);\
|
||||
gdma_ll_tx_start((hal)->dma,(hal)->dma_ch);}while(0)
|
||||
#define i2s_hal_start_rx_link(hal, link_addr) do{\
|
||||
gdma_ll_rx_set_desc_addr((hal)->dma,(hal)->dma_ch,link_addr);\
|
||||
gdma_ll_rx_start((hal)->dma,(hal)->dma_ch);}while(0)
|
||||
|
||||
#define i2s_hal_stop_tx_link(hal) gdma_ll_tx_stop((hal)->dma,(hal)->dma_ch)
|
||||
#define i2s_hal_stop_rx_link(hal) gdma_ll_rx_stop((hal)->dma, (hal)->dma_ch)
|
||||
#define i2s_hal_reset_rxdma(hal) gdma_ll_rx_reset_channel((hal)->dma, (hal)->dma_ch)
|
||||
#define i2s_hal_reset_txdma(hal) gdma_ll_tx_reset_channel((hal)->dma, (hal)->dma_ch)
|
||||
#define i2s_hal_get_out_eof_des_addr(hal, addr) (*addr = (gdma_ll_tx_get_eof_desc_addr((hal)->dma, (hal)->dma_ch)))
|
||||
#define i2s_hal_get_in_eof_des_addr(hal, addr) (*addr = (gdma_ll_rx_get_success_eof_desc_addr((hal)->dma, (hal)->dma_ch)))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
@@ -39,12 +40,47 @@ typedef enum {
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< I2S bits per sample: 8-bits*/
|
||||
I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< I2S bits per sample: 16-bits*/
|
||||
I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< I2S bits per sample: 24-bits*/
|
||||
I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< I2S bits per sample: 32-bits*/
|
||||
I2S_BITS_PER_SAMPLE_8BIT = 8,
|
||||
I2S_BITS_PER_SAMPLE_16BIT = 16,
|
||||
I2S_BITS_PER_SAMPLE_24BIT = 24,
|
||||
I2S_BITS_PER_SAMPLE_32BIT = 32,
|
||||
} i2s_bits_per_sample_t;
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per slot.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_SLOT_8BIT = (8), /*!< slot bit 8*/
|
||||
I2S_BITS_PER_SLOT_16BIT = (16), /*!< slot bit 16*/
|
||||
I2S_BITS_PER_SLOT_24BIT = (24), /*!< slot bit 24*/
|
||||
I2S_BITS_PER_SLOT_32BIT = (32), /*!< slot bit 32*/
|
||||
I2S_BITS_PER_SLOT_SAMPLE_BIT_EQU = (0), /*!< slot bit equals to data bit*/
|
||||
} i2s_bits_per_slot_t;
|
||||
|
||||
#define SLOT_BIT_SHIFT (16) //slot bit shift
|
||||
#define SLOT_CH_SHIFT (16) //slot channel shift
|
||||
|
||||
/**
|
||||
* @brief I2S slot bit configuration paramater. The low 16bit is the audio_data_bit_width and the high 16bit is the slot_bit_width.
|
||||
* e.g.: If set to (I2S_BITS_PER_SLOT_24BIT << SLOT_BIT_SHIFT) | I2S_BITS_PER_SAMPLE_16BIT, the audio data bit is 16bit and the slot bit is 24bit.
|
||||
*
|
||||
*
|
||||
* @note: If the slot_bit_width is set to `I2S_BITS_PER_SLOT_SAMPLE_BIT_EQU`, then the slot_bit_width equals to audio_data_bit_width.
|
||||
*
|
||||
*/
|
||||
typedef uint32_t i2s_slot_bits_cfg_t; /*!< slot bit configuration*/
|
||||
|
||||
/**
|
||||
* @brief I2S slot channel configuration paramater. The low 16bit is the active_slot_number and the high 16bit is the total_slot_num.
|
||||
* The audio data only launch in active slot, otherwise, launch 0 or single data in inactive slot.
|
||||
* e.g.: If set to (4 << SLOT_CH_SHIFT) | 2, the active_slot_number is 2 and the total_slot_num 4.
|
||||
*
|
||||
* @note: If the total_slot_num is set to 0, then the total_slot_num equals to active_slot_number.
|
||||
*
|
||||
*/
|
||||
typedef uint32_t i2s_slot_channel_cfg_t; /*!< slot channel configuration*/
|
||||
|
||||
/**
|
||||
* @brief I2S channel.
|
||||
*
|
||||
@@ -54,25 +90,46 @@ typedef enum {
|
||||
I2S_CHANNEL_STEREO = 2 /*!< I2S 2 channel (stereo)*/
|
||||
} i2s_channel_t;
|
||||
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
/**
|
||||
* @brief Bit map of active slot.
|
||||
* For TX module, only the active slot send the audio data, the inactive slot send a constant(configurable).
|
||||
* For RX module, only receive the audio data in active slot, the data in inactive slot will be ignored.
|
||||
*
|
||||
* @note the bit map of active slot can not exceed (0x1<<total_slot_num).
|
||||
* e.g: active_slot_mask = (I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1), total_slot_num = 4, active_slot_number = 2.
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_TDM_ACTIVE_CH0 = (0x1 << 0),
|
||||
I2S_TDM_ACTIVE_CH1 = (0x1 << 1),
|
||||
I2S_TDM_ACTIVE_CH2 = (0x1 << 2),
|
||||
I2S_TDM_ACTIVE_CH3 = (0x1 << 3),
|
||||
I2S_TDM_ACTIVE_CH4 = (0x1 << 4),
|
||||
I2S_TDM_ACTIVE_CH5 = (0x1 << 5),
|
||||
I2S_TDM_ACTIVE_CH6 = (0x1 << 6),
|
||||
I2S_TDM_ACTIVE_CH7 = (0x1 << 7),
|
||||
I2S_TDM_ACTIVE_CH8 = (0x1 << 8),
|
||||
I2S_TDM_ACTIVE_CH9 = (0x1 << 9),
|
||||
I2S_TDM_ACTIVE_CH10 = (0x1 << 10),
|
||||
I2S_TDM_ACTIVE_CH11 = (0x1 << 11),
|
||||
I2S_TDM_ACTIVE_CH12 = (0x1 << 12),
|
||||
I2S_TDM_ACTIVE_CH13 = (0x1 << 13),
|
||||
I2S_TDM_ACTIVE_CH14 = (0x1 << 14),
|
||||
I2S_TDM_ACTIVE_CH15 = (0x1 << 15),
|
||||
} i2s_tdm_active_slot_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S communication standard format
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
// In order to keep compatibility, remain the old definitions and introduce new definitions,
|
||||
I2S_COMM_FORMAT_STAND_I2S = 0X01, /*!< I2S communication I2S Philips standard, data launch at second BCK*/
|
||||
I2S_COMM_FORMAT_STAND_MSB = 0X03, /*!< I2S communication MSB alignment standard, data launch at first BCK*/
|
||||
I2S_COMM_FORMAT_STAND_MSB = 0X02, /*!< I2S communication MSB alignment standard, data launch at first BCK*/
|
||||
I2S_COMM_FORMAT_STAND_PCM_SHORT = 0x04, /*!< PCM Short standard, also known as DSP mode. The period of synchronization signal (WS) is 1 bck cycle.*/
|
||||
I2S_COMM_FORMAT_STAND_PCM_LONG = 0x0C, /*!< PCM Long standard. The period of synchronization signal (WS) is channel_bit*bck cycles.*/
|
||||
I2S_COMM_FORMAT_STAND_MAX, /*!< standard max*/
|
||||
|
||||
//old definition will be removed in the future.
|
||||
I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/
|
||||
I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/
|
||||
I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/
|
||||
I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/
|
||||
I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/
|
||||
I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/
|
||||
} i2s_comm_format_t;
|
||||
|
||||
/**
|
||||
@@ -87,10 +144,7 @@ typedef enum {
|
||||
} i2s_channel_fmt_t;
|
||||
|
||||
/**
|
||||
* @brief I2S Mode, defaut is I2S_MODE_MASTER | I2S_MODE_TX
|
||||
*
|
||||
* @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip.
|
||||
*
|
||||
* @brief I2S Mode
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_MODE_MASTER = 1, /*!< Master mode*/
|
||||
@@ -98,17 +152,18 @@ typedef enum {
|
||||
I2S_MODE_TX = 4, /*!< TX mode*/
|
||||
I2S_MODE_RX = 8, /*!< RX mode*/
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
//built-in DAC functions are only supported on I2S0 for ESP32 chip.
|
||||
I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
|
||||
I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
I2S_MODE_PDM = 64, /*!< PDM mode*/
|
||||
//PDM functions are only supported on I2S0.
|
||||
I2S_MODE_PDM = 64, /*!< I2S PDM mode*/
|
||||
#endif
|
||||
} i2s_mode_t;
|
||||
|
||||
/**
|
||||
* @brief I2S source clock
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_CLK_D2CLK = 0, /*!< Clock from PLL_D2_CLK(160M)*/
|
||||
@@ -116,39 +171,31 @@ typedef enum {
|
||||
} i2s_clock_src_t;
|
||||
|
||||
/**
|
||||
* @brief I2S configuration parameters for i2s_param_config function
|
||||
* @brief I2S bit width per sample.
|
||||
*
|
||||
* @note: The chip of ESP32 and ESP32S2 only needs to initialize the fields out side the `SOC_I2S_SUPPORTS_TDM` macro.
|
||||
* The chip of ESP32-S3, ESP32-C3 and the later chip, all this fields should be initialized.
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_mode_t mode; /*!< I2S work mode*/
|
||||
int sample_rate; /*!< I2S sample rate*/
|
||||
i2s_bits_per_sample_t bits_per_sample; /*!< I2S bits per sample*/
|
||||
i2s_channel_fmt_t channel_format; /*!< I2S channel format */
|
||||
i2s_mode_t mode; /*!< I2S work mode, using ored mask of `i2s_mode_t`*/
|
||||
uint32_t sample_rate; /*!< I2S sample rate*/
|
||||
i2s_slot_bits_cfg_t slot_bits_cfg; /*!< slot bit configuration, low 16bit is the audio data bit; high 16bit is the slot bit, if set to 0, total slot bit equals to audio data bit*/
|
||||
i2s_channel_fmt_t channel_format; /*!< I2S channel format*/
|
||||
i2s_comm_format_t communication_format; /*!< I2S communication format */
|
||||
int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */
|
||||
int dma_buf_count; /*!< I2S DMA Buffer Count */
|
||||
int dma_buf_len; /*!< I2S DMA Buffer Length */
|
||||
bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */
|
||||
bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */
|
||||
int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value.*/
|
||||
} i2s_config_t;
|
||||
|
||||
/**
|
||||
* @brief I2S event types
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_EVENT_DMA_ERROR,
|
||||
I2S_EVENT_TX_DONE, /*!< I2S DMA finish sent 1 buffer*/
|
||||
I2S_EVENT_RX_DONE, /*!< I2S DMA finish received 1 buffer*/
|
||||
I2S_EVENT_MAX, /*!< I2S event max index*/
|
||||
} i2s_event_type_t;
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
i2s_slot_channel_cfg_t slot_channel_cfg; /*!< slot number configuration, low 16bit is the valid slot number; high 16bit is the total slot number, if set to 0, total slot number equals to valid slot number*/
|
||||
uint32_t active_slot_mask; /*!< active slot bit mask, using the ored mask of `i2s_tdm_active_slot_t`*/
|
||||
bool left_align_en; /*!< Set to enable left aligment*/
|
||||
bool big_edin_en; /*!< Set to enable big edin*/
|
||||
bool bit_order_msb_en; /*!< Set to enable msb order*/
|
||||
#endif
|
||||
} i2s_config_param_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
/**
|
||||
* @brief I2S DAC mode for i2s_set_dac_mode.
|
||||
*
|
||||
* @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip.
|
||||
* @note Built-in DAC functions are only supported on I2S0 for current ESP32 chip.
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_DAC_CHANNEL_DISABLE = 0, /*!< Disable I2S built-in DAC signals*/
|
||||
@@ -159,15 +206,6 @@ typedef enum {
|
||||
} i2s_dac_mode_t;
|
||||
#endif //SOC_I2S_SUPPORTS_ADC_DAC
|
||||
|
||||
/**
|
||||
* @brief Event structure used in I2S event queue
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_event_type_t type; /*!< I2S event type */
|
||||
size_t size; /*!< I2S data size for I2S_DATA event*/
|
||||
} i2s_event_t;
|
||||
|
||||
/**
|
||||
* @brief I2S pin number for i2s_set_pin
|
||||
*
|
||||
@@ -179,7 +217,21 @@ typedef struct {
|
||||
int data_in_num; /*!< DATA in pin*/
|
||||
} i2s_pin_config_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief A/U-law decompress or compress configuration.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_PCM_A_DECOMPRESS=0, /*!< A-law decompress*/
|
||||
I2S_PCM_A_COMPRESS, /*!< A-law compress*/
|
||||
I2S_PCM_U_DECOMPRESS, /*!< U-law decompress*/
|
||||
I2S_PCM_U_COMPRESS, /*!< U-law compress*/
|
||||
I2S_PCM_DISABLE, /*!< Disable A/U law decopress or compress*/
|
||||
} i2s_pcm_cfg_t;
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
/**
|
||||
* @brief I2S PDM RX downsample mode
|
||||
*/
|
||||
@@ -188,7 +240,9 @@ typedef enum {
|
||||
I2S_PDM_DSR_16S, /*!< downsampling number is 16 for PDM RX mode*/
|
||||
I2S_PDM_DSR_MAX,
|
||||
} i2s_pdm_dsr_t;
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
/**
|
||||
* @brief PDM PCM convter enable/disable.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user